Ir al contenido

Errores

Todo error de la API sale en el mismo formato, en cualquier ruta y en cualquier estado.

{
"error": {
"type": "authentication_error",
"code": "api_key_invalid",
"message": "Clave de API inválida, revocada o vencida.",
"request_id": "0a8c1f2e-3b4d-4c5f-9a6b-7c8d9e0f1a2b",
"doc_url": "https://docs.fatureihoje.com/es/errors#api_key_invalid"
}
}
CampoSiempre vieneQué es
typeSíLa familia del error. Sirve para ramificar por rango, sin conocer cada código
codeSíEl caso exacto. Es con él que su programa decide qué hacer
messageSíFrase para que una persona lea. Sale en el idioma de Accept-Language
doc_urlSíLa dirección de esta página, en el ancla del código
request_idEn /public/v1Identificador de esta llamada. Es lo que pide el soporte
paramNoReservado. El contrato lo prevé para el error de un solo campo, y ninguna ruta lo emite hoy
errorsNoLista de campos inválidos. Solo en el 422 de validación

El code es estable y está escrito en inglés. No cambia de valor, no cambia de nombre y no cambia con el idioma. Un código publicado en el catálogo sigue existiendo aunque la API deje de emitirlo, porque una integración que lo trata no puede romperse.

La message es lo contrario: es texto para que una persona lo lea y sale traducido según el encabezado Accept-Language de la solicitud (pt-BR es el valor por defecto, y en y es se aceptan).

Cada code tiene un único estado HTTP, y nunca varía. validation_failed es siempre 422; rate_limit_exceeded es siempre 429. Por eso el catálogo de abajo publica los dos juntos: si usted trata el código, el estado es consecuencia, y nunca va a llegar un par distinto del que está aquí.

Las siete familias de type:

typeRangoCuándo
invalid_request_error400, 404, 413, 415La solicitud está equivocada, o lo que pide no existe
authentication_error401La clave no fue aceptada
permission_error403La clave fue aceptada, pero esta acción no está permitida
conflict_error409Conflicto con el estado actual
validation_error422Campo inválido
rate_limit_error429Presupuesto de llamadas agotado
api_error500, 503El problema es nuestro

Cuando uno o más campos no son válidos, el cuerpo trae la lista, campo por campo:

{
"error": {
"type": "validation_error",
"code": "validation_failed",
"message": "Uno o más campos no son válidos.",
"errors": [
{ "param": "email", "code": "invalid", "message": "Correo inválido" },
{ "param": "phone", "code": "invalid", "message": "Teléfono inválido" }
],
"request_id": "6f12b0d4-8e33-4a91-b2c7-5d0a7e93f118",
"doc_url": "https://docs.fatureihoje.com/es/errors#validation_failed"
}
}

param es el nombre del campo tal como la API lo recibe. message es texto para una persona; lo que su programa usa es param.

Ese param es el de adentro de errors, y es el único que verá hoy. El param del nivel de arriba, al lado de code, está previsto en el contrato pero ninguna ruta lo emite: lea siempre la lista errors.

Toda respuesta de /public/v1, con error o sin error, trae el encabezado Request-Id. En el cuerpo de error, el mismo valor aparece en request_id.

Guarde ese valor en su registro siempre que una llamada falle. Es por él que el soporte encuentra la llamada, y es el único camino cuando el error es interno.

Una ruta fuera de /public/v1 responde 404 antes de que la llamada reciba un identificador, y por eso ese 404 sale sin request_id. Si recibió un error sin request_id, revise primero la ruta.

El doc_url apunta a esta página, ya en el ancla del código:

https://docs.fatureihoje.com/es/errors#api_key_invalid

En portugués la dirección va sin prefijo de idioma: docs.fatureihoje.com/errors#.... Puede registrar esa dirección en su log de error: es corta, permanente, y lleva directo a la explicación del código.

El ejemplo llama a GET /public/v1/me y trata las dos salidas: la respuesta buena y el cuerpo de error. Sirve para cualquier ruta, porque el formato del error es el mismo en todas.

Ventana de terminal
curl -sS -i https://api.fatureihoje.com/public/v1/me \
-H "Authorization: Bearer $FH_API_KEY" \
-H "Accept-Language: es"

