Códigos de error
Todos los errores de la API de Sangho devuelven un objeto JSON estructurado y plano (sin claves anidadas) con un código de error de negocio, un mensaje legible y un enlace directo a la sección de esta página que lo explica. Al hacer clic en un enlace doc_url recibido en su consola o en sus registros, llegará aquí y se resaltará automáticamente la fila del código correspondiente.
Estructura de un error
| Champ | Type | Requis | Description |
|---|---|---|---|
type | string | Requis | Categoría del error: uno de los 7 valores que se indican a continuación. Útil para un tratamiento genérico (mostrar un mensaje por categoría). |
code | string | Requis | Código de negocio preciso de Sangho, p. ej. AMOUNT_TOO_SMALL. Es la fuente de verdad para la gestión detallada de los casos de error y debe preferirse a type y al código HTTP. |
message | string | Requis | Descripción legible del error, en francés |
status | integer | Requis | Código HTTP asociado: 400, 401, 403, 404, 409, 422, 429, 500 |
doc_url | string | Optionnel | Enlace directo a la fila de esta página correspondiente al código, p. ej. https://docs.sangho.ga/errors#AMOUNT_TOO_SMALL |
param | string | Optionnel | Campo implicado en los errores de validación (422) |
errors | object | Optionnel | Detalle por campo para los errores de validación de varios campos — {`{ "amount": ["..."] }`} |
request_id | string | Optionnel | Identificador de la solicitud, que debe facilitar al soporte si es necesario |
Las 7 categorías (type)
Cada error pertenece a una de estas 7 categorías. El SDK de JavaScript expone la misma taxonomía en err.type, lo que resulta práctico para un tratamiento genérico por ramas (reintento, redirección al inicio de sesión, etc.) antes de descender al nivel del code preciso si es necesario.
| type | Estados HTTP típicos | Significado |
|---|---|---|
AUTHENTICATION_ERROR | 401 | Clave API ausente, no válida o caducada |
PERMISSION_ERROR | 403 | Identidad reconocida, pero acción no autorizada (clave pública, cuenta restringida, plan insuficiente…) |
NOT_FOUND_ERROR | 404 | Recurso no encontrado |
CONFLICT_ERROR | 409 | Conflicto: idempotency key reutilizada, duplicado |
VALIDATION_ERROR | 422 | Solicitud sintácticamente correcta pero no válida para el negocio |
RATE_LIMIT_ERROR | 429 | Cuota de llamadas superada |
API_ERROR | 500 | Error en Sangho |
Códigos HTTP estándar
El código HTTP indica la categoría del error. Utilícelo para orientar su lógica de reintentos y de visualización.
| Code | Description |
|---|---|
200 | Éxito: solicitud procesada |
201 | Recurso creado correctamente |
400 | Solicitud no válida: JSON mal formado o cabeceras incorrectas |
401 | Clave API ausente, caducada o no válida |
403 | Permiso insuficiente: la App no tiene acceso a este recurso o a esta acción |
404 | Recurso no encontrado: ID incorrecto o recurso eliminado |
409 | Conflicto: idempotency key reutilizada con un cuerpo de solicitud distinto |
422 | Validación de negocio fallida: regla de negocio no respetada |
429 | Demasiadas solicitudes: se ha alcanzado el límite de peticiones (rate limiting), aplique un backoff |
500 | Error interno de Sangho: vuelva a intentarlo con un backoff exponencial |
Códigos de negocio
Todos los códigos siguen el estándar SCREAMING_SNAKE_CASE, sin prefijo. Enlace sus gestores de errores con code y no con el estado HTTP: el código es la fuente de verdad.
Autenticación — 401
| Code | Description |
|---|---|
MISSING_API_KEY | Clave API ausente: indíquela mediante Authorization: Bearer <clave> |
INVALID_API_KEY | Clave API no válida, revocada o mal formada |
EXPIRED_API_KEY | Clave API caducada: genere una nueva desde su panel |
INVALID_TOKEN | Token JWT no válido o caducado |
AUTHENTICATION_FAILED | Fallo de autenticación genérico: compruebe la cabecera Authorization |
Autorización — 403
Estos errores se devuelven cuando se reconoce la identidad, pero la operación no está autorizada para esta clave, esta cuenta o este plan.
| Code | Description |
|---|---|
PERMISSION_DENIED | Permiso denegado: su clave no está autorizada para realizar esta acción sobre este recurso |
PUBLIC_KEY_NOT_ALLOWED | Esta ruta requiere una clave secreta (sk_prod_ o sk_test_). No exponga nunca su clave secreta en el cliente |
PLATFORM_PARTNER_REQUIRED | Esta ruta (connect.*) está reservada a las Apps con el estado de Socio de Plataforma: haga la solicitud desde su panel, la aprobación es manual |
APP_DISABLED | La aplicación está desactivada: reactívela desde su panel |
APP_NOT_VERIFIED | Aplicación no verificada: KYC pendiente de aprobación |
INSUFFICIENT_PERMISSIONS | Permisos insuficientes para este recurso o esta acción |
SANDBOX_ONLY | Esta ruta está reservada al entorno sandbox: utilice una clave sk_test_ |
CURRENCY_NOT_IN_PLAN | La moneda solicitada está activa en Sangho pero no está incluida en su plan actual: pase a un plan superior para activarla |
COMPANY_BLACKLISTED | Esta cuenta ha sido incluida en la lista negra y ya no tiene acceso a la plataforma: contacte con el soporte |
COMPANY_PAYMENTS_DISABLED | Los pagos entrantes están actualmente desactivados para esta cuenta |
COMPANY_PAYOUTS_DISABLED | Las transferencias salientes están actualmente desactivadas para esta cuenta |
COMPANY_SANDBOX_ONLY | Esta cuenta está restringida por el momento al modo de prueba (sandbox) |
COMPANY_KYC_REQUIRED | Se requiere la verificación KYC antes de poder procesar pagos |
El código PERMISSION_DENIED lo devuelve en particular POST /v1/reset cuando se invoca con una clave de producción (sk_prod_). Esta ruta borra todos los datos de la aplicación y solo es accesible en el sandbox. Utilice una clave sk_test_ para acceder a ella.
Recurso no encontrado — 404
| Code | Description |
|---|---|
NOT_FOUND | Recurso no encontrado: ID incorrecto, recurso eliminado o acceso prohibido |
CUSTOMER_NOT_FOUND | Ningún Customer con este identificador para esta aplicación |
PRODUCT_NOT_FOUND | Ningún Product con este identificador |
PAYMENT_INTENT_NOT_FOUND | Ningún PaymentIntent con este identificador |
TRANSACTION_NOT_FOUND | Ninguna Transaction con este identificador |
REFUND_NOT_FOUND | Ningún Refund con este identificador |
INVOICE_NOT_FOUND | Ninguna Invoice con este identificador |
SUBSCRIPTION_NOT_FOUND | Ninguna Subscription con este identificador |
CHECKOUT_SESSION_NOT_FOUND | Ninguna CheckoutSession con este identificador |
PAYMENT_METHOD_NOT_FOUND | Ningún PaymentMethod con este identificador |
PAYMENT_LINK_NOT_FOUND | Ningún PaymentLink con este identificador |
RECEIPT_NOT_FOUND | Ningún Receipt con este identificador |
WEBHOOK_NOT_FOUND | Ningún Webhook con este identificador |
SEARCH_NO_RESULTS | Ningún resultado para la búsqueda: compruebe el parámetro ?search= |
Conflicto — 409
| Code | Description |
|---|---|
IDEMPOTENCY_CONFLICT | Ya se ha procesado una solicitud con la misma |
DUPLICATE_EMAIL | Ya existe un Customer con este correo electrónico para esta aplicación |
DUPLICATE_SKU | Ya existe un Product con este SKU |
Validación de negocio — 422
| Code | Description |
|---|---|
VALIDATION_ERROR | Los datos facilitados no son válidos: consulte el campo errors para ver el detalle por campo |
MISSING_FIELD | Falta un campo obligatorio en la solicitud |
INVALID_FIELD | El valor de un campo es incorrecto o está fuera de los valores aceptados |
INVALID_FILTER_PARAM | Un parámetro de filtro (?param=) no corresponde a ningún campo del modelo |
INVALID_CURRENCY | La moneda facilitada no es un código ISO 4217 reconocido o no está activada en Sangho — véanse las |
AMOUNT_TOO_SMALL | Importe inferior al mínimo autorizado (100 XAF por defecto) |
AMOUNT_TOO_LARGE | Importe superior al límite autorizado |
INVALID_STATUS_TRANSITION | La transición de estado solicitada está prohibida (p. ej. reabrir una Invoice anulada) |
PAYMENT_INTENT_UNCANCELABLE | No se puede cancelar este PaymentIntent en su estado actual |
PAYMENT_INTENT_NOT_CONFIRMABLE | No se puede confirmar este PaymentIntent en su estado actual |
PAYMENT_INTENT_NOT_CAPTURABLE | No se puede capturar: el estado debe ser requires_capture |
CAPTURE_AMOUNT_EXCEEDS_ORIGINAL | El importe que se va a capturar supera el importe original del PaymentIntent |
CHECKOUT_SESSION_EXPIRED | La sesión de checkout ha caducado: pida al cliente que inicie una nueva |
SUBSCRIPTION_ALREADY_CANCELED | Esta Subscription ya está cancelada y no se puede cancelar de nuevo |
INVOICE_NOT_DRAFTABLE | Esta Invoice no está en un estado que permita volver a borrador |
Rate limiting — 429
| Code | Description |
|---|---|
RATE_LIMIT_EXCEEDED | Cuota de llamadas a la API superada: consulte la cabecera Retry-After para conocer el tiempo de espera |
TOO_MANY_REQUESTS | Demasiadas solicitudes simultáneas desde esta clave API |
Pagos y Mobile Money
| Code | Description |
|---|---|
INSUFFICIENT_FUNDS | Fondos insuficientes por parte del comprador (Mobile Money o tarjeta) |
PAYMENT_METHOD_NOT_SUPPORTED | Método de pago no activado para esta cuenta de comerciante |
MOBILE_MONEY_TIMEOUT | El comprador no ha confirmado el pago en el plazo previsto (por lo general, 3 min) |
MOBILE_MONEY_REJECTED | El comprador ha rechazado la solicitud de pago en su teléfono |
MOBILE_MONEY_NUMBER_INVALID | Número de Mobile Money incorrecto o no registrado en el operador |
MOBILE_MONEY_LIMIT_REACHED | Se ha alcanzado el límite diario o mensual del operador para este número |
CUSTOMER_BLACKLISTED | El Customer está en la lista negra: no se autoriza ningún pago |
Webhooks e integraciones
| Code | Description |
|---|---|
WEBHOOK_SIGNATURE_INVALID | Firma HMAC-SHA256 no válida: compruebe su webhook secret |
WEBHOOK_ENDPOINT_UNREACHABLE | La URL del webhook no responde: Sangho lo reintentará según la política de reintentos |
TERMINAL_OFFLINE | El terminal de Sangho no es accesible: compruebe la conexión de red |
PDF_NOT_AVAILABLE | El PDF de este documento aún no se ha generado: vuelva a intentarlo en unos instantes |
METHOD_NOT_ALLOWED | Método HTTP no autorizado en este endpoint |
Error del servidor — 500
| Code | Description |
|---|---|
INTERNAL_ERROR | Error interno de Sangho: nuestro equipo ha sido notificado. Vuelva a intentarlo con un backoff exponencial |
DATABASE_ERROR | Error de base de datos: temporal, vuelva a intentarlo en unos instantes |
UPSTREAM_ERROR | Error de un servicio de terceros (operador, pasarela): vuelva a intentarlo o contacte con el soporte |
Estrategia de reintentos recomendada
No todos los errores son iguales. El SDK de JavaScript ya aplica esta lógica automáticamente (véase el SDK de JavaScript), lo que resulta útil saber si llama directamente a la API.
| Código HTTP | Acción recomendada |
|---|---|
| 400 / 422 | No reintentar: corregir los parámetros de la solicitud |
| 401 / 403 | No reintentar: comprobar la clave API, los permisos o el plan |
| 404 | No reintentar: comprobar el ID del recurso |
| 409 | Recuperar la respuesta idempotente ya generada: no crear un duplicado |
| 429 | Esperar el tiempo indicado en la cabecera Retry-After y después reintentar |
| 500 | Reintentar con backoff exponencial (1 s → 2 s → 4 s → 8 s, máx. 3 intentos) |
La cabecera Retry-After se incluye en todas las respuestas 429. Su valor se expresa en segundos.