Atribu
API Reference

Identity

Merge proposals, the repair scan, and the one rule that keeps a person from being split in two forever.

Atribu resolves an anonymous visitor into a known customer from the identifiers it sees: an anonymous_id, an email, a phone, a CRM contact id, a national id. When two customer profiles turn out to be the same person, they are merged.

Merging is destructive-adjacent — it moves conversions, touches and revenue from one profile onto another — so it is a review queue, not an automatic sweep.

The review queue

Endpoints
POST /api/v1/identity/merge-proposals/scan
GET  /api/v1/identity/merge-proposals
GET  /api/v1/identity/merge-proposals/{id}/preview
POST /api/v1/identity/merge-proposals/{id}/decide
GET  /api/v1/identity/merge-history

Each proposal is a pair of customer profiles a scan believes are the same person, with both sides' identity and the evidence for the match. preview shows exactly what a merge would move; decide accepts or rejects it.

Keyset paginated. Pass pagination.cursor to walk older pages; an unreadable cursor starts from the beginning rather than erroring. There is no total — the queue is being resolved while you walk it, so an offset page would shift under you. status_counts rides alongside data and describes the whole queue, ignoring the current page's filters.

The repair scan

Endpoints
GET  /api/v1/identity/repair-scan
POST /api/v1/identity/repair

repair-scan scores every non-merged customer profile: how many are missing a primary email or phone, how many duplicate-email/phone groups exist, and — per profile — what a backfill would write. Offset-paginated, because the underlying scan is a single pass.

`auto_repairable_count` counts backfills only

Merges left the bulk repair path and go through the proposal queue instead. auto_merge_count is reported for awareness and is not something POST /api/v1/identity/repair will act on.

Why a merge cannot be undone by re-scanning

A profile created from an identifier alone — a ghl_contact_id with no email, say — is an orphan the later PII event can never absorb, because the identifier upsert never re-points an existing mapping. That is why every ingestion path resolves identity from real PII where it has it and only reads the identity graph where it does not. The consequence for a consumer of this API: a merge proposal you reject stays rejected, and the two profiles keep accumulating separately.

MethodPathWhat it does
GET/api/v1/identity/merge-historyList past merges into a customer
GET/api/v1/identity/merge-proposalsList suggested customer merges
POST/api/v1/identity/merge-proposals/{id}/decideMerge, dismiss or snooze a suggested merge
GET/api/v1/identity/merge-proposals/{id}/previewPreview what a suggested merge would move
POST/api/v1/identity/merge-proposals/scanRe-run the suggested-merge proposer
POST/api/v1/identity/repairPreview or apply identity repairs
GET/api/v1/identity/repair-scanAudit customer profiles for missing or duplicated identifiers

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

Next steps

On this page