Documentation › Concepts
Errors and HTTP status
The two error formats, what each HTTP status means and the code catalog.
Two error formats
The API has two error formats. They come from the two parts of the product, and the contract is frozen: both stay as they are.
| Routes | Format | Content-Type |
|---|---|---|
/v1/nfse, /v1/lotes, /v1/webhooks, /v1/eventos |
problem+json, with a stable codigo |
application/problem+json |
/v1/account, /v1/usage, /v1/companies, /v1/documents, /v1/servicos, /v1/municipios |
NestJS format | application/json |
problem+json (issuance, batch, webhooks and events):
{
"type": "https://sudrel.com.br/docs/erros/referencia_duplicada",
"codigo": "referencia_duplicada",
"codigo_oficial": null,
"campo": "/referencia",
"mensagem": "Já existe uma nota com esta referência nesta empresa.",
"correcao": "Consulte a nota existente em GET /v1/nfse/9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f. Se quiser emitir outra nota, use outra referência.",
"retentavel": false,
"nfse_id": "9d2f0c1e-3a4b-4c5d-8e9f-0a1b2c3d4e5f",
"requisicao_id": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
}
| Field | What it is for |
|---|---|
codigo |
Stable. Your code decides on this field. |
codigo_oficial |
Sistema Nacional NFS-e code (e.g. E0240), when the error comes from one of its rules. |
campo |
JSON Pointer to the field with the problem in your body (e.g. /tomador/documento). |
mensagem |
Text for people. The wording can change; do not compare it. |
correcao |
What to do. |
retentavel |
true: repeating the SAME request can succeed. false: fix it first. |
requisicao_id |
The same value as the X-Request-Id header. Search for it in Integrações › Log da API (Integrations › API log). |
erros |
In 422 validacao: all errors at once, each with the fields above. |
itens |
In 412 empresa_nao_pronta: the full readiness list. |
nfse_id, nfse |
In 409 referencia_duplicada (only nfse_id) and in the 422 nfse_rejeitada and falha_transmissao (the full invoice in nfse). |
There is no title, status, detail or instance: the status is in the HTTP
response, and codigo tells the rest.
NestJS format (account, usage, companies, documents, NBS, municipality):
{ "statusCode": 404, "message": "Empresa não encontrada nesta conta.", "error": "Not Found" }
message can be a string or a list of strings (parameter validation error,
one item per field). Here there is no requisicao_id in the body: use the
X-Request-Id header.
HTTP status
| Status | Meaning | What to do |
|---|---|---|
| 200 | OK | Read the body. |
| 201 | Created. In POST /v1/nfse: invoice authorized. |
Continue. |
| 202 | Accepted, still in progress (invoice transmitindo, batch in validation). Not an error. |
Follow it by webhook or GET. Do not repeat the creation. |
| 204 | Removed. | Nothing. |
| 400 | Invalid query parameter (parametro_invalido), or unknown parameter in the document routes. |
Fix the call. |
| 401 | Key missing, invalid or revoked (nao_autenticado). |
Check the Authorization header and the key. |
| 403 | The key cannot do this: restricted to another company (acesso_negado, chave_restrita) or test key in a production-only operation. |
Use the right key. |
| 404 | Does not exist in this account and this environment. | Check the id and the key's environment. |
| 409 | Conflict: referencia_duplicada, idempotencia_conflito, conflito, referencia_ambigua, a state that does not allow the operation. |
Read codigo. See Idempotency. |
| 410 | cursor_vencido in /v1/eventos. |
Continue from cursor_mais_antigo. |
| 412 | empresa_nao_pronta: the company cannot issue. Nothing was created. |
Resolve the bloqueio items in itens. See Readiness. |
| 413 | Spreadsheet over 20 MB in POST /v1/lotes. |
Split the spreadsheet. |
| 422 | The request was understood and refused: validacao, nfse_rejeitada, falha_transmissao, cancelamento_recusado... |
Read codigo, erros, correcao. |
| 429 | More than 120 requests in the minute, on this key. | Wait for the next minute and repeat. |
| 500 | Our error (erro_interno, retentavel: true). |
Repeat with the same Idempotency-Key. If it persists, send the X-Request-Id to support. |
The 429 also has both formats: problem+json limite_de_requisicoes
(retentavel: true) on the issuance, batch, webhooks and events routes, and
{"message": "...", "code": "RATE_LIMITED"} on the others. There is no
Retry-After or X-RateLimit-* header.
Codes (codigo) of the problem+json routes
codigo |
Status | When |
|---|---|---|
parametro_invalido |
400 | Invalid filter, date, limite or cursor |
requisicao_invalida |
400 | Malformed request |
nao_autenticado |
401 | Key missing, invalid or revoked |
acesso_negado |
403 | Key restricted to another company |
chave_restrita |
403 | Key restricted to one company trying to manage webhooks |
nao_encontrado |
404 | Company does not exist, or invoice has no XML yet |
nfse_nao_encontrada |
404 | No invoice with this id, reference or access key |
lote_nao_encontrado |
404 | Batch does not exist |
empresa_nao_encontrada |
404 | empresa_id does not exist in POST /v1/lotes |
referencia_duplicada |
409 | An invoice with this referencia already exists in this company and environment |
idempotencia_conflito |
409 | Same Idempotency-Key with a different body |
conflito |
409 | The same Idempotency-Key is still in progress |
referencia_ambigua |
409 | The referencia exists in more than one company: send empresa_id |
nfse_sem_pdf |
409 | The invoice has no PDF yet (retentavel: true) |
nfse_nao_aguarda_confirmacao |
409 | Confirmation of an invoice that is not in aguardando_confirmacao |
lote_sem_emissao_manual, lote_validando, lote_ja_emitido |
409 | POST /v1/lotes/{id}/emissao at the wrong time |
cursor_vencido |
410 | Events cursor older than 90 days |
empresa_nao_pronta |
412 | Readiness with bloqueio |
validacao |
422 | Invalid body; the details are in erros |
nfse_rejeitada |
422 | The Sistema Nacional NFS-e rejected the invoice |
falha_transmissao |
422 | The transmission could not be completed |
cancelamento_recusado |
422 | The Sistema Nacional NFS-e refused the cancellation |
planilha_obrigatoria |
422 | Multipart POST /v1/lotes without the file |
simulacao_so_no_sandbox, simulacao_invalida |
422 | Simulator with the production key, or scenario does not exist |
reenvio_invalido, evento_nao_assinado |
422 | Webhook resend with wrong parameters |
limite_de_requisicoes |
429 | Request limit |
erro_interno |
500 | Our error |
Inside erros (422 validacao) the codes tell which field and which rule:
tipo_invalido, formato_invalido, campo_desconhecido,
documento_invalido, referencia_muito_longa, tomador_igual_prestador,
codigo_servico_inexistente, aliquota_iss_obrigatoria,
competencia_invalida, obra_obrigatoria, nbs_fora_do_servico and others.
Each one comes with campo, mensagem and correcao; handle any new code
by its campo and its correcao.
Rejection by the Sistema Nacional NFS-e
When the Sistema Nacional NFS-e rejects, the 422 nfse_rejeitada carries
codigo_oficial (e.g. E0039) and the full invoice in nfse. In
nfse.rejeicao.explicacao, for the codes Sudrel knows, you get the
explanation in plain Portuguese and the fix. The invoice is recorded as
rejeitada: fix it and issue a new invoice, with another referencia.