Inyo

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:

  1. Fornecer sua(s) URL(s) de webhook
  2. 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:

CampoTipoObservações
agentIdstringIdentificador do seu agente
eventstringPULL, PUSH ou CHECK
statusstringStatus do pagamento após a mudança. Mesmo valor de newStatus
statusCodestring00 aprovado, 99 recusado
statusDescriptionstringDescrição legível da mudança ou do motivo da recusa
paymentIduuidIdentificador do pagamento na Inyo
externalPaymentIdstringO externalPaymentId enviado na criação do pagamento
amountobject{ "total": number, "currency": string } — valor e moeda de origem (ISO 4217)
recipientAmountobjectSó PUSH. { "total": number, "currency": string } — valor entregue ao destinatário, presente quando o pagamento tem conversão de moeda
eventDatestringMomento em que a notificação foi gerada, ISO 8601 em UTC
oldStatusstring | nullStatus do pagamento antes da mudança
newStatusstringStatus 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 2xx imediatamente 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 o oldStatus recebido 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);
});