Webhooks
Os webhooks entregam notificações em tempo real ao seu servidor quando um pagamento muda de status. Em vez de fazer polling na API por atualizações, seu sistema recebe uma requisição POST descrevendo a mudança.
Configuração de Webhooks
Os endpoints de webhook são configurados durante o onboarding do lojista. Entre em contato com a equipe Inyo para:
- Fornecer sua(s) URL(s) de webhook
- Configurar a autenticação (Basic auth)
Payloads dos Eventos
Toda mudança de status é enviada como uma requisição POST para a sua URL de webhook, com Content-Type: application/json. O campo event indica o tipo de pagamento que mudou — PULL, PUSH ou CHECK. Os campos de todos os eventos:
| Campo | Tipo | Observações |
|---|---|---|
agentId | string | Identificador do seu agente |
event | string | PULL, PUSH ou CHECK |
status | string | Status do pagamento após a mudança. Mesmo valor de newStatus |
statusCode | string | 00 aprovado, 99 recusado |
statusDescription | string | Descrição legível da mudança ou do motivo da recusa |
paymentId | uuid | Identificador do pagamento na Inyo |
externalPaymentId | string | O externalPaymentId enviado na criação do pagamento |
amount | object | { "total": number, "currency": string } — valor e moeda de origem (ISO 4217) |
recipientAmount | object | Só PUSH. { "total": number, "currency": string } — valor entregue ao destinatário, presente quando o pagamento tem conversão de moeda |
eventDate | string | Momento em que a notificação foi gerada, ISO 8601 em UTC |
oldStatus | string | null | Status do pagamento antes da mudança |
newStatus | string | Status do pagamento após a mudança |
1. PULL
Disparado quando um pagamento de pull é autorizado, capturado, desafiado, recusado, cancelado ou 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 status: PENDING, AUTHORIZED, CAPTURED, CHALLENGE, DECLINED, VOIDED, REFUNDED.
flowchart TD
P[PENDING] -->|3DS| C[CHALLENGE]
P --> A[AUTHORIZED]
P -->|capture: true| K[CAPTURED]
P -->|recusado| D[DECLINED]
C --> A
C -->|recusado| D
A -->|captura| K
A -->|void| V[VOIDED]
K -->|reembolso| R[REFUNDED]
Com capture: true o pagamento vai direto para CAPTURED; sem ele, para em AUTHORIZED até você capturar ou cancelar. DECLINED, VOIDED e REFUNDED são finais.
2. PUSH
Disparado quando um pagamento de push é aceito, pago ou rejeitado. A criação responde PENDING e o resultado chega depois 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 status: PENDING, AUTHORIZED, CAPTURED, DECLINED.
flowchart TD
A[PENDING<br/>push aceito] -->|destinatário pago| B[AUTHORIZED]
B --> C[CAPTURED<br/>fundos entregues]
A -->|rejeitado| D[DECLINED]
Um push bem-sucedido envia dois webhooks em sequência, AUTHORIZED e depois CAPTURED. Trate CAPTURED como o sucesso final e DECLINED como a falha final; numa recusa, statusDescription traz o motivo.
3. CHECK
Disparado quando uma verificação do Check Card Account termina. Nenhum valor é movimentado.
{
"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 status: AUTHORIZED (cartão verificado), CHALLENGE, DECLINED, VOIDED.
Entrega e Confiabilidade
- Autenticação: quando Basic auth está configurado, toda entrega traz
Authorization: Basic <credenciais>. Valide em toda requisição. As entregas não são assinadas. - Retentativas: respostas diferentes de 2xx e timeouts são retentados até o limite de tentativas configurado para sua conta. Retorne
2xximediatamente e processe de forma assíncrona. - Duplicatas: retentativas podem entregar a mesma notificação mais de uma vez. Use
(paymentId, newStatus)como chave no seu handler e trate repetições como no-op. - Ordem: não é garantida, e
eventDateé definido quando a notificação é gerada, não quando o status mudou. Se a sequência importa, compare ooldStatusrecebido com o estado que você tem guardado; se não bater, ignore a entrega e reconcilie com uma consulta. - Fonte da verdade: o webhook é uma notificação, não o pagamento completo. Confirme o status — e leia dados de cartão, cobrança ou taxas — pelo endpoint GET de pagamento antes de concluir pedidos.
Exemplo de Handler (Node.js)
app.post('/webhooks/inyo', async (req, res) => {
// Confirma imediatamente
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: fundos liquidados — conclui o pedido. PUSH: destinatário pago.
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);
});
