Manejo de errores
Cada API de Migo devuelve respuestas envueltas en un envelope CustomResponse<T>.
La forma del envelope es:
interface CustomResponse<T> {
success: boolean;
message?: string;
data?: T;
errors?: { code: string; message: string }[];
}
Nota que code es un string (p. ej. "7100"), y errors es un array de objetos { code, message }. No existe campo statusCode, error.name ni error.detail en el payload del wire — el name (p. ej. USER_NOT_FOUND) es la clave interna de MigoNameErrors, no parte del body de la respuesta.
Éxito
{
"success": true,
"message": "ok",
"data": { "...": "..." }
}
Error
{
"success": false,
"message": "Validation failed",
"errors": [
{
"code": "7100",
"message": "User not found in the system."
}
]
}
Mapeo de status codes
| HTTP status | Cuándo se devuelve |
|---|---|
200 OK | Éxito (incluyendo jobs asíncronos que devuelven un id de batch/job en el body) |
201 Created | Recurso creado (p. ej. creación de estado de cuenta aceptada) |
204 No Content | Éxito, sin body |
400 Bad Request | Validación de DTO falló |
401 Unauthorized | JWT faltante / vencido / inválido |
403 Forbidden | Autenticado pero permiso denegado |
404 Not Found | El recurso no existe |
409 Conflict | Conflicto de estado del recurso |
422 Unprocessable Entity | Validación semántica falló (p. ej. tarjeta vencida) |
500 Internal Server Error | Bug de Migo — repórtalo con el timestamp y los detalles de la solicitud |
502 Bad Gateway | Procesador upstream inalcanzable |
503 Service Unavailable | Mantenimiento programado o caída parcial |
504 Gateway Timeout | Timeout del procesador upstream |
Rangos de códigos de error de negocio
Migo usa dos espacios distintos de códigos de error de negocio dependiendo de la API que estés llamando. El Wallet Gateway y el CMS Backoffice exponen un code string dentro del array errors[]; el Middleware usa un envelope separado con un ownCode. Los rangos numéricos no se traslapan y los nombres de los campos difieren.
Wallet Gateway, CMS Backoffice — 7000–8099
Estos códigos aparecen como string en cada entrada del array errors del envelope estándar CustomResponse mostrado arriba (p. ej. "code": "7100").
| Rango | Significado |
|---|---|
7000–7099 | General / validación / terminal-procesador |
7100–7199 | Usuarios (incl. OTP, FCM, password, auth-user) |
7200–7299 | Tarjetas (incl. tarjetas de terceros, view tokens) |
7300–7399 | Transferencias y pagos en terminal |
7400–7499 | Terminales, negocios y sucursales |
7500–7599 | Liquidaciones y régimen fiscal |
7600–7699 | Clientes, auth, roles, permisos, archivos y redes sociales |
7700–7799 | Configuración de proyecto e integridad de app |
8000–8099 | App / móvil (proceso, balance, permisos) |
Los rangos 7800–7899 y 7900–7999 actualmente no se usan.
Lista completa en el Catálogo de errores.
Middleware (Payment Links, payments, tokenization) — ownCode
El Middleware usa un envelope separado (ErrorResponseDto) y lleva el error de negocio dentro de un objeto error anidado, donde ownCode es un valor numérico pequeño (p. ej. "2002", "2007", "5000", "5004"). La forma es:
interface ErrorResponseDto {
message?: string;
error?: {
code?: number; // status HTTP asociado al error
ownCode?: string; // código de error de negocio de Migo
message?: string; // descripción legible
};
}
Estos no chocan con el espacio 7000–8099 porque viven en un envelope y ruta de campo diferentes (error.ownCode, no errors[].code).
| Rango | Significado |
|---|---|
2000–2099 | Creación de transacción / validación de negocio (usuario excluido, monto fuera de rango, etc.) |
5000–5099 | Validación de DTO / configuración (campos faltantes, slug de cliente desconocido) |
Lista completa en Catálogo de errores → ownCodes de Payment Link / Middleware.
Cuando envuelvas llamadas a ambas superficies en el mismo cliente, ramifica por ruta de campo:
const code = response?.errors?.[0]?.code ?? response?.error?.ownCode;
Semántica de reintentos
| Clase de error | ¿Reintentar? | Estrategia |
|---|---|---|
| Network timeout | Sí | Exponential backoff |
500 / 502 / 504 | Sí | Exponential backoff, máximo 3 reintentos |
503 | Sí | Exponential backoff con techo amplio (hasta 5 min) |
400 / 422 | No | Corrige la solicitud |
401 | No (refresca en su lugar) | Refresca el token, luego reintenta |
403 / 404 / 409 | No | No reintentes |
Patrón cliente
async function call<T>(fn: () => Promise<T>, attempt = 0): Promise<T> {
try {
return await fn();
} catch (err) {
const status = err.response?.status;
if (status === 401) {
await refreshToken();
return call(fn, attempt + 1);
}
if ([500, 502, 503, 504].includes(status) && attempt < 3) {
const wait = 2 ** attempt * 500;
await new Promise(r => setTimeout(r, wait));
return call(fn, attempt + 1);
}
throw err;
}
}
Reportar incidentes
Al abrir un ticket de soporte incluye:
- El timestamp de la solicitud en UTC (Migo lo correlaciona con la traza interna)
- URL completa de la solicitud, método y headers (oculta el Bearer token)
- Body de la solicitud (oculta PANs y CVVs)
- Body completo de la respuesta