# Webhooks de notificação

Os webhooks são uma boa prática recomendada para receber notificações do Payments Direct sobre mudanças no status dos seus pagamentos, em vez de fazer polling repetidamente por atualizações.

Este tópico apresenta uma visão geral dos webhooks e orientações sobre como usar webhooks com o Payments Direct.

## Por que usar webhooks de notificação

Um webhook é um método pelo qual um serviço pode notificar um aplicativo cliente sobre eventos relevantes, enviando mensagens de notificação para uma URL de callback que o cliente registrou no serviço. Quando um evento ocorre, o serviço envia uma notificação para a URL de callback especificada, usando o método HTTP POST, para avisar o cliente de que há informações disponíveis sobre o evento. Isso evita que o cliente precise consultar o serviço continuamente em busca de novas informações.

Observação
Payments Direct não oferece suporte a URLs de callback autenticadas.

## Tipos de evento

Payments Direct oferece suporte, no momento, a notificações de webhook para o tipo de evento `PAYMENT_STATE_TRANSITION`. Quando um pagamento passa de um estado para outro, o serviço envia à URL de callback registrada uma notificação com informações sobre o evento. Para mais informações, consulte [Registrar a URL de callback](#1-registrar-a-url-de-callback).

- Este é atualmente o **único tipo de evento** emitido no Payments Direct.
- O payload segue um **design “thin-plus”**: não é um objeto de pagamento completo, mas inclui mais do que apenas um ID.
- Cada webhook contém o `paymentId` e o **novo estado do pagamento**, junto com alguns campos adicionais de contexto.


As abas a seguir mostram payloads de exemplo do evento de transição de estado do pagamento com diferentes estados:

INITIATED
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"INITIATED", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:18.065Z" // The time when the webhook notification was created
}
```

VALIDATING
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"VALIDATING", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:20.468Z" // The time when the webhook notification was created
}
```

AWAITING_FUNDING
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"AWAITING_FUNDING", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:22.117Z" // The time when the webhook notification was created
}
```

TRANSFERRING
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"TRANSFERRING", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:32.455Z" // The time when the webhook notification was created
}
```

COMPLETED
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"COMPLETED", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:43.254Z" // The time when the webhook notification was created
}
```

RETURNED
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"RETURNED", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-06-02T09:14:07.331Z" // The time when the webhook notification was created
}
```

FAILED
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"FAILED", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:43.254Z" // The time when the webhook notification was created
}
```

DECLINED
```json
{
    "id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9", // The ID of the webhook notification
    "eventType":"PAYMENT_STATE_TRANSITION", // The type of event
    "eventVersion":1, // The version of the event. The version number may change if the event data changes
    "eventData": { // The data of the event
        "paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4", // The ID of the payment to which the event corresponds
        "expiresAt":"2025-07-28T17:18:35.663Z", // The time when the payment expires
        "createdAt":"2025-05-29T17:18:35.663Z", // The time when the payment was created
        "sourceCurrency":"USD", // The source currency of the payment
        "sourceAmount":8, // The source amount corresponding to the source currency of the payment
        "destinationCurrency":"COP", // The destination currency of the payment
        "payoutAmount":32538.81, // The payout amount corresponding to the destination currency of the payment
        "paymentState":"DECLINED", // The state that the payment is currently in
        "beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78" // The ID of the payment beneficiary
    },
    "createDate":"2025-05-30T10:21:38.902Z" // The time when the webhook notification was created
}
```

Observação
Os dados do evento `PAYMENT_STATE_TRANSITION` não incluem detalhes como códigos de erro no caso de um pagamento `FAILED`. Esse tipo de evento informa apenas sobre transições de estado do pagamento.

## Configuração e segurança

Para começar a receber notificações de webhook, siga estas etapas para registrar uma URL de callback e adicionar um endereço IP da Ripple à sua lista de permissões:

### 1. Registrar a URL de callback

No momento do seu onboarding no Payments Direct, você precisa informar uma URL de callback para a qual o Payments Direct possa enviar notificações quando ocorrerem eventos. Recomendamos uma URL pública acessível pela internet, mas com acesso restrito. A URL de callback precisa ser HTTPS (não HTTP) e ter um certificado de chave pública. Entre em contato com o seu contato na Ripple para registrar a URL de callback do seu webhook. Essa URL é configurada na instância do Ripple Payments do seu aplicativo cliente.

### 2. Opcional: adicionar os endereços IP da Ripple à sua lista de permissões

Para garantir que os callbacks de webhook venham do Ripple Payments, pode ser necessário adicionar os endereços IP do Ripple Payments à lista de permissões do seu servidor.

Para obter a lista de endereços IP a adicionar à sua lista de permissões, entre em contato com o seu contato na Ripple.

### 3. Opcional: verificar as assinaturas dos webhooks

Para garantir que todas as notificações de webhook sejam geradas pela Ripple, você pode verificar as assinaturas dos webhooks usando uma chave pública que pode ser obtida com o seu contato na Ripple.

Para verificar as assinaturas dos webhooks:

1. Recupere o payload do webhook e a assinatura (do cabeçalho).
**Exemplo**

```json
Body: {"id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9","eventType":"PAYMENT_STATE_TRANSITION","eventVersion":1,"eventData":{"paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4","expiresAt":"2025-07-28T17:18:35.663Z","createdAt":"2025-05-29T17:18:35.663Z","sourceCurrency":"USD","sourceAmount":8,"destinationCurrency":"COP","payoutAmount":32538.81,"paymentState":"VALIDATING","beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78"},"createDate":"2025-05-30T10:21:20.468Z"}

