Pular para o conteúdo principal

Tratamento de Erros

Todos os erros da API seguem o mesmo formato base, o ApiError, independentemente do endpoint, método HTTP ou status. Isso permite tratamento programático sem parsing de mensagens.

Breaking change

Versões anteriores retornavam erros de validação como dicionário {"field": ["mensagem"]} e itens de sync com falha como string em error. Agora toda resposta de erro traz um array errors[] de objetos ApiError no mesmo formato.

Como funciona​

Toda resposta de erro contém um array errors[]. Cada item desse array é um ApiError que carrega no mínimo dois campos: type (categoria programática) e message (texto descritivo).

{
"success": false,
"message": "Turma 'ALG001-2099.1' não encontrada.",
"errors": [
{
"type": "not_found",
"message": "Turma 'ALG001-2099.1' não encontrada.",
"entity": "enrollment",
"code": "ALG001-2099.1"
}
]
}

Os campos extras (entity, code, field, rule, etc.) variam conforme o type. A tabela abaixo é a principal ferramenta de decisão: olhe o type, identifique a categoria e os campos esperados.

typeHTTPQuando acontece
validation_failed422Schema do request inválido (campo obrigatório ausente, formato errado)
code_not_foundsync (200/207/422) ou 404Code referenciado não existe (ex: turma com subject_code inexistente)
constraint_violationsync (200/207/422) ou 422Regra de negócio violada (ex: turma sem nenhum curso vinculado)
not_found404Recurso buscado por code não existe
authentication_failed401 ou 403API Key ausente, inválida, desativada ou com scope insuficiente
rate_limit_exceeded429Limite de requisições por minuto atingido
internalsync (200/207/422) ou 500Falha inesperada do servidor. Em sync, o item falhado vai para data.errors[]. Fora de sync, vira HTTP 500

Em endpoints de sincronização (*/sync), o status HTTP reflete o resultado do lote: 200 se todos os itens passaram, 207 se alguns passaram e outros falharam, 422 se nenhum item foi persistido. Veja Status HTTP do sync em lote.

Em que parte da resposta os erros aparecem​

A localização do errors[] depende do cenário. Há dois lugares possíveis:

Na raiz da resposta: o request inteiro falhou. Vale para validação (422), 404, single-item (422), autenticação (401/403) e rate limit (429).

Em data.errors[]: o request foi aceito e processado item a item (sync em lote). Cada item que falhou vira um objeto com index, code e seu próprio errors[]. O status HTTP varia conforme o resultado do lote (200/207/422) e success é true quando ao menos um item foi persistido. Veja Status HTTP do sync em lote.

Exemplo de falha em endpoint single (errors na raiz)​

{
"success": false,
"message": "Turma 'ALG001-2025.1' ou aluno 'ALU2024999' não encontrado.",
"errors": [
{
"type": "not_found",
"message": "Turma 'ALG001-2025.1' ou aluno 'ALU2024999' não encontrado.",
"entity": "enrollment",
"code": "ALG001-2025.1"
}
]
}

Status HTTP do sync em lote​

Endpoints de sincronização (*/sync) processam cada item de forma independente, então o status HTTP reflete o resultado do lote como um todo:

SituaçãoHTTPsuccess
Todos os itens passaram200true
Alguns passaram e outros falharam (parcial)207true
Houve falhas e nenhum item foi persistido422false

Em todos os casos, a resposta traz data.created, data.updated, data.failed e, quando há falhas, data.errors[] com o detalhe de cada item. Independente do status, sempre verifique data.failed para saber quais itens não passaram. Não trate apenas 200 como sucesso: um 207 significa que parte do lote foi sincronizada.

Sync com falhas parciais​

Quando um endpoint de sincronização processa um batch, cada item é tratado individualmente. Os que dão certo entram em created ou updated; os que falham entram em data.errors[]. Uma falha parcial retorna HTTP 207 (success: true); se nada for persistido, retorna 422 (success: false).

{
"success": true,
"data": {
"created": 8,
"updated": 1,
"failed": 1,
"errors": [
{
"index": 2,
"code": "ALG001-2025.1",
"errors": [
{
"type": "code_not_found",
"message": "Professores não encontrado(a)s: PROF999, PROF888",
"entity": "professor",
"missing": ["PROF999", "PROF888"]
}
]
}
]
}
}

index é a posição do item no array enviado (0-based) e code é o identificador do item.

Dois níveis de errors​

Existem dois arrays chamados errors em níveis diferentes:

  • data.errors[] (externo): a lista de itens do batch que falharam. Sempre tem o mesmo tamanho que failed.
  • data.errors[N].errors[] (interno): a lista de falhas daquele item específico. Um único item pode acumular múltiplos erros quando tem várias referências inválidas ao mesmo tempo.

Em vez de reportar uma falha por vez, a API acumula tudo e devolve junto. Acumulação por item se aplica a:

  • Turma: subject_code + course_codes + professor_codes + student_codes (até 4 erros)
  • Gestor de Área: area_codes + unit_code (até 2 erros)
  • Curso: area_code + unit_code (até 2 erros)

Batch misto: sucessos e falhas convivem​

O exemplo abaixo envia 3 itens onde o 1º e o 3º falham e o 2º é criado normalmente:

{
"success": true,
"data": {
"created": 1,
"updated": 0,
"failed": 2,
"errors": [
{
"index": 0,
"code": "GEST_A",
"errors": [
{ "type": "code_not_found", "message": "Áreas não encontrado(a)s: AX, AY", "entity": "area", "missing": ["AX", "AY"] },
{ "type": "code_not_found", "message": "Unidade 'UX' não encontrado(a).", "entity": "unit", "code": "UX" }
]
},
{
"index": 2,
"code": "GEST_C",
"errors": [
{ "type": "code_not_found", "message": "Unidade 'UY' não encontrado(a).", "entity": "unit", "code": "UY" }
]
}
]
}
}

Note que index: 1 não aparece porque foi sucesso. Use index para mapear cada falha de volta ao item original que você enviou.

Cenários comuns​

Os blocos abaixo mostram um exemplo de cada categoria de erro.

Referência completa de campos​

Cada type carrega um conjunto específico de campos contextuais além de type e message. A tabela é a referência canônica.

typeCampos contextuais
validation_failedfield (dot-notation)
code_not_found (um code)entity, code
code_not_found (múltiplos)entity, missing[]
constraint_violationentity, rule, invalid_codes[] (quando aplicável)
not_foundentity, code
authentication_failed (scope)rule, required_scope, client_scope
authentication_failed (auth)rule
rate_limit_exceededrule, limit, retry_after
internalexception_class

Regras de negócio (constraint_violation)​

O campo rule permite identificar a regra violada sem parsear a mensagem.

ruleEndpointSignificado
at_least_one_professor/enrollments/syncItem sem professor_codes
at_least_one_course/enrollments/sync, /coordinators/syncItem sem course_codes
at_least_one_area/area-managers/syncItem sem area_codes
enrollment_without_courses/enrollments/sync, POST /enrollments/{code}/students/{code}Turma sem cursos vinculados
user_suspended/sso/generate-tokenUsuário com suspended_at não nulo

Regras de autenticação e rate limit​

ruleHTTPSignificado
unauthenticated401Header Authorization ausente
invalid_api_key401API Key não corresponde a nenhum cliente
api_key_disabled403API Key existe mas está desativada no painel
insufficient_scope403Scope da API Key não permite a operação
rate_limit_exceeded429Limite de requisições por minuto atingido