Manejo de errores
Todos los errores se devuelven en formato Problem JSON (RFC 7807) con Content-Type: application/problem+json.
Estructura
{
"type": "https://api-docs.maxpay.com.ar/errors/receivable-account-already-exists",
"title": "Receivable account already exists",
"status": 409,
"detail": "Ya existe una cuenta recaudadora para este cliente con la misma moneda.",
"instance": "/v1/receivable-accounts",
"code": "receivable-account-already-exists",
"requestId": "req_b3f8a1c2d4e5f6789012345678901234",
"existingResourceId": 1042
}
| Campo | Tipo | Siempre presente | Descripción |
|---|---|---|---|
type | URI | Sí | URI que identifica el tipo de problema. Apunta al catálogo de errores. |
title | string | Sí | Resumen corto en inglés. Estable entre versiones del problema. |
status | integer | Sí | Código HTTP que corresponde. |
detail | string | Sí | Descripción humana en español del problema concreto. Puede variar entre ocurrencias. |
instance | URI relativa | Sí | Path del request que generó el error. |
code | string | Sí | Identificador estable del error (kebab-case). Apto para mapear en el ERP. |
requestId | string | Sí | ID único del request. Inclulir en reportes de soporte. |
invalidParams | array | Solo en 400 | Detalle de campos inválidos. |
| Otros campos | variable | No | Contexto adicional específico del problema (ej. existingResourceId, candidates). |
Errores de validación (400)
Cuando el problema es el formato del request (campos faltantes, tipos incorrectos, valores fuera de rango), la respuesta incluye invalidParams:
{
"type": "https://api-docs.maxpay.com.ar/errors/validation",
"title": "Validation error",
"status": 400,
"detail": "El request tiene campos inválidos.",
"instance": "/v1/receivables",
"code": "validation",
"requestId": "req_...",
"invalidParams": [
{ "name": "amount", "reason": "El monto debe ser positivo" },
{ "name": "currencyCode", "reason": "El código de moneda es requerido" }
]
}
Categorías por código HTTP
| HTTP | Categoría | Ejemplos |
|---|---|---|
400 | Formato del request inválido | Schema mal, tipos incorrectos, campos faltantes |
401 | Autenticación fallida | Token inválido, expirado, ausente |
403 | Autorizado pero sin permiso | Falta scope en el token, recurso pertenece a otro customer |
404 | Recurso no existe | ID inexistente o no accesible |
409 | Conflicto de estado | Recurso ya existe, idempotency-key reusada con body distinto |
422 | Regla de negocio | Cuenta no habilitada para deudas, transición de estado inválida |
429 | Rate limit excedido | Demasiados requests por minuto |
500 | Error interno | Bug en Max Pay |
502/504 | Falla en proveedor externo | Proveedor bancario no disponible, timeout en COELSA |
Catálogo completo
Ver Catálogo de errores para la lista exhaustiva de códigos, mensajes y contexto.
Manejo recomendado en el ERP
async function callMaxpay(path, options) {
const res = await fetch(`${BASE_URL}${path}`, options);
if (res.ok) return await res.json();
const problem = await res.json();
const requestId = problem.requestId;
switch (problem.code) {
case 'idempotency-key-reuse':
// Cuerpo diferente con misma key — bug del integrador, alertar
throw new IntegrationError(problem, requestId);
case 'receivable-account-already-exists':
// Recurso ya creado — usar el ID existente
return await callMaxpay(`/v1/receivable-accounts/${problem.existingResourceId}`, {
method: 'GET',
headers: options.headers
});
case 'rate-limit-exceeded':
const retryAfter = parseInt(res.headers.get('Retry-After'), 10);
await sleep(retryAfter * 1000);
return await callMaxpay(path, options);
case 'external-provider-unavailable':
case 'external-provider-timeout':
// Reintentar con backoff exponencial
throw new RetryableError(problem, requestId);
default:
throw new MaxpayError(problem, requestId);
}
}
Para reportar un incidente
Si necesitás reportar un error a soporte, incluí siempre el requestId y el code. Esto permite encontrar la traza completa del request en nuestros logs.