Saltar al contenido

Errores y códigos de estado

Toda la API devuelve respuestas JSON (con header Content-Type: application/json) independientemente del header Accept del request. No hay redirects ni páginas HTML de error en /api/v1/*.

Forma del error

Todos los errores siguen una estructura común:

jsonc
{
  "message": "Descripción humana del error",
  "errors": {
    // sólo presente en 422: detalle por campo
    "email": ["El campo email es obligatorio."],
    "human.tax_id_number": ["El CUIT no es válido."]
  }
}
  • message: texto pensado para mostrarse en logs de su sistema o, si aplica, al usuario final.
  • errors: diccionario campo → array de errores (sólo en validación, status 422). Las claves usan dot-notation para errores en campos anidados del bulk POST (ej. human.residential_address.postal_code).

Códigos de estado

StatusSignificadoCuándo ocurre
200 OKLectura exitosaGET / list, GET / show, GET / checklist, GET / catalogs.
201 CreatedRecurso creadoPOST /accounts (bulk), POST /documents, POST /hosted-flow/link.
204 No ContentOperación exitosa sin bodyDELETE /documents/{id}.
400 Bad RequestRequest mal formadoJSON inválido en el body.
401 UnauthorizedSin autenticarFalta el header Authorization, token revocado, token expirado.
403 ForbiddenAutenticado pero sin permisoToken activo pero le falta la ability requerida (accounts:read, accounts:write). El body indica qué ability falta.
404 Not FoundRecurso no encontradoRecurso inexistente o al que el token no tiene acceso (no se distingue intencionalmente, por seguridad).
413 Payload Too LargeArchivo demasiado grandeUpload de documento que supera el límite (50 MB por archivo).
422 Unprocessable EntityValidación fallóFalta un campo requerido, formato inválido, valor fuera de los enums permitidos, magic-bytes que no coinciden con el MIME, legajo en estado no apto para la acción. El body incluye errors por campo cuando aplica.
429 Too Many RequestsRate limit alcanzadoSe superó el límite de requests por minuto (120 req/min para su empresa, compartido entre todos sus tokens). Reintentar después del header Retry-After. Si necesitás aumentar el límite de llamadas, contactate con tu ejecutivo.
500 Internal Server ErrorError inesperado del servidorError inesperado del servidor. Reportable a soporte. Reintentar con backoff exponencial.
502 Bad GatewayError en un servicio externoEl proveedor de firma electrónica no respondió (sólo en modo api_link). El legajo revierte; reintentá con backoff.
503 Service UnavailableMantenimiento o sobrecargaReintentar después del header Retry-After.

Ejemplos

401 — token ausente o inválido

http
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{ "message": "Missing API token." }
http
HTTP/1.1 401 Unauthorized
Content-Type: application/json

{ "message": "Invalid or expired API token." }

El mensaje distingue entre token ausente (Missing API token.) y token presente pero rechazado por estar revocado, expirado o no existir (Invalid or expired API token.). Por seguridad, no se diferencia entre "el token no existe" y "el token existe pero fue revocado".

403 — falta de ability

http
HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "message": "Token lacks required ability.",
  "required": ["accounts:write"]
}

El campo required es siempre un array, aunque la operación pida una sola ability — esto permite documentar endpoints que requieran combinaciones (ej. ["accounts:write", "accounts:submit"]) sin cambiar el shape.

404 — recurso ajeno o inexistente

http
HTTP/1.1 404 Not Found
Content-Type: application/json

{ "message": "Not found." }

Sin namespace ni id en el mensaje

La API nunca devuelve mensajes tipo No query results for model [App\Models\Account] {id-no-existe}. Sólo "Not found.", para no filtrar estructura interna ni hacer eco del id pedido.

422 — validación del bulk POST

El bulk POST (POST /v1/accounts) valida cada sección anidada del payload contra la configuración de Campos configurables. Los errores vienen con claves en dot-notation:

http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "The given data was invalid.",
  "errors": {
    "type": ["The type field is required."],
    "human.tax_id_number": ["El CUIT no es válido."],
    "human.residential_address.postal_code": ["El código postal es obligatorio."],
    "human.investor_questionnaire.0.option_id": ["The selected option is invalid."]
  }
}
http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "Account is not in an onboarding state.",
  "errors": {
    "status": ["Account status must be draft or in_progress."]
  }
}
http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "Hosted-flow handoff is only available for accounts created via the public API.",
  "errors": {
    "account": ["This account was not created via the API."]
  }
}
http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "Account is already bound to a different consumer.",
  "errors": {
    "email": ["This account is bound to a different email address."]
  }
}

422 — documento con magic-bytes inválidos

El upload de documentos valida tanto el MIME declarado como los magic-bytes del archivo. Un PDF con cuerpo HTML disfrazado se rechaza:

http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "message": "El contenido del archivo no coincide con el tipo declarado.",
  "errors": {
    "file": ["El contenido del archivo no coincide con el tipo declarado."]
  }
}

Reintentos

Status¿Reintentar?
4xx (excepto 408, 429)No. Son errores del cliente — corregí el payload o la autenticación.
408, 429Sí, con backoff. Respetá el header Retry-After.
5xxSí, con backoff exponencial. Si persiste, abra ticket de soporte.

Leé Idempotencia y reintentos para evitar duplicados al reintentar operaciones de escritura.