El -i imprime los encabezados antes del cuerpo, así que el Request-Id aparece junto al error.

Esta es la lista completa. Se genera del contrato de la API al construir el sitio, así que un código nuevo aparece aquí solo y ningún código queda afuera.

Código HTTP Tipo
api_key_invalid 401 authentication_error
access_denied 403 permission_error
permission_missing 403 permission_error
member_permission_denied 403 permission_error
member_suspended 403 permission_error
organization_suspended 403 permission_error
subscription_inactive 403 permission_error
plan_feature_unavailable 403 permission_error
plan_limit_reached 403 permission_error
resource_not_found 404 invalid_request_error
route_not_found 404 invalid_request_error
invalid_request 400 invalid_request_error
validation_failed 422 validation_error
conflict 409 conflict_error
idempotency_key_reused 422 validation_error
idempotency_in_progress 409 conflict_error
unsupported_media_type 415 invalid_request_error
request_too_large 413 invalid_request_error
rate_limit_exceeded 429 rate_limit_error
request_failed 400 invalid_request_error
internal_error 500 api_error
service_unavailable 503 api_error
api_key_invalid 401 authentication_error

Mensaje Clave de API inválida, revocada o vencida.

Qué hacer Revise el encabezado Authorization: Bearer <clave>, que la clave siga activa en el panel y que la IP de salida de su servidor esté en la lista de la clave. La respuesta es la misma en todos esos casos a propósito: no dice cuál fue el motivo.

access_denied 403 permission_error

Mensaje No tiene acceso a este recurso.

Qué hacer Acceso denegado sin causa conocida. Este código sale cuando el motivo no es el permiso de la clave ni el del miembro. Guarde el request_id y hable con el soporte.

permission_missing 403 permission_error

Mensaje Esta clave no tiene el permiso requerido por esta ruta.

Qué hacer Vea los permisos de la clave en key.permissions, en la respuesta de GET /public/v1/me, y compárelos con lo que exige la ruta en la Referencia. El permiso de una clave no cambia después de creada, ni en la rotación: para cambiarlo, cree otra clave.

member_permission_denied 403 permission_error

Mensaje El miembro que representa esta clave no puede realizar esta acción.

Qué hacer La clave tiene el permiso, pero el miembro que representa no puede hacer esto en el panel. Ajuste el rol o los permisos de ese miembro, o use una clave de otro miembro.

member_suspended 403 permission_error

Mensaje El miembro que representa esta clave está suspendido.

Qué hacer Reservado. Hoy el miembro suspendido cae en el 401 de api_key_invalid, porque la respuesta de la autenticación no puede confirmar que la clave es válida. Si este código aparece, reactive al miembro en el panel.

organization_suspended 403 permission_error

Mensaje La empresa de esta clave está suspendida.

Qué hacer Reservado, por el mismo motivo que el anterior, pero para la empresa. Si aparece, resuelva la situación de la empresa en el panel.

subscription_inactive 403 permission_error

Mensaje La suscripción de la empresa no está activa.

Qué hacer Regularice el pago en el panel. Repetir la llamada antes de eso devuelve el mismo error, así que insistir en bucle no sirve.

plan_feature_unavailable 403 permission_error

Mensaje El plan de la empresa no incluye este recurso de la API.

Qué hacer La API está disponible a partir del plan Start. El mismo código sale cuando la API fue apagada para esa empresa en particular.

plan_limit_reached 403 permission_error

Mensaje Se alcanzó el límite del plan para este recurso.

Qué hacer El más común es la cantidad de claves activas. Vea el uso en el panel, revoque lo que ya no usa o suba de plan.

resource_not_found 404 invalid_request_error

Mensaje Recurso no encontrado.

Qué hacer El id no existe o es de otra empresa. La API responde 404 en los dos casos, nunca 403: un 403 contaría que el registro existe en otro lugar. Revise el id y la empresa de la clave en GET /public/v1/me.

route_not_found 404 invalid_request_error

Mensaje Ruta no encontrada.

Qué hacer La ruta no existe. Revise el método, la ruta y la dirección: api.fatureihoje.com sirve solo /public/v1. Una ruta de un área que todavía no se publicó responde igual.

invalid_request 400 invalid_request_error

Mensaje Solicitud inválida.