Headers:
ripple-signature: fcSWDhoHpNd+ZAQ2REndD7jacC1askGqltuXvFxp4MPWQ64w4cVz6yuvq3dAG/3pvCoJA10qXi/SCnvSXJajVKuOknU0WATEifQ+Zs4J06pCt2M0V8Ogcq2WIZ0+NUb2zvDfRr2o5UuzXVbEgDzZL0lC9s3PATQfcm3sJyYBSrCC35qf2NbkFye8i57jUPK8slEYwCwq6W+O+V1nFkNN6YMLi8MAHDSBsdGK+o/L1oCCckDaCFtMUaewVe15GKaQs6pHsVeLK0d7xgJmGciAnaifr7Ta2pv6dX4kTpIBzxy08VKiXHCRoRxZIyDF33jfHp5zVr/2H9xssGytZpDTkkSYYlgGNRS/mZxErE6Mddk2AN9ChMiWBq3TlMNLRCy3fCsICfLp/LqMqmU6/gr9uY41geLyzgozq2IanG4dHBuzHvyW8YykyeuifzFRKu4ykyKZpHTlYGe+ibDAh8Oo3XoO4iPe1NBqCFK+4EyjVgOa4LKT5XOBUxoXVUS4AxMun4MyPGNrOYVvLR2dzUc/5KeXVpWE4est6+XWLpSQduxRTwoeRHK7NdDyestKecWr0RS4le9FmvogBkuoCiMbMBrv+e0J9/A1X3txVXI+s6Zi72TwO6GqBAJx0bYRvAdKp3L9N2hcnd+P7NCnDKpb+hxc8+WeFkJcwtnqIupUVhw=
ripple-signature-timestamp: 2025-05-30T10:21:21.808586489Z
```
2. Crie o hash da requisição concatenando o valor de `ripple-signature-timestamp` e o `body` da requisição como uma string separada por um ponto, por exemplo:

```json
2025-05-30T10:21:21.808586489Z.{"id":"4d3f90cf-b70f-5ff1-827a-f8aa9cf84ab9","eventType":"PAYMENT_STATE_TRANSITION","eventVersion":1,"eventData":{"paymentId":"5ce2c433-a96d-48d0-8857-02637a60abf4","expiresAt":"2025-07-28T17:18:35.663Z","createdAt":"2025-05-29T17:18:35.663Z","sourceCurrency":"USD","sourceAmount":8,"destinationCurrency":"COP","payoutAmount":32538.81,"paymentState":"VALIDATING","beneficiaryToken":"cb207125-73a7-4a94-8502-a7780f1cae78"},"createDate":"2025-05-30T10:21:20.468Z"}
```
3. Descriptografe o valor da assinatura usando a chave pública da Ripple obtida com o seu contato na Ripple.
4. Compare os valores de hash, ou seja, a assinatura descriptografada e o valor de hash que você criou.
Se os valores coincidirem, o webhook é autêntico e não foi adulterado. Caso contrário, se não coincidirem, você deve rejeitar o webhook.


Dica
Além disso, você pode calcular a diferença entre o timestamp atual e o timestamp recebido para decidir se a diferença é aceitável.

### Tempos de resposta e comportamento de nova tentativa

Se a entrega de uma notificação de webhook falhar, ou seja, quando o cliente responde com qualquer código de status diferente de `2xx`, o Payments Direct repete a notificação até 75 vezes (ou por 72 horas). O intervalo entre as novas tentativas é de 1 minuto após a primeira falha e de até uma hora após cada falha seguinte.

Novas tentativas e outros problemas de rede podem fazer com que notificações duplicadas sejam enviadas. Nesse caso, a Ripple recomenda que você mantenha uma lista das notificações duplicadas.

Esclarecimento
A ordem de entrega não é garantida. As notificações podem chegar fora de sequência, especialmente se houver novas tentativas após uma indisponibilidade. Os clientes precisam projetar os handlers de webhook para tratar mensagens fora de ordem com segurança.

Alternativa aos webhooks
Como alternativa ao uso de webhooks para receber notificações do Ripple Payments sobre mudanças no status do pagamento, você pode usar a operação Search payments para fazer polling de atualizações de pagamento. Consulte [Polling](/pt-br/products/payments-direct-2/api-docs/payment-monitoring/polling).