Erros e códigos
O que cada status quer dizer e como resolver.
Esta página é para quem trata as respostas da API no sistema que chama o TOPO, por exemplo o alerta de falha de um iFlow do SAP. Ela lista cada status, a mensagem que chega e o que fazer.
A forma do erro
Todo erro das rotas REST tem a mesma forma:
{ "success": false, "error": "Informe companyId ou cnpj." }erroré o motivo em português, para mostrar a quem opera a integração.codeaparece quando existe um código estável, por exemploIMPORTACAO_RECUSADAna recusa do balancete.
Trate o erro pelo status HTTP e pelo code. O texto de error pode mudar de redação.
Hoje só algumas recusas trazem code. Nas outras, o status HTTP é o que identifica o erro.
Quando o pedido tem mais de um campo errado, error junta os motivos numa frase só, separados por vírgula:
{
"success": false,
"error": "period deve estar no formato AAAA-MM, lineItems não pode ser vazio"
}O id da requisição
Toda resposta, de sucesso ou de erro, traz o cabeçalho X-Request-Id:
HTTP/2 400
x-request-id: 4409b8ae-51a4-4a3d-805f-8277777ac1ecGrave esse valor no log da integração. Ao abrir um chamado sobre uma chamada que falhou, mande o X-Request-Id, o horário e o status: com eles o suporte TOPO acha a chamada no registro do TOPO.
A recusa sai sempre com status 4xx, nunca com 2xx. O SAP PI/PO e o CPI tratam qualquer 2xx como entrega feita, e um balancete recusado com 201 sumiria sem alerta.
Status por status
| Status | Exemplo de error | Causa | Como resolver |
|---|---|---|---|
| 400 | period deve estar no formato AAAA-MM, por exemplo 2026-08. | Campo faltando ou em formato errado. | Corrija o campo que a mensagem cita. |
| 400 | Informe companyId ou cnpj. | O balancete veio sem empresa. | Mande companyId ou cnpj. |
| 400 | O plano de contas do arquivo ("Plano X") não corresponde a nenhum plano de contas ativo no TOPO (...) com code: IMPORTACAO_RECUSADA | chartName não bate com nenhum plano ativo da empresa. | Use o nome exato do plano, como está cadastrado no TOPO. |
| 400 | Nenhuma conta do balancete existe no plano de contas. (...) com code: IMPORTACAO_RECUSADA | Nenhuma linha pôde entrar: as contas não existem no plano, não entram na conciliação (exigeConciliacao: false), ou o chartName faltou e o TOPO não achou o plano. | Mande o chartName e confira as contas em GET /api/v1/chart-of-accounts/{id}/accounts. |
| 400 | Não foi possível concluir a operação. Confira os dados informados e tente de novo. | O corpo não é um JSON válido. | Confira aspas e vírgulas do JSON, e o cabeçalho Content-Type: application/json. |
| 400 | Envie o arquivo do balancete no campo file. | A importação por arquivo veio sem o arquivo. | Mande o arquivo no campo file do formulário. |
| 400 | limit deve estar entre 1 e 100. | Página grande demais na leitura. | Use limit até 100 e peça as páginas seguintes. |
| 401 | Chave de API inválida | Sem chave, chave errada, revogada, de outro ambiente ou na URL. | Confira a chave e o cabeçalho. Se perdeu a chave, abra um chamado e peça outra ao suporte TOPO. |
| 403 | Escopo insuficiente: a chave não tem trial_balances:write | A chave não tem o escopo da rota. | Abra um chamado e peça ao suporte TOPO uma chave com o escopo. |
| 403 | Módulo não contratado para esta empresa | A empresa não tem o módulo que a rota usa. | Fale com o cliente ou abra um chamado. |
| 404 | Nenhuma empresa com o CNPJ 12.345.678/0001-90 está cadastrada neste ambiente. | CNPJ ou companyId que o cliente não tem neste ambiente. | Confira o CNPJ e o ambiente (staging e produção têm cadastros separados). |
| 404 | Registro não encontrado. Ele pode ter sido excluído ou estar fora do seu acesso. | A rota não existe (por exemplo, faltou o /api no começo do caminho). | Confira o caminho: toda rota começa com /api/v1/. |
| 409 | O período 08/2026 desta empresa está fechado (Bloqueado: Sim). (...) com code: COMPETENCE_CLOSED | A competência enviada está fechada no TOPO. | Um administrador do módulo reabre o período no TOPO, com justificativa, e você envia de novo. |
| 409 | O período seguinte (09/2026) desta empresa está fechado (Bloqueado: Sim). Importar o balancete de 08/2026 mudaria as conciliações dele. (...) com code: NEXT_COMPETENCE_CLOSED | A competência seguinte está fechada, e a importação mudaria as conciliações dela. | Um administrador do módulo reabre o período seguinte no TOPO, com justificativa, e você envia de novo. |
| 415 | Envie a consulta com Content-Type: application/json. | GraphQL sem o cabeçalho de JSON. | Mande Content-Type: application/json. |
| 429 | Muitas requisições em pouco tempo. Aguarde alguns segundos e tente de novo. | Mais de 30 chamadas por minuto na mesma rota com a mesma chave. | Espere os segundos do cabeçalho Retry-After e tente de novo. |
| 500 | Mensagem genérica com um código de referência | Falha do TOPO. | Tente de novo em alguns minutos. Se repetir, mande o código ao suporte TOPO por um chamado. |
Quando repetir a chamada
- 429 e 5xx: repita depois de esperar. No 429, espere o
Retry-After. - 400, 403, 404 e 409: não repita igual. O mesmo pedido vai receber a mesma resposta até alguém corrigir o dado ou o cadastro.
- 401: não repita. Confira a chave primeiro.
Reenviar um balancete que já entrou não duplica nada. Veja idempotência.
Erros do GraphQL
A rota /api/v1/graphql responde no formato do GraphQL: uma lista errors, cada item com message em português e extensions.code.
{
"errors": [
{
"message": "Esta API é só de leitura: não existe mutation nem subscription.",
"extensions": { "code": "SO_LEITURA" }
}
]
}extensions.code | Quando |
|---|---|
CONSULTA_INVALIDA | A consulta pede um campo ou tipo que não existe no schema (status 400). |
SO_LEITURA | A consulta tem mutation ou subscription. |
PROFUNDIDADE_EXCEDIDA | A consulta tem aninhamento demais. |
COMPLEXIDADE_EXCEDIDA | A consulta pede dados demais de uma vez. Peça menos campos ou páginas menores. |
CONTENT_TYPE_INVALIDO | Faltou Content-Type: application/json (status 415). |
Se parte da consulta der certo, a resposta vem com status 200, com data e com errors explicando o que faltou.