Qué hacer La solicitud está malformada, casi siempre JSON roto o un parámetro de consulta inválido. Corrija antes de repetir: la misma solicitud devuelve el mismo error.

validation_failed 422 validation_error

Mensaje Uno o más campos no son válidos.

Qué hacer El cuerpo trae errors, con param, code y message de cada campo. Corrija lo que señala y envíe de nuevo: la misma solicitud devuelve el mismo error.

conflict 409 conflict_error

Mensaje La operación entra en conflicto con el estado actual del recurso.

Qué hacer Lea el recurso otra vez y decida a partir de lo que dice ahora. Repetir sin releer devuelve el mismo conflicto. Es lo que responde, por ejemplo, un cambio de situación de cita que la agenda no permite (cancelada no vuelve, completada solo vuelve a confirmada), la edición de una orden de servicio ya completada o cancelada, la edición de un presupuesto aprobado o cancelado, la eliminación de un presupuesto que ya se convirtió en venta activa la segunda conversión del mismo presupuesto en venta o en orden, iniciar, completar o cancelar una orden ya completada o cancelada, cualquier escritura en un presupuesto absorbido en una unión, el código interno (sku) que ya existe en la empresa, el nombre de variación repetido en el mismo producto, la eliminación de una categoría que todavía tiene productos o servicios, y en la venta: cualquier escritura en una venta cancelada, versión nueva o cancelación con factura activa, versión nueva con la comisión del vendedor ya pagada, cobrar o reprogramar una venta de contrato, anular un cobro ya anulado o con factura activa, y reprogramar sin cuota abierta. En finanzas: cambiar un campo protegido de un movimiento de venta o del banco, eliminar un movimiento de venta o del banco, marcar como pagado un movimiento cancelado o en el resumen, eliminar una cuenta que tiene movimientos, y la eliminación de serie que borraría más de lo pedido (con param scope).

idempotency_key_reused 422 validation_error

Mensaje Esta Idempotency-Key ya se usó con un cuerpo diferente.

Qué hacer Genere un valor nuevo para cada operación distinta. Repetir la clave solo vale para repetir la MISMA solicitud, byte a byte.

idempotency_in_progress 409 conflict_error

Mensaje Una solicitud con esta Idempotency-Key todavía está en curso.

Qué hacer Espere unos segundos y repita la misma solicitud, con la misma clave. No genere una clave nueva: eso ejecutaría la operación dos veces.

unsupported_media_type 415 invalid_request_error

Mensaje Envíe el cuerpo en JSON, con Content-Type: application/json.

Qué hacer Formulario, multipart y texto plano no se aceptan. Revise el Content-Type que su biblioteca envía por defecto.

request_too_large 413 invalid_request_error

Mensaje El cuerpo de la solicitud supera el límite de 1 MB.

Qué hacer Divida el envío en partes más pequeñas. El tope vale para toda llamada, con o sin Idempotency-Key.

rate_limit_exceeded 429 rate_limit_error

Mensaje Se alcanzó el límite de llamadas por minuto. Intente de nuevo en unos instantes.

Qué hacer Espere lo que dice el encabezado Retry-After y retroceda progresivamente. No repita en un bucle apretado: el presupuesto es de la empresa y usted atrasa sus llamadas buenas.

request_failed 400 invalid_request_error

Mensaje No fue posible procesar la solicitud.

Qué hacer La API no procesó la solicitud y el motivo no tiene código propio en el catálogo. Guarde el request_id. Si el error se repite con la misma solicitud, envíe el request_id al soporte.

internal_error 500 api_error

Mensaje Error interno. Si persiste, envíe el request_id al soporte.

Qué hacer El problema es de nuestro lado. La respuesta nunca trae detalle interno, a propósito. Puede intentar de nuevo después de esperar. Si persiste, envíe el request_id a dev@fatureihoje.com.

service_unavailable 503 api_error

Mensaje API no disponible en este momento. Inténtelo de nuevo en breve.

Qué hacer La causa es configuración de borde, no su solicitud. Espere e intente otra vez. Si dura, avise al soporte con el request_id.

  • Límites de uso: el 429 y los encabezados que dicen cuánto queda.
  • Idempotencia: los dos errores que aparecen cuando repite una solicitud.
  • Autenticación: la guía del 401, que es el error más común al principio.