> ## Documentation Index
> Fetch the complete documentation index at: https://docs.userkit.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Contatos

> Seus usuários: visitantes, identidades, atribuição de primeiro toque e merges feitos de propósito.

Um **contato** é um dos seus usuários. Ele começa como visitante anônimo e se torna
identificado quando uma identidade forte se liga a ele.

Contatos vivem dentro de um ambiente. Tudo abaixo é delimitado a um.

## Arestas de identidade

Um contato é alcançado por **arestas de identidade** — valores que resolvem até
ele. São três tipos:

| Tipo           | O que é                                     | Em caso de conflito              |
| -------------- | ------------------------------------------- | -------------------------------- |
| `external_id`  | Sua própria chave primária para essa pessoa | Nunca reaponta                   |
| `email`        | Um endereço                                 | Nunca reaponta                   |
| `anonymous_id` | Um id de dispositivo ou navegador           | **O último a reivindicar ganha** |

Essa diferença é o modelo inteiro.

`external_id` e `email` são *identificantes*: um valor que já pertence a outro
contato é uma **duplicata para unir à mão**, nunca um reapontamento silencioso.
Mover um e-mail de um contato para outro em silêncio é como uma pessoa acaba lendo
os dados de outra.

`anonymous_id` é o oposto: um cookie de dispositivo pertence a quem entrou por
último, então o último a reivindicar leva.

```bash theme={null}
curl -s $API/v1/contacts/{id} -H "Authorization: Bearer $UK_KEY"
```

```json theme={null}
{
  "contact": {
    "id": "3f9a…",
    "identified": true,
    "email_verified": false,
    "identities": [
      { "kind": "external_id",  "value": "user_8421",         "created_at": "…" },
      { "kind": "email",        "value": "grace@example.com", "created_at": "…" },
      { "kind": "anonymous_id", "value": "anon_2f9c1b",       "created_at": "…" }
    ]
  }
}
```

## Identify

`POST /v1/contacts` é cria-ou-atualiza. Envie o que o seu backend souber; pelo
menos uma entre `external_id`, `email` ou `anonymous_id` é obrigatória.

```bash theme={null}
curl -s $API/v1/contacts \
  -H "Authorization: Bearer $UK_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "external_id": "user_8421",
    "email": "grace@example.com",
    "anonymous_id": "anon_2f9c1b",
    "name": "Grace Hopper"
  }'
```

`201` quando o contato foi criado, `200` quando já existia — os dois com `created`
no corpo, para você não precisar ler o status.

A ordem de resolução é **`external_id`, depois `email`**: a sua própria chave
primária é a afirmação mais forte.

Nome e e-mail são *atributos*. Uma mudança é uma mudança, não uma pessoa nova — eles
são atualizados a cada chamada.

A **aresta de identidade** de e-mail só é criada quando está livre. Um conflito
deixa a aresta onde está e entrega a você uma duplicata para resolver.

<Note>
  Uma chamada que carrega só um `anonymous_id` é um avistamento de visitante, não uma
  identificação. `identified` continua `false`.
</Note>

### Absorvendo o visitante

Quando um `anonymous_id` chega junto com um tipo identificante, o contato-visitante
a que ele pertencia é absorvido pelo identificado — automaticamente, na mesma
transação.

É esse o momento em que a atribuição se paga: a campanha que trouxe alguém até a
sua landing page foi registrada na linha anônima, semanas antes de essa pessoa ter
um nome, e sobrevive até o contato que você agora conhece.

## Atribuição

Primeiro toque, capturado no visitante no primeiro carregamento e preservado
através de todo merge:

```json theme={null}
"attribution": {
  "utm_source": "newsletter",
  "utm_medium": "email",
  "utm_campaign": "july-launch",
  "utm_term": null,
  "utm_content": null,
  "referrer": "https://news.ycombinator.com/",
  "landing_page": "https://example.com/pricing"
}
```

Todos os campos são opcionais; vazio significa desconhecido. É *primeiro* toque,
não último — não se move depois de definido.

Envie em `/v1/boot` (da página, onde as UTMs de fato estão) ou em `/v1/contacts` a
partir do seu servidor.

## Identificado e verificado

Duas flags diferentes, e a diferença importa.

<ResponseField name="identified" type="boolean">
  Este contato é mais que um visitante — um `external_id` se ligou a ele, ou um
  e-mail foi comprovado.
</ResponseField>

<ResponseField name="email_verified" type="boolean">
  O **endereço** foi comprovado, por um link que chegou nele: verificação,
  redefinição de senha ou magic link.
</ResponseField>

Passar um e-mail para a API registra um atributo. Não comprova um. Qualquer um
digita um endereço; só uma mensagem chegando nele é evidência.

No modo federado isso é estrutural: um e-mail que chega por `/v1/boot` é guardado
na linha e nunca vira aresta de identidade, porque o HMAC comprova o `external_id` e
*apenas* o `external_id`. Um hash válido para o seu próprio id somado ao e-mail de
outra pessoa jamais pode tocar o contato dessa pessoa.

Existe ainda um terceiro `verified`, na
[sessão de contato](/pt-br/concepts/credentials#sessões-de-contato), que diz
que a identidade por trás *daquela sessão* foi comprovada. Parente, não igual.

## Merges

Não existe desfazer. Então merges acontecem de propósito.

```bash theme={null}
curl -s "$API/v1/organization/contacts/{source_id}/merge?environment=live" \
  -H "Authorization: Bearer $UK_SESSION" \
  -H "X-Organization-Id: org_4b1e…" \
  -H 'Content-Type: application/json' \
  -d '{ "target_id": "…" }'
```

A direção é deliberadamente explícita: **`{id}` na URL é a origem** — a linha que
desaparece — e `target_id` no corpo é a sobrevivente. Exige `customers:write`.

Todo merge grava um registro com quem fez, quando e o que se moveu:

```json theme={null}
{
  "merge": {
    "id": "…",
    "source_contact_id": "…",
    "target_contact_id": "…",
    "kind": "manual",
    "moved": { "...": "..." },
    "created_at": "…"
  }
}
```

Essa proveniência é o que torna um merge errado reparável à mão. Unir um contato a
ele mesmo responde `400`.

Merges automáticos acontecem — absorver um visitante no contato que acabou de
reivindicar o `anonymous_id` dele — e são registrados do mesmo jeito, com outro
`kind`.

## Lendo contatos

Duas superfícies, duas posturas:

<CodeGroup>
  ```bash Seu servidor — o ambiente da chave theme={null}
  curl -s "$API/v1/contacts?limit=50&offset=0" \
    -H "Authorization: Bearer $UK_KEY"
  ```

  ```bash O painel — uma visão explícita theme={null}
  curl -s "$API/v1/organization/contacts?environment=test&limit=50" \
    -H "Authorization: Bearer $UK_SESSION" \
    -H "X-Organization-Id: org_4b1e…"
  ```
</CodeGroup>

A paginação é `limit` (padrão 50, teto de 200) e `offset`. O teto é deliberado:
suficiente para uma tela, pequeno o bastante para ninguém baixar a audiência
inteira sem querer.
