Pular para o conteúdo principal

Errors

A API usa um formato uniforme de erro para todas as respostas não-2xx.


Formato

{
"code": "PHONE_NOT_FOUND",
"message": "Phone not found",
"details": { "phoneId": "5f7b2e1c-..." }
}
CampoTipoDescrição
codestringIdentificador estável da causa (use no seu código)
messagestringDescrição human-readable (em inglês ou português; não dependa do conteúdo)
detailsobject | undefinedContexto adicional (varia por erro)

HTTP status code segue convenções REST. Você pode confiar no code antes do message.

Erros de validação Zod retornam:

{
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{ "path": ["webhook", "secret"], "message": "String must contain at least 16 character(s)" }
]
}

Catálogo completo

4xx — erros do cliente

400 Bad Request

CodeOrigemDescrição
VALIDATION_ERRORZodBody/query/params não passou no schema
WABA_CREDENTIALS_REQUIREDPOST /v1/phonestype=WABA sem credentials
WABA_CREDS_INCOMPLETETemplatesPhone WABA sem wabaPhoneNumberId/accessToken/businessAccountId
WABA_CREDS_MISSINGTemplatesToken decryptado vazio
WABA_TOKEN_MISSINGVáriosToken WABA não decifrável
QR_NOT_APPLICABLEGET /:id/qrcodePhone não é BAILEYS
PAIRING_NOT_APPLICABLEPOST /:id/pairing-codePhone não é BAILEYS
LOOKUP_UNSUPPORTED_CHANNELPOST /v1/lookupPhone não é BAILEYS
MEDIA_NOT_AUDIOPOST /:id/transcribecontentType não é audio/*
MEDIA_NOT_IMAGEPOST /:id/ocrcontentType não é image/*
MISSING_PHONE_IDMedia uploadHeader X-Phone-Id ausente
RECORDING_EMPTYPOST /v1/calls/:id/recordingBody não é Buffer ou tamanho 0
INVALID_TOSendto malformado
INVALID_JIDBaileys sendJID inválido após normalização
INVALID_TOKENPOST /:id/rotate-tokenNovo token não passou na validação Meta
UNSUPPORTED_TYPESendtype não suportado no canal
EMPTY_BATCHLookup/BlockArray vazio
BATCH_TOO_LARGELookup/Block>100 itens
SCHEDULE_TOO_SOONPOST /v1/messages/scheduledscheduledAt <agora + 5s
FLOW_NOT_SYNCEDFlowsFlow ainda não tem metaFlowId

401 Unauthorized

CodeQuando
AUTH_MISSINGSem X-API-Key em endpoint protegido
AUTH_INVALIDKey inexistente
AUTH_REVOKEDKey revogada via POST /v1/admin/api-keys/:id/revoke
AUTH_EXPIREDexpiresAt passou

402 Payment Required

CodeQuando
ACCOUNT_SUSPENDEDAccount em dunning SUSPENDED (14+ dias atraso). Cliente precisa pagar (/v1/billing/invoices/:id/issue) ou contatar admin para reativar

403 Forbidden

CodeQuando
ACCOUNT_INACTIVEAccount CANCELLED ou outro status ≠ ACTIVE
ADMIN_FORBIDDENEndpoint /v1/admin/* sem X-Admin-Token válido

404 Not Found

CodeQuando
PHONE_NOT_FOUNDPhone inexistente, não é WABA quando exigido, ou de outra account
MESSAGE_NOT_FOUNDMessage UUID local inexistente
MESSAGE_KEY_NOT_FOUNDwhatsappMessageId fora do cache (TTL 7d) — operações react/edit/delete impossíveis
MEDIA_NOT_FOUNDMedia UUID inexistente
TEMPLATE_NOT_FOUNDTemplate inexistente
SCHEDULED_NOT_FOUNDScheduled message inexistente
IDENTITY_NOT_FOUNDKey não resolveu para nenhuma identidade no phone
TASK_NOT_FOUNDLookup task inexistente ou expirada
AGENT_NOT_FOUNDPhone sem AI Agent configurado
DOC_NOT_FOUNDKnowledge doc inexistente
CONVERSATION_NOT_FOUNDAgent conversation inexistente
FLOW_NOT_FOUNDFlow inexistente
GROUP_NOT_FOUNDWABA Group inexistente
CALL_NOT_FOUNDCall inexistente
INVOICE_NOT_FOUNDInvoice inexistente
DELIVERY_NOT_FOUNDWebhook delivery inexistente
RECORDING_NOT_FOUNDCall sem recording upload
TRANSCRIPTION_NOT_REQUESTEDVocê não chamou POST /transcribe antes do GET
OCR_NOT_REQUESTEDVocê não chamou POST /ocr antes do GET
ACCOUNT_NOT_FOUNDAdmin: account inexistente
PLAN_NOT_FOUNDAdmin: billing plan code inexistente
NO_PUBLIC_KEYFlow sem keypair gerado (não é data_exchange)

409 Conflict

CodeQuando
ALREADY_CONNECTEDGET /qrcode ou POST /pairing-code em phone já CONNECTED
ALREADY_DELIVEREDPOST /v1/events/:id/replay em delivery já entregue
PHONE_NOT_CONNECTEDSend/op em phone não CONNECTED
CONVERSATION_CLOSEDTentou release em conversation CLOSED
SCHEDULED_NOT_PENDINGPATCH/DELETE em scheduled com status ≠ PENDING
TEMPLATE_NOT_SUBMITTEDPATCH /templates/:id antes do metaTemplateId
GROUP_SUSPENDEDOperação em group suspended=true

410 Gone

CodeQuando
MEDIA_EXPIREDTTL 7d passou
MEDIA_DELETEDACK explícito já fez delete

425 Too Early

CodeQuando
QR_NOT_READYQR ainda não emitido pelo Worker — tente em 1-2s
PAIRING_NOT_READYPairing code ainda não gerado

429 Too Many Requests

CodeQuando
RATE_LIMITEDExcedeu 600 req/min (300 em /v1/messages). Header Retry-After indica espera
SCHEDULE_QUOTA_EXCEEDED>10.000 scheduled messages PENDING

5xx — erros do servidor

500 Internal Server Error

CodeQuando
INTERNAL_ERRORCatch-all para exceções não mapeadas (não exposto detalhe)
BAILEYS_NO_IDBaileys não retornou ID na mensagem enviada
FORM_DATA_MISSINGUpload multipart corrompido
IG_TOKEN_BADToken Instagram falhou validação
KEYPAIR_INVALIDGeração de keypair RSA falhou
META_NO_ID / META_NO_CALL_IDMeta retornou OK sem ID na resposta
OPENAI_KEY_DECRYPT_FAILEDKey OpenAI armazenada não decifra
WABA_TOKEN_INVALIDToken armazenado falhou decrypt

502 Bad Gateway

CodeQuando
AI_BAD_OUTPUTOpenAI retornou JSON inválido em endpoint que espera JSON estruturado

503 Service Unavailable

CodeQuando
ADMIN_DISABLEDServidor sem ADMIN_TOKEN configurado
ASAAS_NOT_CONFIGUREDServidor sem ASAAS_API_KEY
IG_NOT_CONFIGUREDServidor sem credenciais Instagram
META_APP_ID_MISSINGGET /waba/embedded-signup/config sem META_APP_ID
META_APP_NOT_CONFIGUREDPOST /waba/embedded-signup sem META_APP_ID/META_APP_SECRET

Erros transientes vs definitivos

Retry com backoff para:

  • 503/502/500
  • 425 QR_NOT_READY, 425 PAIRING_NOT_READY
  • 429 RATE_LIMITED (respeitando Retry-After)

NÃO retry para:

  • 4xx exceto os acima (corrige a request)
  • 402 ACCOUNT_SUSPENDED (até pagar)
  • 404/409/410 (semânticos, não vão mudar com retry)

Códigos Meta repassados

Algumas operações WABA propagam códigos Meta diretamente no message ou details. Os mais comuns:

Meta codeSignificado
131026Recipient not on WhatsApp
131047Re-engagement message — 24h window fechada, precisa template
131051Mensagem fora da janela 24h
131057Account spamming / restricted
132000-132099Template-related (rejected, paused, not approved)
133010Phone number not registered
133015Phone re-registration required
190Access token expirado
4 / 17 / 32Rate limit Meta (META_RATE_LIMIT em logs)

Quando estes aparecem no failedReason de messages_sent, ação típica:

  • Token expirado → POST /v1/phones/:id/rotate-token
  • Janela 24h → use template
  • Recipient not on WhatsApp → POST /v1/lookup antes (Baileys-only) ou aceite custo de FAILED

Códigos Instagram

IG codeSignificado
4 / 17Rate limit (IG_RATE_LIMIT)
190Token expirado — re-OAuth
100Parâmetro inválido (ex.: IGSID inexistente)

Boas práticas

  1. Code é estável; message não. Faça switch em code, nunca em message.
  2. Sempre logue code + details quando capturar — facilita troubleshooting.
  3. Implemente fallback para INTERNAL_ERROR — pode ser bug do gateway. Reporte com X-Request-Id (response header).
  4. Diferencie 402 de 4xx. ACCOUNT_SUSPENDED exige fluxo de cobrança UX, não pode ser tratado como "input ruim".