Lista contatos com dados de CRM. Filtros: ?search=&source_platform=&inbox_status=open&pipeline_stage_id=&crm_status=&is_ai_enabled=true&page=1&limit=50. Para incluir o resumo de cliques em links curtos, use &include=link_clicks. Para exportar a base inteira, use ?order_by=created_at e siga pagination.next_cursor no parâmetro &cursor=.
- include=link_clicks é opcional e acrescenta `link_clicks: { total, last_at }` em cada contato. A métrica conta apenas cliques humanos; preview automático do WhatsApp e bots ficam fora.
- `inbox_status=resolved` é a conversa encerrada; ela volta para `open` quando o cliente manda mensagem nova, quando um atendente assume ou quando sai uma campanha ou template para ele. Uma resposta nova do cliente após o encerramento volta sem responsável e com a IA da conversa desligada. Cada contato traz `last_closed_at` (quando a conversa foi encerrada pela última vez, ou null se nunca foi) e `last_close_reason_id` (o motivo escolhido, ou null). Os dois são somente leitura e continuam preenchidos depois que a conversa reabre.
- A listagem traz os mesmos campos de CRM do caminho interno, incluindo `custom_fields`, observação, CPF, RG, endereço, aniversário, estado, gênero, estado civil, profissão, cargo e organização. Na listagem, `custom_fields` mantém as chaves gravadas no contato (slugs).
- `pipeline_stage_id` (e `pipeline_stage`) é a etapa da negociação em foco do contato: entre as negociações com etapa, a ativa que entrou por último na etapa ou, sem nenhuma ativa, a fechada que entrou por último. Contato com várias negociações aparece numa etapa só, e o filtro `pipeline_stage_id=` compara com essa mesma etapa. Contato sem negociação com etapa vem com `pipeline_stage_id: null`.
- O endpoint retorna JSON com `Content-Type: application/json` e autentica com `Authorization: Bearer <token>`.
- Ordenação padrão (order_by=last_message_at): `last_message_at` decrescente, contatos sem mensagem por último, com desempate por `id` — a ordem entre páginas é estável. Como cada mensagem nova move o contato para o topo, a paginação por `page` pode repetir ou pular um contato que recebeu mensagem durante a leitura.
- Exportação completa (order_by=created_at): leitura sequencial por cursor, em `created_at` crescente com desempate por `id`, que não repete nem pula contatos. A primeira chamada vai sem `cursor`; cada resposta traz `pagination: { limit, total, next_cursor }`, e a próxima página se pede com `&cursor=<next_cursor>`. `next_cursor: null` indica o fim. `total` é a contagem com os mesmos filtros. O parâmetro `page` não é aceito nesse modo, e todos os filtros e o `include=link_clicks` continuam valendo.
- Rate limit na exportação: o padrão é de 60 requisições por minuto por chave (configurável por chave). Com limit=100, cada 6.000 contatos consomem 1 minuto de cota. Ao receber 429, aguarde e repita a chamada com o mesmo `next_cursor` — o cursor não expira.
Resposta (200)
{
"success": true,
"data": [
{
"id": "<uuid>",
"identifier": "5548999990000",
"phone": "5548999990000",
"email": "joao@exemplo.com.br",
"name": "João Silva",
"display_name": "João Silva",
"wa_push_name": "João S.",
"avatar_url": null,
"observation": "Veio da feira de negócios",
"custom_fields": {
"origem": "indicação"
},
"source_platform": "whatsapp",
"inbox_status": "open",
"priority": "normal",
"crm_status": "open",
"is_ai_enabled": true,
"is_archived": false,
"is_blocked": false,
"is_group": false,
"is_simulated": false,
"first_message_at": "2026-07-01T14:03:00.000Z",
"last_message_at": "2026-07-15T09:22:00.000Z",
"last_inbound_at": "2026-07-15T09:20:00.000Z",
"last_closed_at": null,
"last_close_reason_id": null,
"street": "Rua das Flores",
"street_number": "100",
"address_complement": null,
"neighborhood": "Centro",
"city": "Florianópolis",
"state": "SC",
"postal_code": "88010000",
"country": "BR",
"birthday": "1990-05-12",
"cpf": "99001122334",
"rg": "1234567",
"genero": "Masculino",
"estado_civil": "Casado",
"profissao": "Engenheiro",
"cargo": "Diretor",
"organization_id": "<uuid>",
"organization": {
"id": "<uuid>",
"name": "Empresa Exemplo",
"cnpj": "12345678000190",
"razao_social": "Empresa Exemplo Ltda.",
"enriched_at": null
},
"pipeline_stage_id": "<uuid>",
"assigned_to_member_id": "<uuid>",
"last_connection_id": "<uuid>",
"created_at": "2026-07-01T14:03:00.000Z",
"updated_at": "2026-07-15T09:22:00.000Z",
"pipeline_stage": {
"id": "<uuid>",
"name": "Novo",
"color": "#6366f1",
"display_order": 1
},
"tags": [
{
"id": "<uuid>",
"name": "VIP",
"color": "#6366f1"
}
]
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 320,
"total_pages": 7
}
}Erros
| Status | Código | Quando ocorre |
|---|---|---|
| 400 | INVALID_PARAMETER | order_by diferente de last_message_at/created_at; cursor sem order_by=created_at; page com order_by=created_at; ou cursor inválido. O campo `details` indica o parâmetro. |
Exemplo
curl -s -H "Authorization: Bearer <sua-key>" https://www.prosalab.com/api/v1/contacts