> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pivolio.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pivolio.com/_mcp/server.

# How Pivolio works

Every event travels the same path. Understanding it makes the dashboard —
and the occasional delivery failure — much easier to reason about.

## The pipeline

```
1. Collect      SDK or HTTP ──▶ POST /track   (write key, dedupe, rate limit)
2. Enrich       identity resolution · attribution · PII hashing · geo · risk score
3. Dispatch     one delivery attempt per connected destination
4. Record       every event and every delivery outcome, for reporting
```

Stages 2–4 run asynchronously. The collector acknowledges your event as soon as
it is validated and queued, so a slow ad platform never slows down your site.

## 1. Collect

Your event hits `POST /track` (or `/batch`, `/pixel`, `/ingest/integration`)
authenticated by a **write key**. Three things happen before it's accepted:

* **Validation.** The event must carry `event_id`, `event_name`, `event_time` and
  `anonymous_id`. Malformed events are rejected at the edge with a `422`.
* **Deduplication.** `event_id` is an idempotency key. Re-sending the same
  `event_id` returns `{"ok": true, "duplicate": true}` and does no further work —
  which is what makes the SDK's retries safe.
* **Rate limiting.** Two separate budgets apply: one counts *requests* per IP, the
  other counts *events* per workspace.

## 2. Enrich

This is where an event becomes useful.

* **Identity resolution** matches the event against your identity graph using its
  anonymous ID, user ID, email, phone and click IDs. It either finds one person,
  finds none and creates one, or finds several and **merges them into the oldest**.
* **Click backfill** attaches earlier click IDs to conversions that arrived without
  one, within each platform's expiry window.
* **PII hashing** normalizes and SHA-256s email, phone, name and location before
  anything leaves your infrastructure. Raw PII is never sent to an ad platform.
* **Attribution** assigns the event a channel — click ID first, then UTM medium,
  then referrer inference.
* **Traffic quality** scores the event for bot and click-fraud signals.

See [Identity resolution](/documentation/core-concepts/identity-resolution) and
[Attribution](/documentation/core-concepts/attribution) for the details.

## 3. Dispatch

Each connected destination gets its own delivery attempt, independently. One
platform failing never blocks another.

Each attempt ends in one of five outcomes — `sent`, `skipped`, `retrying`,
`failed`, or `suppressed`. They mean quite different things, and
[Delivery statuses](/documentation/core-concepts/delivery-statuses) is worth reading before you
try to interpret a delivery report.

> **Note**
>
> Transient failures (timeouts, `5xx`, `429`) are retried automatically. Permanent
> ones (a `4xx` that isn't `429`, or a payload the platform rejects) are not — no
> amount of retrying fixes a malformed event or a revoked token.

## 4. Record

Every event and every delivery attempt is written to reporting storage regardless
of outcome. This is deliberate: reporting is a **best-effort side effect** of
delivery, never a gate on it. A conversion that already reached Meta is never
re-delivered because a metric failed to log.

It's also why an unsubscribed workspace still shows complete analytics — tracking
and reporting always run; only step 3 requires a plan.

## Where the pieces live

* The **SDK** runs in your users' browsers and handles collection, identity
  persistence, batching and retries. See [SDKs](/documentation/sd-ks/overview).
* The **dashboard** is where you connect destinations, inspect individual events
  in the Live Debugger, and read attribution and traffic-quality reports.
* The **API** is what both of those talk to. See the **API Reference** tab.