# Erros, limites e boas práticas

## Formato dos erros

Todo erro volta assim:

```json
{
  "error": "validation_failed",
  "message": "Algum campo veio errado. `details` diz qual e por quê.",
  "details": { "name": ["Required"] },
  "request_id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677"
}
```

- `error` é o código estável: é nele que o seu sistema decide o que fazer.
- `message` explica, no idioma do cabeçalho `Accept-Language` (português, inglês ou espanhol; inglês se não vier).
- `request_id` identifica a chamada: cite-o ao falar com o suporte. Você pode mandar o seu em `X-Request-Id`.

| HTTP | Código | O que fazer |
|---|---|---|
| 401 | `unauthorized` | Falta a chave. Envie Authorization: Bearer <chave>. |
| 401 | `api_key_invalid` | Chave inválida ou revogada. Confira a chave ou crie outra em Configurações › API. |
| 401 | `api_key_expired` | A chave passou da validade. Crie outra em Configurações › API. |
| 403 | `api_key_address_not_allowed` | Esta chave não aceita chamadas deste endereço IP. Inclua o endereço na chave. |
| 403 | `insufficient_scope` | A chave não tem o escopo desta chamada. `details.required` diz quais servem. |
| 403 | `not_available_to_api_keys` | Esta chamada não faz parte da API pública. |
| 403 | `not_available_to_test_keys` | Esta chamada não tem modo teste: use uma chave de produção. |
| 403 | `permission_denied` | A chave não pode fazer isto. |
| 403 | `integration_template_only` | Texto e arquivos pedem o escopo messages:send_text; sem ele, só modelos aprovados. |
| 404 | `not_found` | Não encontrado. |
| 404 | `campaign_not_found` | Campanha não encontrada nesta empresa. |
| 404 | `contact_not_found` | Contato não encontrado nesta empresa. |
| 422 | `validation_failed` | Algum campo veio errado. `details` diz qual e por quê. |
| 409 | `campaign_not_editable` | A campanha já saiu do rascunho; só um rascunho pode ser editado ou disparado. |
| 409 | `template_not_approved` | O modelo ainda não foi aprovado pela Meta. Espere a aprovação ou escolha outro. |
| 409 | `campaign_audience_empty` | Ninguém do público pode receber a campanha. Veja os motivos na prévia do público. |
| 409 | `contact_exists` | Já existe um contato com este telefone. `details.contactId` diz qual. |
| 409 | `window_closed` | A janela de 24 horas está fechada: só um modelo aprovado pode iniciar a conversa. |
| 409 | `idempotency_key_reused` | Esta Idempotency-Key já foi usada com outro pedido. Use uma chave nova por pedido. |
| 409 | `idempotency_in_progress` | O primeiro pedido com esta Idempotency-Key ainda está em andamento. Tente em instantes. |
| 429 | `rate_limited` | Limite de 600 chamadas por minuto. Espere os segundos de Retry-After. |
| 500 | `internal_error` | Erro do nosso lado. Já fomos avisados; tente de novo com o mesmo request_id se persistir. |

## Limite de chamadas

Cada chave pode fazer 600 chamadas por minuto. Toda resposta diz onde você está:

```http
RateLimit-Limit: 600
RateLimit-Remaining: 587
RateLimit-Reset: 41
```

Passou do limite, a resposta é `429 rate_limited` com `Retry-After` (segundos). Espere esse tempo e tente de novo. O disparo de uma campanha não conta: quem envia é o DoneTalk, no ritmo que a Meta permite para o número.

## Repetir sem duplicar

Mande `Idempotency-Key` (até 200 letras, números, `_ . : -`) em criações e envios. Se a rede cair e você mandar de novo a mesma chamada com a mesma chave em até 24 horas, recebe a primeira resposta, com `Idempotent-Replayed: true`, e nada é feito duas vezes. A mesma chave com outro pedido volta `409 idempotency_key_reused`.

```http
Idempotency-Key: pedido-88213-campanha
```

## Paginação

- **Campanhas:** `limit` e `cursor`; a resposta traz `nextCursor` (null na última página).
- **Contatos:** `limit` e `before` (o `lastActivityAt` do último da página).
- **Destinatários de uma campanha:** `limit` e `offset`, ou `format=csv` para tudo.

## Versões

A v1 só ganha coisas novas: campos e chamadas a mais, nunca mudança no que já existe. Ignore campos que você não conhece. Se um dia for preciso mudar algo, nasce a v2, e a v1 continua por 12 meses, com aviso.
