Erros
Todo erro desta API vem no mesmo formato, com o mesmo conjunto de campos, seja qual for o endpoint ou a causa. Vale a pena tratar o código de erro programaticamente em vez da mensagem: a mensagem é para leitura humana e pode mudar sem aviso.
O envelope de erro
Toda resposta de erro vem envelopada em {"error": {...}}, nunca junto com data. O campo details traz contexto extra específico do código — por exemplo, o tempo de espera de um 429 — e pode vir vazio.
{
"error": {
"code": "INVALID_BODY",
"message": "Corpo da requisição inválido.",
"details": {}
}
}x-request-id
Toda resposta, de sucesso ou erro, traz o header x-request-id. Cite esse valor ao abrir um chamado de suporte: ele é o jeito mais rápido de localizar a requisição exata nos logs internos, sem precisar reconstruir o horário e os parâmetros da chamada.
Códigos de erro
Agrupados por status HTTP, na ordem em que a API os devolve com mais frequência dentro do grupo.
400
| Código | Quando acontece | Como resolver |
|---|---|---|
| INVALID_JSON | O corpo da requisição não é um JSON válido. | Envie JSON bem formado e o header content-type: application/json. |
| INVALID_PROFILE | Os dados de perfil do número não passaram na validação da Meta. | Confira tamanho e formato de cada campo do perfil antes de reenviar. |
| INVALID_TEMPLATE_NAME | O nome do template não segue o formato exigido pela Meta. | Use apenas letras minúsculas, números e underscore, sem espaços. |
| IDEMPOTENCY_KEY_INVALID | O header Idempotency-Key veio com um formato que a API não aceita. | Envie um valor não vazio, com até 255 caracteres, sem espaços nas pontas. |
| IDEMPOTENCY_KEY_REQUIRED | A requisição precisa do header Idempotency-Key e ele não foi enviado. | Inclua o header Idempotency-Key com um valor novo (um UUID serve bem) a cada operação distinta. |
| INVALID_API_KEY | Os dados enviados para criar ou atualizar uma chave de API não passaram na validação. | Confira nome, escopos e data de expiração da chave contra o schema documentado no recurso. |
| INVALID_BODY | O corpo da requisição não é um JSON válido ou não bate com o schema esperado pelo endpoint. | Valide o corpo contra o schema do endpoint antes de enviar e confirme o header Content-Type: application/json. |
| INVALID_CHANNEL | Os dados enviados para criar ou atualizar um canal não passaram na validação. | Revise os campos do canal (nome, número, configuração) contra o schema do recurso Canais. |
| INVALID_CURSOR | O parâmetro cursor de uma listagem paginada veio corrompido ou adulterado. | Use sempre o valor de cursor devolvido pela própria API na resposta anterior, sem editá-lo. |
| INVALID_EXPIRATION | A data de expiração enviada para uma chave de API não está no futuro. | Envie expires_at como uma data ISO 8601 posterior ao momento atual, ou omita para não expirar. |
| INVALID_MEDIA | O arquivo de mídia enviado está ausente, tem um tipo não suportado ou excede o tamanho máximo do tipo. | Confira o tipo MIME e o tamanho do arquivo contra os limites da página de Limites antes de enviar. |
| INVALID_MESSAGE | O corpo da mensagem não corresponde a nenhum tipo de mensagem WhatsApp suportado. | Revise o campo type e os campos específicos do tipo contra o schema de POST .../messages. |
| INVALID_QUERY | Os parâmetros de consulta (query string) de uma listagem não passaram na validação. | Confira nomes, tipos e valores permitidos dos parâmetros de consulta do endpoint. |
| INVALID_SCOPE | A criação de uma chave de API pediu um ou mais escopos que não existem. | Use apenas escopos da lista documentada na tabela de escopo por papel, em Autenticação. |
| INVALID_TEMPLATE | O corpo de envio de template não bate com o schema exigido pela Meta para templates aprovados. | Confira o nome, idioma e os parâmetros de componentes do template contra o que foi aprovado na Meta. |
| INVALID_WEBHOOK | A configuração enviada para criar ou atualizar um webhook (url, eventos, modo de payload) é inválida. | Revise url, event_types e payload_mode contra o schema do recurso Webhooks. |
| INVALID_WEBHOOK_EVENT | Um evento interno tentou ser enfileirado com um tipo que não está em WEBHOOK_EVENT_TYPES, ou com dados incompletos. | Isto normalmente não é causado pelo integrador — se aparecer, cite o x-request-id ao abrir suporte. |
| INVALID_WEBHOOK_PAYLOAD | O payload de um evento de webhook não pôde ser serializado em JSON. | Isto normalmente não é causado pelo integrador — se aparecer, cite o x-request-id ao abrir suporte. |
| WEBHOOK_DNS_FAILED | A URL do webhook não pôde ser resolvida por DNS no momento do cadastro. | Confirme que o domínio do endpoint resolve publicamente antes de cadastrar o webhook. |
| WEBHOOK_URL_NOT_ALLOWED | A URL do webhook usa um esquema, host ou faixa de IP que a política de destino bloqueia. | Use HTTPS, um host público e evite redes internas — veja a seção de bloqueios em Webhooks. |
401
| Código | Quando acontece | Como resolver |
|---|---|---|
| UNAUTHENTICATED | A rota exige uma sessão de administrador da plataforma e nenhuma sessão válida foi enviada. | Autentique-se no painel administrativo antes de chamar a rota. |
402
| Código | Quando acontece | Como resolver |
|---|---|---|
| ACTIVE_SUBSCRIPTION_REQUIRED | A organização não tem uma assinatura paga em estado ativo. | Contrate ou reative um plano em /painel/assinatura antes de repetir a operação. |
| SUBSCRIPTION_REQUIRED | A operação (enviar mensagem, criar webhook) exige assinatura e a organização está sem uma. | Contrate um plano em /painel/assinatura; o envio e a criação de webhook voltam a funcionar assim que a assinatura fica ativa. |
403
| Código | Quando acontece | Como resolver |
|---|---|---|
| FORBIDDEN | A sessão autenticada não tem permissão de administrador da plataforma para a rota. | Esta rota é restrita à equipe interna — não há ação possível do lado do integrador. |
| OWNER_REQUIRED | A operação de cobrança (contratar plano ou adicional) foi chamada por alguém que não é o proprietário da organização. | Peça para o proprietário da organização realizar a operação, ou delegue o papel de owner a quem for executar. |
| PLAN_QUOTA_EXCEEDED | A organização atingiu o limite de canais ou de webhooks do plano contratado. | Remova um recurso existente ou faça upgrade do plano em /painel/assinatura. |
| SESSION_REQUIRED | Um endpoint de gestão de chaves de API foi chamado com uma chave de API em vez de uma sessão do painel. | Gerencie chaves de API autenticado por sessão do painel; uma chave de API não pode criar ou revogar outras chaves. |
404
| Código | Quando acontece | Como resolver |
|---|---|---|
| META_RESOURCE_NOT_FOUND | O recurso pedido não existe na Meta ou não pertence a este canal. | Confirme o identificador e se ele foi criado sob o mesmo número. |
| NOT_FOUND | O identificador do recurso na URL não existe, não pertence à organização autenticada, ou o id não é um UUID válido. | Confirme o id do recurso e que ele pertence à organização da credencial em uso. |
| PHONE_NUMBER_NOT_FOUND | O fluxo de conexão pública não encontrou o número de telefone associado ao link. | Gere um novo link de conexão pública; o número pode ter sido desvinculado da conta da Meta. |
| CUSTOMER_NOT_FOUND | A organização pediu o portal de cobrança sem nunca ter iniciado uma cobrança. | Contrate um plano por POST /api/v1/subscription/checkout antes de abrir o portal. |
409
| Código | Quando acontece | Como resolver |
|---|---|---|
| SEND_RESULT_UNKNOWN | A Meta não confirmou se a mensagem foi aceita e o resultado ficou indeterminado. | Não reenvie às cegas: consulte os logs do canal para saber se a mensagem saiu antes de tentar de novo. |
| CHANNEL_CREDENTIAL_MISSING | O canal não tem uma credencial da Meta armazenada no momento de enviar a mensagem. | Reconecte o canal no painel para renovar a credencial antes de tentar enviar novamente. |
| CHANNEL_NOT_CONNECTED | A operação exige um canal conectado à Meta (com WABA associado) e o canal ainda não está. | Conclua a conexão do canal no painel antes de enviar mensagens ou consultar templates por ele. |
| EXTERNAL_ID_CONFLICT | O identificador externo enviado ao criar um canal já está em uso por outro canal da organização. | Use um identificador externo diferente, ou reutilize o canal existente em vez de criar um novo. |
| IDEMPOTENCY_KEY_REUSED | A mesma Idempotency-Key foi enviada de novo, mas com um corpo de requisição diferente do original. | Gere uma Idempotency-Key nova para cada corpo de requisição distinto; nunca reaproveite o valor com dados diferentes. |
| OPERATION_IN_PROGRESS | Já existe uma operação em andamento para a mesma Idempotency-Key, ainda não concluída. | Aguarde e repita a requisição depois — a resposta original é devolvida assim que a operação em curso terminar. |
| PHONE_ALREADY_CONNECTED | O número de telefone que o cliente final está tentando conectar já está vinculado a outro canal. | Desconecte o número do canal anterior antes de conectá-lo a um novo, ou use o canal já existente. |
| SUBSCRIPTION_ALREADY_EXISTS | A organização tentou contratar um plano enquanto já tem uma assinatura em aberto. | Cancele ou aguarde a resolução da assinatura existente antes de contratar uma nova. |
413
| Código | Quando acontece | Como resolver |
|---|---|---|
| MEDIA_TOO_LARGE | O arquivo enviado passa do limite aceito pela Meta para aquele tipo de mídia. | Comprima ou reduza o arquivo antes de reenviar. |
| PAYLOAD_TOO_LARGE | O corpo da requisição passa do limite aceito pela API. | Divida o envio em requisições menores. |
| MESSAGE_TOO_LARGE | O corpo da mensagem serializado excede 256 KiB, um limite do próprio CRPRO Hub, imposto antes de repassar a mensagem para a Meta. | Reduza o conteúdo da mensagem para caber no limite de 256 KiB por payload — veja a tabela de Limites. |
| WEBHOOK_PAYLOAD_TOO_LARGE | O payload serializado de um evento de webhook excede o tamanho máximo aceito para entrega. | Isto normalmente não é causado pelo integrador — se aparecer, cite o x-request-id ao abrir suporte. |
415
| Código | Quando acontece | Como resolver |
|---|---|---|
| UNSUPPORTED_MEDIA_TYPE | O content-type enviado não é aceito neste endpoint. | Use um dos tipos suportados pela Meta para o formato em questão. |
422
| Código | Quando acontece | Como resolver |
|---|---|---|
| PHONE_NUMBER_MISSING | A conta da Meta resolvida pelo link de conexão pública não tem número de telefone associado. | Verifique no gerenciador de negócios da Meta se a conta tem um número de telefone configurado, antes de gerar um novo link. |
429
| Código | Quando acontece | Como resolver |
|---|---|---|
| RATE_LIMITED | A requisição excedeu um dos limites de taxa da API — geral, de envio por canal, de teste de webhook ou de conexão pública. | Reduza a frequência de chamadas e recue antes de tentar de novo — veja a orientação de recuo em Limites. |
500
| Código | Quando acontece | Como resolver |
|---|---|---|
| INTERNAL_ERROR | Ocorreu um erro não previsto no processamento da requisição. | Tente novamente; se persistir, abra um chamado de suporte citando o header x-request-id da resposta. |
502
| Código | Quando acontece | Como resolver |
|---|---|---|
| META_RESPONSE_TOO_LARGE | A resposta da Meta veio acima do limite que o Hub aceita processar. | Reduza o intervalo ou a quantidade de itens pedidos e tente de novo. |
| STRIPE_CUSTOMER_FAILED | O provedor de cobrança (Stripe) recusou a criação do cliente ao contratar um plano. | Tente novamente; se persistir, contate o suporte citando o header x-request-id da resposta. |
| STRIPE_CHECKOUT_FAILED | O provedor de cobrança (Stripe) recusou a abertura da sessão de checkout. | Tente novamente; se persistir, contate o suporte citando o header x-request-id da resposta. |
| STRIPE_PORTAL_FAILED | O provedor de cobrança (Stripe) recusou a abertura do portal de cobrança. | Tente novamente; se persistir, contate o suporte citando o header x-request-id da resposta. |
| STRIPE_ADDON_FAILED | O provedor de cobrança (Stripe) recusou a alteração da quantidade de conexões adicionais. | Confira no portal de cobrança se o cartão da assinatura continua válido e tente novamente. |
| STRIPE_PREVIEW_FAILED | O provedor de cobrança (Stripe) não conseguiu calcular o valor proporcional da alteração. | Tente novamente; se persistir, contate o suporte citando o header x-request-id da resposta. |
| META_INVALID_RESPONSE | A Meta aceitou a chamada de envio, mas devolveu uma resposta sem o identificador da mensagem enviada. | Trate como falha de entrega e tente reenviar; se persistir, confirme o status do número no gerenciador de negócios da Meta. |
| META_SEND_FAILED | A Meta recusou o envio da mensagem (número inválido, template não aprovado, janela de atendimento fechada, entre outros). | Consulte o campo meta_code nos detalhes do erro e o motivo na documentação da Cloud API da Meta antes de reenviar. |
503
| Código | Quando acontece | Como resolver |
|---|---|---|
| SEND_ACCEPTED_PENDING_PERSISTENCE | A mensagem foi aceita pela Meta, mas o registro local ainda não foi gravado. | Não reenvie: o registro é reconciliado automaticamente. Consulte os logs do canal para confirmar. |
Códigos de contexto de requisição
Os códigos abaixo não nascem de um endpoint específico — eles vêm da camada de autenticação e contexto de requisição, comum a toda a API, e por isso ficam numa tabela separada.
400
| Código | Quando acontece | Como resolver |
|---|---|---|
| INVALID_FROM | O parâmetro from do filtro de logs veio com uma data que não pôde ser interpretada. | Envie from como uma data ISO 8601 válida, ou omita o parâmetro. |
| INVALID_TO | O parâmetro to do filtro de logs veio com uma data que não pôde ser interpretada. | Envie to como uma data ISO 8601 válida, ou omita o parâmetro. |
| ORGANIZATION_ID_OBRIGATORIO | O usuário autenticado por sessão pertence a mais de uma organização e a requisição não enviou o header x-organization-id. | Envie o header x-organization-id com o id da organização em que a operação deve acontecer. |
401
| Código | Quando acontece | Como resolver |
|---|---|---|
| NAO_AUTENTICADO | Nenhuma sessão de painel nem chave de API válida foi encontrada na requisição. | Envie o header Authorization: Bearer hub_pk_... ou autentique-se no painel antes de chamar a API. |
| CREDENCIAL_INVALIDA | O valor enviado no header Authorization não corresponde a nenhuma chave de API ativa. | Confira se a chave foi copiada por inteiro e se não foi revogada; gere uma nova em /painel/chaves se necessário. |
| CREDENCIAL_REVOGADA | A chave de API usada já foi revogada. | Crie uma nova chave em /painel/chaves; uma chave revogada não volta a funcionar. |
| CREDENCIAL_EXPIRADA | A chave de API usada passou da data de expiração configurada na criação. | Crie uma nova chave em /painel/chaves, com uma expiração mais longa ou sem expiração. |
403
| Código | Quando acontece | Como resolver |
|---|---|---|
| SCOPE_INSUFICIENTE | A credencial (chave de API, token de canal ou sessão) autenticou com sucesso, mas não tem o escopo exigido pelo endpoint. | Use uma credencial com o escopo necessário — veja a tabela de escopo por papel em Autenticação. |
| SCOPE_DELEGATION_FORBIDDEN | A criação de uma chave de API pediu um escopo que a credencial atual não possui. | Peça apenas escopos que a sessão que está criando a chave já tem — não é possível delegar um escopo que não se possui. |
| MEMBERSHIP_AUSENTE | O usuário autenticado por sessão não pertence a nenhuma organização. | Aceite um convite ou crie uma organização no painel antes de chamar a API. |
404
| Código | Quando acontece | Como resolver |
|---|---|---|
| RECURSO_NAO_ENCONTRADO | O header x-organization-id aponta para uma organização à qual o usuário não pertence, ou o recurso pedido é de outra organização. | Confira o id da organização e que o usuário é membro dela; o 404 é deliberado em vez de 403, para não confirmar a existência do recurso a quem não tem acesso. |
429
| Código | Quando acontece | Como resolver |
|---|---|---|
| RATE_LIMITED | A requisição excedeu o limite geral de 120 requisições por minuto por organização e credencial. | Reduza a frequência de chamadas e recue antes de tentar de novo — veja a orientação de recuo em Limites. |
INVALID_FROM e INVALID_TO, nesta última tabela, vêm do filtro de período em /api/v1/logs. Os demais códigos dessa tabela vêm de qualquer endpoint autenticado, antes mesmo da lógica específica do endpoint rodar.