Saltar al contenido principal

Errores

Todos los errores comparten un único envelope:

{
"error": {
"code": "validation_failed",
"message": "Field 'email' is required",
"details": {
"field": "email"
}
}
}
  • code es un identificador machine-readable. Estable entre releases.
  • message es texto legible en inglés. No se proveen strings localizadas — tradúcelas en el consumidor.
  • details es opcional y su forma depende del tipo de error. Para errores de validación incluye el campo ofensor; para errores de rate-limit incluye un retry_after numérico.

Códigos estándar​

HTTPcodeCuándo
400bad_requestJSON malformado, Content-Type no soportado, etc.
400validation_failedEl body o query falló la validación de schema.
401mtls_requiredCertificado de cliente ausente/inválido.
401invalid_tokenJWT malformado o firma inválida.
401invalid_audienceaud no corresponde al entorno.
401token_expiredClaim exp en el pasado.
401token_revokedjti listado en RevokedTokens.
403insufficient_scopeEl token carece del scope requerido.
403insufficient_permissionLa persona detrás del token no tiene el permiso que el endpoint exige; message es el slug del permiso.
403forbiddenOrigin shared-secret ausente o incorrecto, o el token no resuelve a ningún tenant — message es unknown_organization, no_membership o unknown_workspace. Consulta Autenticación.
400workspace_requiredLa organización tiene varios workspaces y no se envió X-Workspace-Id.
404not_foundEl recurso no existe (o pertenece a otro workspace).
409conflictConflicto de estado (p. ej. clave de idempotencia reutilizada con un body diferente, violación de unique constraint).
422unprocessable_entityViolación de regla de negocio (p. ej. no se puede desactivar un webhook con retries activos).
429rate_limitedLímite por cuenta excedido. Incluye header Retry-After.
500internal_errorError no manejado. ID de correlación devuelto en details.request_id.
503service_unavailableDependencia upstream (S3, DB, AI Gateway) con fallo.

Leyendo details​

details es intencionalmente laxo. Patrones comunes:

  • Errores de validación — { "field": "subscribed_events.0", "issue": "must be a known SystemEvent slug" }.
  • Rate limiting — { "retry_after": 17, "limit": 600, "remaining": 0 }.
  • Conflicto de idempotencia — { "key": "...", "original_status": 201, "original_response_id": "..." }.
  • Not found entre workspaces — nunca filtra la existencia del recurso; la respuesta es indistinguible de un id realmente inexistente.

Correlación​

Cada respuesta — exitosa o no — lleva un header X-Request-Id. Inclúyelo al reportar problemas para que podamos obtener el trace desde OpenTelemetry.

Guía de reintentos​

Clase de error¿Reintentar?
400, 401, 403, 404, 409, 422No — corrige la solicitud.
429Sí, después de Retry-After segundos.
500, 503Sí, con backoff exponencial (comienza en 1s, tope de 30s, máx. 5 intentos).

Para operaciones idempotentes (GET, PATCH, DELETE) reintentar siempre es seguro. Para operaciones POST incluye siempre un X-Idempotency-Key para que los reintentos no dupliquen la creación.