Webhooks
Los webhooks entregan notificaciones en tiempo real a su servidor cuando un pago cambia de estado. En lugar de consultar la API en busca de actualizaciones, su sistema recibe una solicitud POST que describe el cambio.
Configuración de webhooks
Los endpoints de webhook se configuran durante el onboarding del comercio. Contacte al equipo de Inyo para:
- Proporcionar su(s) URL(s) de webhook
- Configurar la autenticación (Basic auth)
Payloads de los eventos
Cada cambio de estado se envÃa como una solicitud POST a su URL de webhook, con Content-Type: application/json. El campo event indica qué tipo de pago cambió — PULL, PUSH o CHECK. Los campos de todos los eventos:
| Campo | Tipo | Notas |
|---|---|---|
agentId | string | Identificador de su agente |
event | string | PULL, PUSH o CHECK |
status | string | Estado del pago después del cambio. Mismo valor que newStatus |
statusCode | string | 00 aprobado, 99 rechazado |
statusDescription | string | Descripción legible del cambio o del motivo del rechazo |
paymentId | uuid | Identificador del pago en Inyo |
externalPaymentId | string | El externalPaymentId enviado al crear el pago |
amount | object | { "total": number, "currency": string } — monto y moneda de origen (ISO 4217) |
recipientAmount | object | Solo PUSH. { "total": number, "currency": string } — monto entregado al destinatario, presente cuando el pago tiene conversión de moneda |
eventDate | string | Momento en que se generó la notificación, ISO 8601 en UTC |
oldStatus | string | null | Estado del pago antes del cambio |
newStatus | string | Estado del pago después del cambio |
1. PULL
Se dispara cuando un pago pull es autorizado, capturado, desafiado, rechazado, anulado o reembolsado.
{
"agentId": "YOUR.AGENT",
"event": "PULL",
"status": "AUTHORIZED",
"statusCode": "00",
"statusDescription": "Payment authorized successfully",
"paymentId": "469670e2-31e3-4700-b9f2-abee99418dc4",
"externalPaymentId": "order-12345",
"amount": {
"total": 95.00,
"currency": "USD"
},
"eventDate": "2026-10-08T16:31:02.120Z",
"oldStatus": "PENDING",
"newStatus": "AUTHORIZED"
}
Valores de estado: PENDING, AUTHORIZED, CAPTURED, CHALLENGE, DECLINED, VOIDED, REFUNDED.
flowchart TD
P[PENDING] -->|3DS| C[CHALLENGE]
P --> A[AUTHORIZED]
P -->|capture: true| K[CAPTURED]
P -->|rechazado| D[DECLINED]
C --> A
C -->|rechazado| D
A -->|captura| K
A -->|void| V[VOIDED]
K -->|reembolso| R[REFUNDED]
Con capture: true el pago pasa directo a CAPTURED; sin él, se queda en AUTHORIZED hasta que lo capture o anule. DECLINED, VOIDED y REFUNDED son finales.
2. PUSH
Se dispara cuando un pago push es aceptado, pagado o rechazado. La creación responde PENDING y el resultado llega después por webhook.
{
"agentId": "YOUR.AGENT",
"event": "PUSH",
"status": "CAPTURED",
"statusCode": "00",
"statusDescription": "Payment captured successfully",
"paymentId": "c9036407-555a-46ed-a602-e8179857b28f",
"externalPaymentId": "payout-12345",
"amount": {
"total": 98.20,
"currency": "USD"
},
"recipientAmount": {
"total": 1775.00,
"currency": "MXN"
},
"eventDate": "2026-10-08T18:30:10.935Z",
"oldStatus": "AUTHORIZED",
"newStatus": "CAPTURED"
}
Valores de estado: PENDING, AUTHORIZED, CAPTURED, DECLINED.
flowchart TD
A[PENDING<br/>push aceptado] -->|destinatario pagado| B[AUTHORIZED]
B --> C[CAPTURED<br/>fondos entregados]
A -->|rechazado| D[DECLINED]
Un push exitoso envÃa dos webhooks en secuencia, AUTHORIZED y luego CAPTURED. Trate CAPTURED como el éxito final y DECLINED como el fallo final; en un rechazo, statusDescription trae el motivo.
3. CHECK
Se dispara cuando termina una verificación de Check Card Account. No se mueven fondos.
{
"agentId": "YOUR.AGENT",
"event": "CHECK",
"status": "AUTHORIZED",
"statusCode": "00",
"statusDescription": "Payment authorized successfully",
"paymentId": "5b0e2f4c-8d1a-4c7e-9a33-2f6b1d0e7c58",
"externalPaymentId": "check-12345",
"amount": {
"total": 0.00,
"currency": "USD"
},
"eventDate": "2026-10-08T14:02:44.508Z",
"oldStatus": "CHALLENGE",
"newStatus": "AUTHORIZED"
}
Valores de estado: AUTHORIZED (tarjeta verificada), CHALLENGE, DECLINED, VOIDED.
Entrega y confiabilidad
- Autenticación: cuando Basic auth está configurado, cada entrega lleva
Authorization: Basic <credenciales>. ValÃdelo en cada solicitud. Las entregas no están firmadas. - Reintentos: las respuestas distintas de 2xx y los timeouts se reintentan hasta el lÃmite de intentos configurado para su cuenta. Responda
2xxde inmediato y procese de forma asÃncrona. - Duplicados: los reintentos pueden entregar la misma notificación más de una vez. Use
(paymentId, newStatus)como clave en su manejador y trate las repeticiones como no-op. - Orden: no está garantizado, y
eventDatese define cuando se genera la notificación, no cuando cambió el estado. Si la secuencia importa, compare eloldStatusrecibido con el estado que tiene guardado; si no coincide, ignore la entrega y concilie con una consulta. - Fuente de verdad: el webhook es una notificación, no el pago completo. Confirme el estado — y lea datos de tarjeta, facturación o comisiones — con el endpoint GET de pago antes de completar pedidos.
Ejemplo de manejador (Node.js)
app.post('/webhooks/inyo', async (req, res) => {
// Confirma de inmediato
res.status(200).send('OK');
const notification = req.body;
const { externalPaymentId, paymentId, event, newStatus } = notification;
if (await alreadyProcessed(paymentId, newStatus)) return;
switch (newStatus) {
case 'AUTHORIZED':
markAsAuthorized(externalPaymentId);
break;
case 'CAPTURED':
// PULL: fondos liquidados — completa el pedido. PUSH: destinatario pagado.
event === 'PUSH'
? markPayoutDelivered(externalPaymentId)
: fulfillOrder(externalPaymentId);
break;
case 'DECLINED':
notifyDecline(externalPaymentId, notification.statusDescription);
break;
case 'VOIDED':
cancelOrder(externalPaymentId);
break;
case 'REFUNDED':
processRefund(externalPaymentId, notification.amount.total);
break;
}
await markProcessed(paymentId, newStatus);
});
