Atribu
API Reference

Tracking & Server-Side Events

Tracking keys, the installer payloads, and the two ways a system posts an outcome it already knows about.

Two different jobs live here. Tracking keys and installers are how the browser tracker gets onto a site. POST /api/v1/events is how a system that already knows an outcome happened — an ERP, a POS, a back office — tells Atribu without a browser at all.

Tracking keys

Endpoint
POST /api/v1/tracking/keys
GET  /api/v1/tracking/keys

The POST is idempotent by natural key: a profile that already has an active key gets that key back rather than a second one. So an agent can call it unconditionally on every run without accumulating keys.

Installer payloads

Endpoints
GET /api/v1/tracking/snippet
GET /api/v1/tracking/installers/gtm
GET /api/v1/tracking/installers/shopify-pixel

snippet returns the raw <script> (optionally bundled with the Meta Pixel); the two installers return the payload a Google Tag Manager container or a Shopify Web Pixel expects. An agent that can edit the site puts the snippet in; one that cannot hands the payload to the person who can.

The by-hand versions of all three, with screenshots, are in Install the tracker.

Server-side outcome events

Endpoint
POST /api/v1/events

This is how a dealer's ERP posts a closed sale. Two rules matter more than the schema:

The idempotency key is required whenever the event carries money

Without one it defaults to a fresh UUID, and a retried sale becomes a second conversion. A payment posted twice is revenue counted twice, and every ROAS on the profile is wrong afterwards.

event_type is free text. What gives a name meaning is a conversion definition that lists it — there is no fixed sale_closed type to look up. Post checkout_completed and then define what it means; the definition is what decides whether it counts as cash, and whether it is attribution-eligible.

One customer paying for several people — subject_ref

A clinic often bills several patients (children, dependants) to one customer: the parent whose contact carried the ad conversation. By default Atribu counts one first payment per customer, so a second patient's first treatment would read as a repeat payment — not a new customer, not a Purchase at Meta, and credited only to the ad that acquired the parent.

Send properties.subject_ref — your own opaque id for who the payment is for — and each distinct subject_ref under one customer gets its own first payment. A payment without it behaves exactly as before.

Accepted shapes: a canonical UUID (8-4-4-4-12 hex — your internal patient uuid is ideal), or a short token of up to 32 letters, digits, _ and -.

Turn it on without inflating new customers. A subject counts as new only if every earlier payment of that customer carries a different subject_ref; an earlier untagged payment makes it a returning one. So before you start sending subject_ref on new payments, re-send the customer's historical payments with the same idempotency key plus their subject_ref — Atribu re-derives the first-payment flags on that update. A retry that omits subject_ref removes it from the stored payment again.

Two consequences of that rule, both deliberate:

  • A household with earlier payments from an integration keeps the per-customer rule. Payments that arrive from MercadoPago, Webpay, a CSV import or Shopify cannot carry a subject_ref, so they cannot be backfilled; a later patient of that household is never counted as a new customer. (At the time this shipped, no clinic customer had such a mixed history.)
  • An untagged payment after a tagged one is never a first payment, even within the 7 days that normally group a deposit with its balance — it may be the same patient again. Tag both payments to keep them grouped.
A second patient's first payment
{
  "event_name": "payment_received",
  "idempotency_key": "invoice_20931",
  "properties": { "value": 45000, "currency": "CLP", "subject_ref": "3f6c1e2a-8b7d-4c1e-9a55-0e2b7d9c4f11" },
  "user_traits": { "phone": "+56911112222" }
}

subject_ref is never personal data

Atribu rejects with 400 invalid_parameter a value that contains an @, 7 or more digits in a row once separators are removed (a RUT/RUN with or without check digit, even split by a letter, a phone number, a compact date), a date, a name, or a 32/40/64 character hex digest. Those checks catch mistakes; they cannot recognise every name (JuanPerez) or a hashed or encoded personal identifier, so subject_ref must be an opaque id — that is your obligation under the data-processing agreement. Atribu uses subject_ref only to decide first payments and count new customers — it is never sent to Meta, Google or TikTok, no API returns it, and it is erased with the customer.

POST /api/v1/payments/webpay is the same idea for Transbank Webpay, which has no OAuth connection to authorize: the payment is reported directly. See Webpay.

A CRM connection is not required

Readiness's crm_or_outcome_source_connected step is satisfied by outcome events arriving on this route. A system that posts its own outcomes needs no CRM and no browser.

MethodPathWhat it does
POST/api/v1/eventsIngest a server-side outcome event (e.g. a closed sale)
GET/api/v1/paymentsList payments, with the merchant actions applied to each
PUT/api/v1/payments/{payment_id}/installmentMark (or unmark) a payment as a later installment
PUT/api/v1/payments/{payment_id}/payerAssign who paid a payment
POST/api/v1/payments/{payment_id}/refundRecord a refund made outside the provider
DELETE/api/v1/payments/{payment_id}/refundUndo a manually recorded refund
POST/api/v1/payments/webpayReport a Webpay (Transbank) payment
GET/api/v1/tracking/custom-domainsList the profile's first-party tracking domains
POST/api/v1/tracking/custom-domainsRegister a first-party tracking domain
DELETE/api/v1/tracking/custom-domains/{id}Remove a first-party tracking domain
POST/api/v1/tracking/custom-domains/{id}/verifyRe-check a domain's DNS and store the verdict
GET/api/v1/tracking/eventsThe raw enriched-event feed
GET/api/v1/tracking/installers/gtmGet the Google Tag Manager installer payload
GET/api/v1/tracking/installers/shopify-pixelGet the Shopify Web Pixel installer payload
GET/api/v1/tracking/keysList the profile's active tracking keys
POST/api/v1/tracking/keysIssue a tracking key (idempotent)
DELETE/api/v1/tracking/keys/{id}Revoke a tracking key
GET/api/v1/tracking/opsWarehouse diagnostics for the profile
GET/api/v1/tracking/originWhere this profile's tracker collects
GET/api/v1/tracking/qualityIs this profile's tracking healthy?
GET/api/v1/tracking/replay-statusThe profile's most recent attribution replay
GET/api/v1/tracking/settingsRead the profile's tracker and enrichment settings
PATCH/api/v1/tracking/settingsUpdate the profile's tracker and enrichment settings
GET/api/v1/tracking/snippetGet the raw tracker snippet (with optional Meta Pixel bundle)
GET/api/v1/tracking/verificationThe latest install-verification attempt
POST/api/v1/tracking/verificationStart an install verification

Generated from openapi.json. The full request and response schema for every operation is in the OpenAPI document.

Next steps

On this page