﻿# Guia do Contrato da API

## Quando usar este guia

Use este documento quando você vai integrar por backend próprio, webhook próprio ou qualquer camada HTTP que não depende de um provedor específico.

Hoje existem duas portas públicas:

- `GET /api/agents/manifest` para agentes descobrirem contratos e exemplos
- `POST /api/messages` para o contrato genérico novo
- `POST /api/whatsapp/message` para compatibilidade e fluxos explicitamente ligados a WhatsApp

Se você quer a versão mais simples:

- sua integração chama `GET /api/agents/manifest` uma vez para descobrir o contrato
- sua integração recebe a mensagem
- sua integração chama o ChatAgent
- sua integração pega `reply`
- sua integração manda `reply` de volta ao cliente

## Manifesto para agentes

```http
GET /api/agents/manifest
Authorization: Bearer SUA_API_KEY
```

Use esse endpoint quando um agente, backend generico ou orquestrador precisa saber como integrar sem ler todos os guias.

Ele retorna:

- endpoint recomendado
- endpoints disponiveis
- campos obrigatorios
- exemplos de payload
- codigos de erro esperados
- regra de memoria por `actor.id` e `conversation.id`

Esse endpoint nao consome creditos e nao altera dados.

## Endpoint genérico recomendado

```http
POST /api/messages
Authorization: Bearer SUA_API_KEY
Content-Type: application/json
```

Body:

```json
{
  "actor": {
    "id": "lead-42",
    "type": "lead",
    "name": "Maria"
  },
  "conversation": {
    "id": "site-chat:lead-42",
    "channel": "web"
  },
  "message": {
    "text": "Quero saber os horários"
  }
}
```

## Endpoint compatível para WhatsApp

```http
POST /api/whatsapp/message
Authorization: Bearer SUA_API_KEY
Content-Type: application/json
```

## Existem 2 modos

### Modo recomendado

Use a **API key do número**.

Nesse modo, o próprio token já decide:

- qual número está respondendo
- qual perfil vale
- qual contexto deve ser usado

Body:

```json
{
  "from": "5511999999999@s.whatsapp.net",
  "name": "Maria",
  "message": "Quero saber os horários"
}
```

### Modo compatível

Use a **API key geral do tenant**.

Nesse modo, você precisa mandar `number_id`.

Body:

```json
{
  "number_id": 12,
  "from": "5511999999999@s.whatsapp.net",
  "name": "Maria",
  "message": "Quero saber os horários"
}
```

## Campos obrigatórios

Sempre obrigatórios:

- `from`
- `message`

Obrigatório em caso específico:

- `number_id`, quando a chave usada for a API key geral do tenant

Opcional:

- `name`

## Exemplo de resposta

```json
{
  "reply": "Posso te ajudar com os horários. Qual unidade você procura?",
  "conversation_id": "site-chat:lead-42",
  "thread_id": "number:12:whatsapp:5511999999999@s.whatsapp.net",
  "channel": "whatsapp",
  "credits_remaining": 123,
  "elapsed": 4.2,
  "status": "answered"
}
```

## O que a resposta quer dizer

- `reply`: texto pronto para voltar ao cliente
- `conversation_id`: identificador público da conversa no contrato genérico
- `thread_id`: identificador da conversa para log e rastreio
- `channel`: canal da chamada
- `credits_remaining`: créditos restantes
- `elapsed`: tempo aproximado da resposta
- `status`: estado final da operação

## Como pensar no `from`

`from` não é um detalhe.

Ele precisa representar o mesmo contato de forma consistente.

Exemplos bons:

- JID estável
- telefone normalizado
- ID persistente do contato

Exemplos ruins:

- ID temporário do evento
- valor aleatório gerado a cada mensagem
- campo que muda conforme a tentativa ou a sessão

## Como pensar no `thread_id`

Hoje a conversa pública fica isolada por:

- número
- contato

Por isso o formato parece assim:

```text
number:12:whatsapp:5511999999999@s.whatsapp.net
```

Isso é bom porque o mesmo contato pode falar com dois números diferentes sem misturar memória.

## Códigos de status que você precisa tratar

### `200`

Deu certo. Use `reply`.

### `400`

Normalmente significa:

- body inválido
- faltou `from`
- faltou `message`
- faltou `number_id` quando a chave usada foi a do tenant

### `401`

A chave está ausente ou inválida.

### `402`

A conta está sem créditos.

### `429`

Houve excesso de chamadas em pouco tempo.

### `503`

O serviço ainda não está pronto para processar.

## Boas práticas

- use a API key do número sempre que puder
- só use a chave geral do tenant quando fizer sentido para o seu fluxo
- se a chave for a do tenant, envie `number_id` sem falhar
- guarde `thread_id` em log
- valide `reply` antes do envio final

## Exemplo de validação manual

Antes de integrar no seu sistema final, vale testar assim:

### Teste com chave do número

```bash
curl -X POST https://seu-dominio/api/whatsapp/message \
  -H "Authorization: Bearer SUA_API_KEY_DO_NUMERO" \
  -H "Content-Type: application/json" \
  -d '{"from":"5511999999999@s.whatsapp.net","name":"Maria","message":"Olá"}'
```

### Teste com chave geral do tenant

```bash
curl -X POST https://seu-dominio/api/whatsapp/message \
  -H "Authorization: Bearer SUA_API_KEY_GERAL" \
  -H "Content-Type: application/json" \
  -d '{"number_id":12,"from":"5511999999999@s.whatsapp.net","name":"Maria","message":"Olá"}'
```

## Erros clássicos

### 1. A integração usa a chave geral e esquece `number_id`

Resultado:

- erro `400`

### 2. O cliente recebe resposta, mas sem memória

Resultado:

- `from` está mudando

### 3. A API responde certo, mas o cliente não recebe nada

Resultado:

- sua integração não usou `reply`
- ou o envio final ao provedor falhou

## Checklist final

- [ ] escolhi o modo certo de autenticação
- [ ] se a chave for a do tenant, eu envio `number_id`
- [ ] `from` é estável
- [ ] `message` vai limpa
- [ ] `reply` volta para o cliente
- [ ] `thread_id` fica salvo no log
