Skip to main content
Docs vCurrentAPI
Version: Current

Responses & Error Codes

This page is the canonical reference for the format of every API response — success and error. All examples below are real responses from the production API.

Standard error format

Every error returns Content-Type: application/json with a detail field:

  • business/authorization errors → detail is a string;
  • payload validation errors (422) → detail is a list of per-field problems.
{ "detail": "API key inválida" }

Status table

HTTPWhen it happensdetail (real example)
200Successroute-specific body
401Missing or invalid API keyAPI key required
403Invalid/expired key, IP not allowed, or insufficient scopeScope insuficiente para esta API key
404Resource not found (analysis, medical record)Análise não encontrada
409Conflict (resource already exists)Prontuário já existe para este patient_reference
422Invalid payload (validation)list of per-field errors
429Request rate limit exceededRate limit excedido
503Dependency unavailable / service busyServiço ocupado. Tente novamente.
504Analysis exceeded the endpoint time limitA análise excedeu o tempo limite. Tente novamente em instantes.

401 — Not authenticated

Missing or invalid X-API-Key header.

{ "detail": "API key required" }

403 — Not authorized

Several scenarios return 403, always with a string detail:

{ "detail": "API key inválida" }
{ "detail": "API key expirada" }
{ "detail": "IP não permitido para esta API key" }
{ "detail": "Scope insuficiente para esta API key" }

On scope-named routes (e.g. medical records), the message states the required scope:

{ "detail": "Escopo insuficiente: requer prontuario:write" }

404 — Not found

{ "detail": "Análise não encontrada" }
{ "detail": "Prontuário não encontrado" }

409 — Conflict

{ "detail": "Prontuário já existe para este patient_reference" }

422 — Invalid payload

Schema validation. detail is a list: each item points to the field (loc), the error type (type) and the message (msg).

{
"detail": [
{
"type": "missing",
"loc": ["body", "medications"],
"msg": "Field required",
"input": { "language": "pt-BR" }
}
]
}

429 — Rate limit

Returned when the organization's per-minute or monthly limit is exceeded. Honor the Retry-After header (when present) and apply exponential backoff.

{ "detail": "Rate limit excedido" }

503 — Service unavailable

A critical dependency is temporarily unavailable (e.g. rate limiter/cache) or the service is under load protection. It is safe to retry after a short interval.

{ "detail": "Serviço ocupado. Tente novamente." }

504 — Timeout

The analysis did not finish within the endpoint time limit (load protection). Retry; complete responses are cached and tend to return quickly on the retry.

{ "detail": "A análise excedeu o tempo limite. Tente novamente em instantes." }

Error-handling best practices

  • Always treat 401/403 as a credential/scope error (do not retry without fixing).
  • On 422, read detail[].loc to point the user to the invalid field.
  • On 429/503/504, use retry with backoff (e.g. 1s, 2s, 4s) with a max attempt cap.
  • For the interactions route, remember the fail-safe policy: a technical failure never lowers the risk — check analysis_status (complete | partial | failed) and source_coverage to know how complete the analysis is.

Note: detail messages are returned by the API in Portuguese; the table and notes above describe their meaning in English.