# Messaging Service API

Documentação do contrato implantado. O CRM deve consumir esta API no backend;
tokens internos nunca devem ser enviados ao frontend.

## Endereços

- público: `https://messaging.driveparts.virtuaserver.com.br`;
- rede Docker: `http://messaging-api:8080`;
- WAHA e rotas `/internal/*` permanecem privados.

## Autenticação e tenant

Todas as rotas `/v1/*` exigem os headers:

```text
x-internal-token: <credencial do CRM>
x-store-id: <identificador da loja>
```

O `store_id` vem exclusivamente do header autenticado. Toda leitura e mutação
de conta ou mensagem aplica esse tenant. Credencial ausente ou inválida retorna
`401`; tenant ausente ou inválido retorna `400`.

## Health e ajuda

### `GET /help`

Retorna este documento em `text/markdown`. Não exige autenticação.

### `GET /health/live`

Confirma que o processo HTTP está vivo e informa a revisão da imagem.

### `GET /health/ready`

Retorna `200` quando MongoDB e os dois clientes Redis estão acessíveis; caso
contrário retorna `503`.

## Contas e números

### `POST /v1/accounts`

Reserva atomicamente o worker WAHA saudável com menor carga e enfileira a
criação da sessão sem iniciá-la.

```json
{
  "display_name": "WhatsApp Comercial",
  "provider": "waha"
}
```

`provider` é opcional e atualmente aceita apenas `waha`. Retorna `202` com a
conta e seu UUID.

### `GET /v1/accounts/{account_id}`

Retorna a conta pertencente ao tenant autenticado.

### `POST /v1/accounts/{account_id}/connect`

Enfileira o início da sessão. Retorna `202`; o processamento é assíncrono.

### `POST /v1/accounts/{account_id}/disconnect`

Para a sessão, preservando credenciais e histórico para reconexão. Retorna
`202`; não remove permanentemente o número.

### `GET /v1/accounts/{account_id}/status`

Consulta o provider e sincroniza o estado. Estados usuais: `provisioning`,
`connecting`, `qr_required`, `connected`, `disconnecting`, `disconnected`,
`degraded` e `failed`.

### `GET /v1/accounts/{account_id}/qr`

Retorna o QR Code da sessão em `{ "value": "..." }` quando o provider o
disponibiliza.

### `DELETE /v1/accounts/{account_id}` — ainda não disponível

A remoção permanente será implementada como desprovisionamento assíncrono,
preservando histórico/auditoria, removendo a sessão no provider e liberando a
capacidade do worker. Até lá, use `disconnect`.

## Mensagens

### `POST /v1/accounts/{account_id}/messages`

Enfileira texto com idempotência por `client_message_id` dentro do tenant e da
conta.

```json
{
  "conversation_id": "5511999999999@c.us",
  "client_message_id": "pedido-123-mensagem-1",
  "text": "Olá!"
}
```

Retorna `202` quando cria a mensagem e `200` quando a mesma chave idempotente já
existe.

### `POST /v1/accounts/{account_id}/media`

Enfileira imagem, documento ou áudio.

```json
{
  "conversation_id": "5511999999999@c.us",
  "client_message_id": "pedido-123-anexo-1",
  "kind": "document",
  "media_url": "https://driveparts.com.br/arquivo.pdf",
  "mimetype": "application/pdf",
  "filename": "arquivo.pdf",
  "caption": "Documento"
}
```

`kind` aceita `image`, `document` ou `audio`. Downloads aplicam allowlist de
host, proteção SSRF, timeout, limite de tamanho e zero redirects.

## Rotas exclusivamente internas

Estas rotas não são encaminhadas pelo proxy público.

### `PUT /internal/workers/{worker_id}`

Registra ou atualiza um worker. Exige `x-admin-token`.

### `GET /internal/metrics`

Métricas Prometheus. Exige `x-admin-token`.

### `POST /internal/webhooks/waha/{worker_id}`

Recebe eventos privados do WAHA. Exige assinatura HMAC válida nos headers
`x-webhook-hmac` e `x-webhook-hmac-algorithm`.

## Respostas de erro

- `400`: payload, parâmetro ou tenant inválido;
- `401`: token ou assinatura ausente/inválida;
- `404`: conta/recurso não encontrado dentro do tenant;
- `409`: conflito de estado;
- `502`: rejeição permanente do provider;
- `503`: dependência/capacidade indisponível ou falha transitória;
- `500`: falha interna sem exposição de detalhes sensíveis.
