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
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-historyEach 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
GET /api/v1/identity/repair-scan
POST /api/v1/identity/repairrepair-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.
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/identity/merge-history | List past merges into a customer |
GET | /api/v1/identity/merge-proposals | List suggested customer merges |
POST | /api/v1/identity/merge-proposals/{id}/decide | Merge, dismiss or snooze a suggested merge |
GET | /api/v1/identity/merge-proposals/{id}/preview | Preview what a suggested merge would move |
POST | /api/v1/identity/merge-proposals/scan | Re-run the suggested-merge proposer |
POST | /api/v1/identity/repair | Preview or apply identity repairs |
GET | /api/v1/identity/repair-scan | Audit 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.