Códigos de error


Cómo leer un error

Hay tres capas distintas y conviene no confundirlas:

Capa Ejemplo Qué significa
HTTP 422 Cómo respondió nuestra API
Validación errors.payment_card.cvv Tu petición no cumple las reglas. Se arregla en tu código
Código de red 51, M12, V68 La operación llegó a la red y la red decidió. No siempre se arregla reintentando

Un pago rechazado no es un error de tu integración: la petición fue correcta y el resultado fue «no». Devuelve 200 u 422 según el caso, y siempre trae el estado de la transacción para que sepas en qué quedó.

{warning} Nunca reintentes automáticamente un rechazo. Si la razón fue fondos insuficientes o una tarjeta bloqueada, reintentar da el mismo resultado y algunos emisores penalizan los reintentos.

Códigos HTTP

Código Cuándo Qué hacer
200 La operación se procesó. Revisa el estado del cuerpo: puede ser un rechazo Leer status / success
201 Se creó algo (una reserva autorizada, por ejemplo) Guardar el id
202 Estado indeterminado: no sabemos aún el resultado No reintentar. Esperar el webhook o consultar
400 Regla de negocio incumplida (por ejemplo, borrar un suscriptor con suscripción activa) Leer message
401 Falta el token o no es válido Ver Autenticación
403 Token válido pero sin permiso, comercio deshabilitado, o cobro que ya no acepta pagos Leer message
404 El recurso no existe, o es de otro comercio, o del otro ambiente Revisar el id y el tipo de token
409 Conflicto: cobro ya aplicado, o Idempotency-Key reutilizada con otros parámetros Leer message
422 Validación, o la red rechazó Leer errors o el estado
429 Ya hay una operación igual en curso Esperar el resultado, no reintentar
5xx Error de nuestro lado o de la red Reintentable con espera

Errores de validación

Siempre tienen la misma forma: un message con el primer error y un objeto errors con todos, indexados por el nombre del campo.

{danger} Validación code: 422

{
"message": "El campo payment_card.cvv es obligatorio.",
"errors": {
"payment_card.cvv": ["El campo payment_card.cvv es obligatorio."],
"customer_payer.email": ["El campo customer_payer.email debe ser un correo válido."]
}
}

Las claves de errors usan notación de punto para los campos anidados. Úsalas para marcar el campo exacto en tu formulario en lugar de mostrar un mensaje genérico.

{warning} Una excepción: generar un pago devuelve solo el mapa de errores, sin message ni la envoltura errors:

{
    "payment.amount": ["The payment.amount field is required."]
}

Y si en esa misma llamada omites payment.currency_type, la validación se detiene ahí: recibirás ese único error y ninguno más, porque los límites de monto dependen de la moneda.

Conflictos de idempotencia

Las escrituras de suscripciones aceptan el header Idempotency-Key. Cuando esa clave choca, el cuerpo no tiene la forma de un error de validación: trae un objeto error con su propio type.

{danger} Misma clave, parámetros distintos code: 409

{
"error": {
"type": "idempotency_error",
"message": "La Idempotency-Key ya fue usada con parámetros distintos."
}
}

{danger} Misma clave, misma petición todavía en curso code: 409

{
"error": {
"type": "idempotency_error",
"message": "Una solicitud con esta Idempotency-Key aún está en proceso."
}
}

Cuando en cambio repites exactamente la misma llamada con la misma clave, te devolvemos la respuesta original con el header Idempotency-Replayed: true y sin volver a ejecutar el cobro.

