---
title: "Contatos"
slug: contacts
group: "Referência da API"
source: https://linkzap.orion.moe/developers/contacts
openapi: https://linkzap.orion.moe/openapi.json
---

# Contatos

A base de quem fala com você. O telefone é a identidade: criar duas vezes o mesmo número atualiza, não duplica.

## Listar e buscar

### `GET /api/v1/contacts`
Lista os contatos da organização, do mais recentemente atualizado para o mais antigo. Paginada. **Uma chave de canal vê todos os contatos da conta** — contato não pertence a canal.

**Parâmetros da URL**

| Campo | Tipo | Descrição |
| --- | --- | --- |
| `query` | texto | Busca por nome, telefone ou e-mail. |
| `phone` | texto | Acha o contato exato. Aceita qualquer formatação; 422 se não for um telefone válido. |
| `page` | inteiro | A partir de 1. Padrão 1. |
| `limit` | inteiro | De 1 a 200. Padrão 50. |

Pedido:

```bash
curl "https://linkzap.orion.moe/api/v1/contacts?phone=5592999990000" \
  -H "Authorization: Bearer lz_SUA_CHAVE"
```

Resposta:

```json
{
  "data": [
    {
      "id": "ctt_3c81...",
      "phone": "5592999990000",
      "name": "Maria Souza",
      "email": null,
      "fields": { "cpf": "000.000.000-00", "plano": "ouro" },
      "tags": ["cliente", "vip"],
      "optIn": true,
      "optInAt": "2026-09-20T11:02:00.000Z",
      "optOutAt": null,
      "source": "api",
      "createdAt": "2026-09-20T11:02:00.000Z",
      "updatedAt": "2026-09-21T09:40:12.000Z"
    }
  ],
  "page": 1,
  "limit": 50,
  "total": 1
}
```

`optIn` é derivado: só é `true` se existe um opt-in registrado e **nenhum** opt-out depois dele.

## Criar ou atualizar

### `POST /api/v1/contacts`
Cria pelo telefone (201) ou atualiza o que já existe (200). O campo `created` da resposta diz qual dos dois aconteceu.

**Corpo (JSON)**

| Campo | Tipo | Obrigatório | Descrição |
| --- | --- | --- | --- |
| `phone` | texto | obrigatório | DDI + DDD + número. |
| `name` | texto | — | Até 120 caracteres. |
| `email` | texto | — | Precisa ser um e-mail válido, ou string vazia para limpar. |
| `fields` | objeto | — | Campos próprios seus, texto de até 500 caracteres cada. Mesclam com os que já existem — mandar um campo não apaga os outros. Campo que ainda não existe na conta é criado como texto. Se o campo tem **tipo** (Configurações › Campos do contato), o valor é convertido para a forma do tipo — número `"1234.5"`, data `"2026-12-31"`, sim/não `"true"`/`"false"`, lista com o texto da opção — e a chamada devolve **422** quando ele não cabe (texto num campo de número, opção que não existe); nesse caso nada da chamada é gravado. O nome do campo não diferencia maiúsculas de minúsculas. |
| `tags` | lista | — | Até 20 nomes de etiqueta. As que não existem são criadas. Aplicar uma etiqueta pode **disparar um fluxo**, se houver um esperando por ela. |
| `optIn` | booleano | — | `true` registra o opt-in, `false` registra o opt-out. Ausente não mexe no que já estava. |

Pedido:

```bash
curl -X POST https://linkzap.orion.moe/api/v1/contacts \
  -H "Authorization: Bearer lz_SUA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "5592999990000",
    "name": "Maria Souza",
    "tags": ["lead-site"],
    "fields": { "origem": "formulario-contato" },
    "optIn": true
  }'
```

Resposta:

```json
{
  "data": {
    "id": "ctt_3c81...",
    "phone": "5592999990000",
    "name": "Maria Souza",
    "email": null,
    "fields": { "origem": "formulario-contato" },
    "tags": ["lead-site"],
    "optIn": true,
    "optInAt": "2026-09-21T09:40:12.000Z",
    "optOutAt": null,
    "source": "api",
    "createdAt": "2026-09-21T09:40:12.000Z",
    "updatedAt": "2026-09-21T09:40:12.000Z"
  },
  "created": true
}
```

> [!WARNING]
> **Opt-in tem consequência**
>
> É ele que libera o contato para sequências e campanhas. Marque `optIn: true` apenas quando a pessoa de fato autorizou — a caixa de seleção que ela marcou no seu formulário, o aceite no seu cadastro. Um opt-in inventado vira mensagem indesejada, e mensagem indesejada vira número bloqueado.

Criar um contato dispara o webhook `contact.created`; mudar o consentimento dispara `contact.opt_in` ou `contact.opt_out`; mudar nome, e-mail, campo ou etiqueta dispara `contact.updated`, com o que mudou em `changed`. Se o seu sistema também escuta esses eventos, lembre que a sua própria chamada os provoca.
