Errores
Los errores usan códigos HTTP estándar y siempre el mismo cuerpo JSON. Tu
código debe decidir por error.code, que es estable; message es
orientativo (en inglés) y puede cambiar.
HTTP/1.1 409 Conflict
Content-Type: application/json
X-Request-Id: req_7f3a9c2e5b1d4f60
{
"error": {
"code": "external_id_already_exists",
"message": "external_id is already assigned to another employee of the company."
}
}
Todos los códigos
Cada endpoint documenta en la referencia qué códigos puede devolver. Podemos añadir códigos nuevos en v1 (siempre con un status HTTP coherente): trata un código desconocido según su status.
| HTTP | Código | Significado y qué hacer |
|---|---|---|
| 400 | invalid_cursor | El cursor no es válido (manipulado o de otro listado). Repite la consulta sin cursor. |
| 401 | invalid_api_key | Falta la API key o no es válida, está revocada o ha caducado. |
| 403 | api_disabled | El producto (areas, employees...) no está habilitado en el panel para el entorno de la API key (live o test). |
| 403 | endpoint_disabled | El administrador desactivó este endpoint concreto en el panel. |
| 403 | insufficient_scope | La API key no tiene el scope que exige el endpoint (p. ej. employees:write). |
| 403 | ip_not_allowed | La IP de origen no está en la lista de IPs permitidas del producto. |
| 403 | new_recipients_paused | xYago pausó los envíos del remitente a destinatarios nuevos (demasiados teléfonos sin xYago). Los destinatarios que ya recibieron mensajes siguen funcionando. Contacta con xYago. |
| 403 | verify_paused | xYago pausó Verify para el remitente (demasiados teléfonos sin xYago). Las verificaciones ya iniciadas se pueden seguir comprobando. Contacta con xYago. |
| 404 | not_found | El recurso no existe o pertenece a otra empresa (nunca se distingue). |
| 404 | sender_not_found | El sender_id no es un remitente de tu cuenta. |
| 404 | template_not_found | El remitente no tiene una plantilla con ese nombre. |
| 404 | recipient_not_on_xyago | POST /verify/start: el teléfono no usa xYago. No se envió nada ni se reintentará: envía el código por tu otro canal (p. ej. SMS). |
| 409 | area_already_exists | Ya existe un área con ese nombre bajo el mismo padre. |
| 409 | external_id_already_exists | El external_id ya está asignado a otro empleado de la empresa. |
| 409 | external_id_in_progress | Otra petición está creando ahora mismo un empleado con ese external_id. Reintenta en unos segundos (y consulta antes por external_id). |
| 409 | employee_already_exists | Ya hay un empleado con ese phone_number en la empresa. |
| 409 | email_already_registered | El email ya lo usa otro empleado. |
| 409 | document_number_already_exists | El document_number ya lo usa otro empleado de la empresa. |
| 409 | vacation_already_decided | La solicitud ya estaba aprobada o rechazada. |
| 409 | vacation_overlap | El empleado ya tiene vacaciones aprobadas en ese rango. |
| 409 | time_entry_overlap | El tramo se solapa con otro tramo del empleado en la empresa. |
| 409 | sender_not_approved | El remitente aún no está aprobado por xYago (en live solo envían remitentes aprobados). |
| 409 | sender_suspended | xYago suspendió el remitente (o la cuenta). Contacta con xYago. |
| 409 | template_not_approved | La plantilla no está aprobada (en sandbox también vale una en draft). |
| 409 | template_paused | xYago pausó la plantilla (p. ej. por quejas de los usuarios). No se puede usar hasta que xYago la reactive; contacta con xYago. |
| 409 | idempotency_key_reused | Ya usaste esa Idempotency-Key con otro cuerpo. Usa una clave nueva por envío distinto. |
| 409 | undeliverable | El mensaje no se puede entregar a este destinatario. No reintentes. |
| 409 | verification_expired | El código caducó (10 minutos). Inicia una verificación nueva. |
| 409 | max_attempts_reached | Se agotaron los 5 intentos de la verificación. Inicia una nueva. |
| 409 | verification_not_pending | La verificación ya no admite códigos: ya se verificó (un solo uso), se sustituyó por otra más reciente (canceled) o no se pudo enviar (failed). |
| 409 | sandbox_number_exists | El número ya es un número de prueba confirmado. |
| 422 | validation_error | El cuerpo o los parámetros no cumplen el esquema (campo obligatorio, formato, campo desconocido...). message indica el campo. |
| 422 | invalid_parent_id | parent_id no corresponde a un área activa de la empresa. |
| 422 | invalid_employee_data | xYago rechazó los datos del empleado. Revisa los campos. |
| 422 | employee_has_no_job | Se intentó cambiar el puesto de un empleado sin puesto en la empresa. |
| 422 | invalid_employee_id | employee_id no corresponde a un empleado de la empresa. |
| 422 | invalid_vacation | xYago rechazó la solicitud de vacaciones. |
| 422 | vacation_type_not_configured | La empresa no tiene configurado el tipo de ausencia de vacaciones en xYago. |
| 422 | vacation_requires_document | La empresa exige un documento de soporte para las vacaciones; no se pueden solicitar por la API. |
| 422 | invalid_date_range | Rango from..to no válido: from posterior a to o más de 31 días. |
| 422 | invalid_time_range | El tramo termina en el futuro. |
| 422 | invalid_time_entry | xYago rechazó el tramo. |
| 422 | invalid_phone | to no es un teléfono E.164 válido (al menos 10 dígitos). |
| 422 | template_variables_mismatch | El número de variables no coincide con el de la plantilla (variables_count). |
| 422 | invalid_variables | Una variable supera 256 caracteres o contiene un enlace. |
| 422 | invalid_button_variables | Falta el valor de button_variables de un botón de enlace con variable, sobra uno (el botón no tiene variable) o no es válido (texto, máx. 200 caracteres). |
| 422 | sandbox_recipient_not_allowed | Con una clave xy_test_ solo se envía a los números de prueba confirmados en el panel. |
| 422 | invalid_message | xYago rechazó el contenido del mensaje. |
| 429 | rate_limited | Se superó el límite de peticiones por minuto de la API key o, en POST /messages, un tope de envío del remitente (mensajes por minuto, por destinatario y día, destinatarios nuevos por día) o, en Verify, un tope de códigos (espera entre códigos, por teléfono, por remitente) o de códigos erróneos por hora. Espera los segundos de Retry-After. |
| 500 | internal_error | Error inesperado de xYago. Reintenta con backoff; si persiste, contacta a soporte con el X-Request-Id. |
| 502 | upstream_error | Un servicio interno de xYago falló o no respondió a tiempo. Reintenta con backoff (en las escrituras, comprueba antes si ya se aplicaron). |
| 503 | limits_unavailable | Los límites de envío no se pueden comprobar ahora mismo; por seguridad no se envía. Reintenta con backoff y la misma Idempotency-Key. |
| 503 | messaging_not_configured | La mensajería no está disponible temporalmente. Contacta con soporte. |
| 503 | import_queue_unavailable | No se pudo encolar la importación. Reintenta más tarde. |
Qué reintentar
| Status | ¿Reintentar? |
|---|---|
400, 401, 403, 404, 409, 422 | No: corrige la petición o la configuración. Excepción: 409 external_id_in_progress (reintenta en unos segundos). |
429 | Sí, después de los segundos de Retry-After. |
500, 502, 503, errores de red / timeout | Sí, con backoff exponencial (p. ej. 1 s, 2 s, 4 s... máximo 5 intentos). En escrituras, comprueba antes si ya se aplicaron (ver idempotencia). |
Errores de validación
422 validation_error indica qué campo falla en message, con el
formato campo: motivo (varios separados por ; ). Los campos
desconocidos también se rechazan: por ejemplo enviar company_id en un alta
devuelve 422, porque la empresa sale de la API key.
{
"error": {
"code": "validation_error",
"message": "phone_number: String should match pattern '^\\+[1-9][0-9]{6,14}$'; company_id: Extra inputs are not permitted"
}
}
Cuando contactes con soporte
Incluye el X-Request-Id de la respuesta, el método y la ruta, la hora (UTC) y
el entorno (live/test). Nunca envíes la API key.