Authentication
Toda chamada autenticada ao wpp-gateway exige o header X-API-Key. A key identifica a account proprietária — não há conceito de usuário individual na API pública.
X-API-Key: ak_live_QWj3aB...XzY9
Formato da API key
- Prefixo fixo:
ak_live_(até hoje só existe ambientelive; sandbox usariaak_test_no futuro). - Suffix: 32 caracteres
[A-Za-z0-9_-](base64url do hash). - Tamanho típico: 40-44 caracteres.
A key plaintext é mostrada apenas uma vez no momento da criação. O backend persiste só o hash SHA-256 — não há recuperação possível depois.
Autenticação alternativa para SSE
EventSource (Server-Sent Events nativo do browser) não permite custom headers. Para o endpoint /v1/events/stream, você pode passar a key via query string:
GET /v1/events/stream?api_key=ak_live_...
Use só em cenários de browser interno (dashboards) — nunca exponha em URLs públicas/logs.
Criação de keys (admin)
Endpoints de admin usam um token separado X-Admin-Token, configurado via env ADMIN_TOKEN. Eles vivem em /v1/admin/* e são acessados apenas pelo time de plataforma.
POST /v1/admin/accounts
Cria uma nova account.
Body:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | sim | Nome legível (2-120 chars) |
email | string | sim | Email único da account |
billingPlanCode | string | não | Code do plano (pay_as_you_go, flat, free_tier) |
wabaMarkupPct | number | não | Markup % sobre custo Meta (default 0, máx 100) |
Exemplo:
curl -X POST https://wpp.ogmma.com.br/v1/admin/accounts \
-H "X-Admin-Token: <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Ltda",
"email": "billing@acme.com",
"billingPlanCode": "pay_as_you_go",
"wabaMarkupPct": 20
}'
Response 201:
{
"id": "a1b2c3d4-...",
"name": "Acme Ltda",
"email": "billing@acme.com",
"status": "ACTIVE",
"billingPlanId": "...",
"wabaMarkupPct": "20",
"createdAt": "2026-05-21T10:00:00.000Z"
}
POST /v1/admin/api-keys
Emite uma key vinculada a uma account.
Body:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
accountId | UUID | sim | Account dona da key |
label | string | sim | Nome interno (1-120 chars) |
expiresAt | ISO datetime | não | Expiração (omita para keys eternas) |
Exemplo:
curl -X POST https://wpp.ogmma.com.br/v1/admin/api-keys \
-H "X-Admin-Token: <ADMIN_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"accountId": "a1b2c3d4-...",
"label": "Production backend"
}'
Response 201:
{
"id": "k1l2m3n4-...",
"accountId": "a1b2c3d4-...",
"label": "Production backend",
"prefix": "ak_live_QWj3",
"expiresAt": null,
"createdAt": "2026-05-21T10:01:00.000Z",
"key": "ak_live_QWj3...XzY9"
}
O campo
keyaparece só nesta resposta. Salve-o num secret manager imediatamente.
POST /v1/admin/api-keys/:id/revoke
Revoga uma key (revokedAt populado). Requests com keys revogadas recebem 401 AUTH_REVOKED.
curl -X POST https://wpp.ogmma.com.br/v1/admin/api-keys/k1l2m3n4-.../revoke \
-H "X-Admin-Token: <ADMIN_TOKEN>"
Rotação
Para rotacionar uma key:
- Emita uma key nova (
POST /v1/admin/api-keys). - Atualize seus secrets / variáveis de ambiente.
- Revogue a key antiga (
POST /v1/admin/api-keys/:id/revoke).
Não existe rotação "in-place" — keys são imutáveis (hash não muda). Esse design evita "qual era a key ativa há 5 min?" durante incidentes.
Escopos
Hoje a API trata todas as keys com escopo total (scopes: [] na model = sem restrição). O campo scopes em api_keys está preparado para granularidade futura (ex.: messages:send, phones:read).
Roadmap: scopes granulares (
messages.send,phones.read, etc) estão planejados. Hoje, qualquer key da account pode chamar qualquer endpoint dela.
Estado da account vs respostas de auth
A API valida em ordem:
- Key existe? Não →
401 AUTH_INVALID. - Key revogada? Sim →
401 AUTH_REVOKED. - Key expirada? Sim →
401 AUTH_EXPIRED. - Account
SUSPENDED? Sim →402 ACCOUNT_SUSPENDED(inadimplência ≥ 14 dias, ver Billing). - Account com qualquer status ≠ ACTIVE? Sim →
403 ACCOUNT_INACTIVE(CANCELLED).
Após a validação, o middleware popula req.account = { id, name } e atualiza lastUsedAt em background.
Errors
| HTTP | Code | Quando |
|---|---|---|
| 401 | AUTH_MISSING | Header X-API-Key ausente |
| 401 | AUTH_INVALID | Key inexistente |
| 401 | AUTH_REVOKED | Key foi revogada via admin |
| 401 | AUTH_EXPIRED | expiresAt passou |
| 402 | ACCOUNT_SUSPENDED | Account com fatura ≥ 14d em atraso |
| 403 | ACCOUNT_INACTIVE | Account CANCELLED |
| 403 | ADMIN_FORBIDDEN | Endpoints /v1/admin/* sem X-Admin-Token correto |
| 503 | ADMIN_DISABLED | Servidor sem ADMIN_TOKEN configurado |
Ver Errors para o catálogo completo.