Errores, identificador de petición y reintentos
La forma común de los errores de la API externa, el catálogo de códigos, cómo seguir una petición con X-Request-Id y cuándo reintentar.
Actualizado el . 5 min de lectura
Incluido en todos los planes. Ver precios
Todas las respuestas de error de la API externa tienen la misma forma, y casi todas traen un código estable (errorCode) pensado para que tu código decida qué hacer sin leer el texto del mensaje. Esta página explica esa forma, cómo seguir una petición concreta y cuándo merece la pena reintentar.
La forma de un error
{
"statusCode": 404,
"message": "Usuario externo no encontrado. Usa /users/identify primero.",
"error": "NOT_FOUND",
"errorCode": "USER_NOT_FOUND",
"timestamp": "2026-10-08T10:31:12.000Z",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}- statusCodenumberobligatorio
- Código HTTP de la respuesta.
- messagestringobligatorio
- Explicación en castellano, útil para el registro o para mostrarla a una persona.
- errorstringobligatorio
- Nombre del estado HTTP en mayúsculas (BAD_REQUEST, NOT_FOUND, TOO_MANY_REQUESTS...). No lo uses para decidir: para eso está errorCode.
- errorCodestring
- Código estable del caso concreto (USER_NOT_FOUND, FILE_TOO_LARGE...). Es lo que debe leer tu código.
- timestampstringobligatorio
- Fecha y hora de la respuesta, en ISO 8601.
- requestIdstring
- Identificador de la petición, el mismo que la cabecera X-Request-Id.
Algunos errores añaden campos propios. Por ejemplo, los de plan traen moduleKey o capabilityKey; se explican en Errores de plan.
No pintes el objeto de error en tu interfaz
El cuerpo del error es un objeto, no un texto. Si lo pasas tal cual a un aviso o a un componente de React, la pantalla se rompe con «Objects are not valid as a React child». Muestra message, decide con errorCode y guarda requestId.
Seguir una petición con X-Request-Id
Todas las respuestas, correctas o no, llevan la cabecera X-Request-Id. Si tu petición ya trae una (letras, números, guiones y guiones bajos, hasta 128 caracteres), UTILIA OS la respeta; si no, genera una nueva. Enviar la tuya te permite seguir la misma petición en tus registros y en los nuestros: es lo primero que te pedirá soporte.
X-Api-Key: utl_tu_clave
X-Request-Id: pedido-8812-intento-1Cuándo reintentar
Reintenta solo cuando el fallo puede desaparecer por sí solo:
¿Reintento o no?
El fallo es pasajero
Reintenta
429 (espera lo que diga Retry-After), cualquier 5xx y los fallos de red: tiempo agotado o conexión cortada.La respuesta será la misma
No reintentes
400, 401, 403, 404, 409 y 422. Corrige la petición, la clave, el permiso o el plan; repetir solo gasta tu cupo.Para los reintentos, usa espera exponencial con algo de azar (por ejemplo, 1, 2, 4 y 8 segundos) y un tope de cuatro intentos. Si la operación crea algo que mueve dinero o emite un documento, envía siempre la misma clave de idempotencia en cada intento para no duplicarlo.
Catálogo de códigos
Autenticación y acceso
| errorCode | HTTP | Qué significa |
|---|---|---|
API_KEY_REQUIRED | 401 | No llegó la clave en la cabecera X-Api-Key. |
API_KEY_INVALID | 401 | La clave no existe, está desactivada o ha caducado. |
API_KEY_NOT_LINKED | 401 | La clave existe, pero no pertenece a ninguna aplicación externa. |
APP_DISABLED | 403 | La aplicación externa está desactivada. |
ORIGIN_NOT_ALLOWED | 403 | El origen de la petición no está entre los dominios autorizados de la aplicación. |
CORS_ORIGIN_NOT_ALLOWED | 403 | El navegador llama desde un origen que la plataforma no tiene autorizado. |
RATE_LIMIT_EXCEEDED | 429 | Se superó el límite de peticiones por hora de la clave. Llega con Retry-After: 3600. |
MODULE_NOT_ENABLED | 403 | El plan de la organización no incluye el aplicativo. No se arregla reintentando ni pidiendo permisos. |
CAPABILITY_NOT_ENABLED | 403 | El plan de la organización no incluye la capacidad. |
INSUFFICIENT_SCOPE | 403 | La aplicación no tiene concedido el permiso de la operación. El mensaje no dice cuál, a propósito. |
Tickets
| errorCode | HTTP | Qué significa |
|---|---|---|
TICKET_NOT_FOUND | 404 | El ticket no existe o no es de este usuario. |
TICKET_ACCESS_DENIED | 403 | El usuario no tiene acceso a este ticket. |
TICKET_CLOSED | 403 | No se pueden añadir mensajes a un ticket cerrado. |
TICKET_CANNOT_REOPEN | 404 | El ticket no existe o su estado no permite reabrirlo. |
Usuarios externos
| errorCode | HTTP | Qué significa |
|---|---|---|
USER_NOT_FOUND | 404 | El usuario externo no existe. Lo devuelven los endpoints de tickets e IA, como POST /tickets/ai-suggest. Llama antes a POST /users/identify. |
EXTERNAL_USER_NOT_FOUND | 404 | Lo mismo, pero en los endpoints de facturación y métodos de pago (/invoices/stats, /invoices/:id, /invoices/:id/pay, /payment-methods...). Trátalo igual que USER_NOT_FOUND. |
Archivos
| errorCode | HTTP | Qué significa |
|---|---|---|
FILE_MISSING | 400 | La petición no incluye ningún archivo. |
FILE_INVALID_MIME | 400 | El tipo de archivo no está permitido. |
FILE_TOO_LARGE | 400 | El archivo supera el tamaño máximo configurado en la aplicación. |
FILE_TOO_MANY | 400 | La subida trae más archivos de los que admite el endpoint. |
FILE_INVALID_ATTACHMENTS | 400 | Algún adjunto no es válido o no pertenece a la aplicación. |
FILE_QUOTA_EXCEEDED | 403 | La aplicación ha agotado su almacenamiento. |
FILE_NOT_FOUND | 404 | El archivo no existe. |
IA
| errorCode | HTTP | Qué significa |
|---|---|---|
AI_NO_INPUT | 400 | Hay que enviar texto, audio o imágenes. |
AI_AUDIO_TOO_LARGE | 400 | El audio supera 10 MB. Usa POST /tickets/ai-transcribe-async. |
Validación
| errorCode | HTTP | Qué significa |
|---|---|---|
VALIDATION_ERROR | 400 | Los datos enviados no cumplen las reglas del endpoint. El mensaje dice qué campo falla. |
Los campos que el endpoint no declara se descartan sin error, así que un dato en el sitio equivocado no siempre provoca un 400: lo explica Dónde va cada parámetro.
Facturación, cobros, CRM y presupuestos
Cada familia de endpoints tiene sus propios códigos (INVOICE_NOT_FOUND, PAYMENT_AUTHORIZATION_REQUIRED, CLIENT_NOT_ACCESSIBLE, LEAD_ALREADY_CONVERTED...). Están documentados en la página de cada familia, dentro de API REST, y en la guía de facturación y cobro.
Gestión de aplicaciones desde el panel
Estos códigos no los devuelve la API externa, sino la API del panel con la que una persona gestiona las aplicaciones (/api/integrations/apps/...):
| errorCode | HTTP | Qué significa |
|---|---|---|
APP_SLUG_DUPLICATE | 409 | Ya existe una aplicación con ese identificador. |
APP_NOT_FOUND | 404 | La aplicación externa no existe. |
SCOPE_OUT_OF_PLAN | 400 | El permiso que intentas conceder exige algo que el plan no incluye. |
WEBHOOK_NO_URL | 400 | La aplicación no tiene dirección de avisos configurada. |
WEBHOOK_URL_INVALID | 400 | La dirección de avisos apunta a una red privada o no es válida. |
DELIVERY_NOT_FOUND | 404 | La entrega del aviso no existe. |
DELIVERY_ALREADY_SUCCESS | 400 | No se puede reintentar una entrega que ya llegó bien. |
Siguiente paso
Evita los errores más habituales antes de que aparezcan con Dónde va cada parámetro y Errores frecuentes al integrar.