Detalle Comportamiento
Vigencia de la clave 24 horas
Métodos afectados POST, PUT, PATCH, DELETE
Rutas Las escrituras de /api/v1/subscriptions/*, /api/v1/payment/* y /api/v1/mit/pre-authorizations/*. Ver el detalle en Convenciones
Alcance de la clave Por comercio y usuario del token
Respuestas 5xx No se memorizan, para que puedas reintentar un fallo transitorio

{success} Úsala en todo cobro. El caso que evita: cobras, tu proceso se cae antes de guardar la respuesta, y al reintentar no sabes si el primer intento llegó. Con la misma Idempotency-Key el segundo intento te devuelve la respuesta original en vez de cobrar dos veces.

{info} La clave la eliges tú: una distinta por operación, no por reintento. Un UUID generado al empezar el cobro y reutilizado en todos los reintentos de esa misma operación es lo habitual.

Rechazos de la red

Los más frecuentes. El código llega en response_code de la transacción y, cuando no fue aprobada, también en error.code con su message, su retryable y su action.

{
    "status": "Rechazada",
    "status_key": "rejected",
    "response_code": "51",
    "error": { "code": "51", "message": "…", "retryable": false, "action": "contact_issuer" }
}

{info} El catálogo completo, con todos los códigos y su retryable, se consulta en vivo en GET /api/v1/resources/mit/response-codes. Léelo de ahí en vez de copiar esta tabla: se mantiene sola.

Código Qué pasó Qué hacer
00 Aprobada
05 Negada: la tarjeta puede estar bloqueada, o el emisor no respondió Pedir otro medio de pago
51 Fondos insuficientes Pedir otra tarjeta o un monto menor
54 Tarjeta vencida Pedir la fecha correcta u otra tarjeta
57 El emisor no permite este tipo de transacción Pedir otro medio de pago
61 Excede el límite de la tarjeta Pedir otra tarjeta o un monto menor
91 El emisor no está disponible Reintentable más tarde

Qué es seguro reintentar

error.retryable Ejemplos Qué hacer
false 05, 51, 54, 57, 61 (fondos, vencida, bloqueada, límite) No reintentes. El resultado será el mismo y algunos emisores penalizan la insistencia. Pide otro medio de pago
true 91, E99, S01, S10, S11 (la red o un servicio interno falló) Reintenta con espera creciente
T01 y cualquier 202 Estado indeterminado: no reintentes. No sabemos si la operación se procesó. Consulta el estado antes de hacer nada

{danger} La diferencia entre «falló» y «no sé si falló» es la que produce cobros dobles. Ante T01 o un 202, consulta con estado de transacción antes de reenviar nada.

Reserva de cupo

Estos son propios de las reservas de cupo.

Código HTTP Qué pasó
MIT_PRODUCTION_KEY_REQUIRED 422 Intentaste autorizar con llave de prueba; una reserva retiene fondos reales
MIT_AMOUNT_EXCEEDS_AUTHORIZED 422 El cobro final supera lo reservado
MIT_EXPIRED 422 La reserva venció; hay que crear una nueva
MIT_ALREADY_CONFIRMED 409 Esta reserva ya tiene su cobro aplicado
MIT_VOID_WINDOW_CLOSED 422 Ya cerró la ventana para liberar (24 h antes del vencimiento). Deja que venza
MIT_FRANCHISE_NOT_ENABLED 422 Esa franquicia no está habilitada para reservas en tu comercio
MIT_INDETERMINATE 202 No recibimos respuesta de la red. No reintentes
MIT_IN_PROGRESS 429 Ya hay una autorización en curso para esta reserva
M01 409 La reserva ya fue confirmada
M02 422 La operación referenciada no es una reserva pre-autorizada
M04 422 La reserva está vencida en la red
M05 422 La reserva no fue aprobada, así que no hay cupo que cobrar
M06 422 La red no encuentra la operación. Solo conserva 30 días
M08 / M10 / M11 422 La franquicia o el banco emisor no permiten reservas
M12 422 El valor del cobro final no corresponde al reservado
309 422 El tipo de transacción MIT no admite 3DS
310 422 El ECI enviado no es válido: debe ser 05, 06 o 07
319 / 320 422 Enviaste el objeto 3DS de la otra franquicia

Anulación y reversión

Código Qué pasó
A01 Pasó la fecha permitida para anular
A03A06 La operación no está en un estado que admita anulación
A07 No se puede anular una operación incremental
V39 No se puede liberar una reserva que ya fue cobrada
V40 La reserva no está en fecha válida para liberarse
V42 La operación indicada no es anulable

Errores de transporte y cifrado

Código HTTP Qué pasó Qué hacer
T01 202 Se agotó el tiempo de espera con la red. No sabemos si la operación quedó registrada No reintentar. Consultar el estado
E99 502 Error interno de la red Reintentable con espera
S10 / S11 500 Fallo de cifrado con la red Contactar a soporte

{danger} T01 y MIT_INDETERMINATE son los dos casos en que reintentar es peligroso: si la operación sí se aplicó, un reintento la duplica. Consulta el estado o espera el webhook.

Catálogo en vivo

En lugar de copiar esta tabla a tu código, consúltala:

GET /api/v1/resources/mit/response-codes

Cada entrada trae:

Campo Para qué
code El código
message El mensaje pensado para el comercio
action Qué hacer
retryable Si tiene sentido reintentar

Qué mostrarle a tu cliente

Tenemos dos mensajes para cada código y sirven para cosas distintas:

Campo Audiencia Ejemplo
Mensaje al pagador El tarjetahabiente «Transacción declinada. Fondos insuficientes»
Mensaje al comercio Tu operador o tu log «Fondos insuficientes. Pídele al cliente otra tarjeta»

En la respuesta de una transacción, authorization_message_customer y description traen el mensaje que se le puede mostrar al cliente tal cual.

{warning} No le muestres al cliente el código crudo ni el mensaje interno. Un M12 en pantalla no le dice nada a nadie, y los mensajes internos pueden mencionar tu configuración.