Payments Webhooks (Brazil)
A webhook is a web callback that Belvo uses to send notifications about a specific link.
This article is about webhooks for our Payment Initiation solution. For information regarding our Aggregation and Enrichment webhooks, check out this article
Set up webhooks
To set up a new webhook:
In your Belvo dashboard, go to the payment webhooks section.
In the Payments Webhooks tab, click +New webhook.
Fill in the New webhook form with the required information.
- URL: the URL to receive the webhook notifications.
- Authorization: an optional bearer token to use if your URL is protected.
Click Create webhook.
Webhook Schemas and Types
Belvo offers two webhook schema versions for Payments Brazil webhooks:
- Schema Version 1 (Legacy): The original webhook format used for CHARGES, PAYMENT_INTENTS, and TRANSACTIONS webhooks. This schema continues to work for existing integrations.
- Schema Version 2 (New): A newer webhook format introduced for enhanced functionality. This schema is used for BANK_ACCOUNTS (V2), CUSTOMERS (V2), and PAYMENT_AUTHORIZATIONS webhooks.
Schema Version 2 webhooks are only sent when resources are created using the X-Belvo-API-Resource-Version: Payments-BR.V2
header. If you don't include this header, you will receive webhooks in the legacy format (where applicable).
Webhook outbound IP addresses
You can receive webhook events from the following IP addresses:
3.130.254.46
18.220.61.186
18.223.45.212
We highly recommend you whitelist these IP addresses so that you can receive webhook events.
Client-side webhook response best practice
We highly recommend that once you receive a webhook you reply to Belvo with a 2XX status code within five seconds to confirm that you have received the webhook. Otherwise, our API will retry the request.
Webhook retry policy
If our system does not receive 2XX status code, it automatically tries to send the request again. This retry process will happen up to three times, with each attempt spaced 60 seconds apart. For example, if the first attempt fails, our system waits for 60 seconds before trying again and will continue this pattern until it either receives a successful response or reaches the maximum of three retries.
Webhook Events (Version 2)
Bank Account, Charge, and Customer webhooks are available in both schema versions. When using the X-Belvo-API-Resource-Version: Payments-BR.V2
header, you'll receive the new Schema Version 2 format shown below. Without this header, you'll receive the legacy format documented in the Customers (Legacy) section.
Whenever there is an event related to a Bank Account, Charge, Customer, or Payment Authorization you will receive the following webhook:
{
"schema_version": "2",
"resource": "BANK_ACCOUNT",
"resource_id": "7d01c4cf-57ed-4ed9-b109-a5bfb2d8c42b",
"resource_version": "v2",
"timestamp": "2025-01-16T10:30:45.123456Z"
}
Where:
Parameter | Required | Type | Description | Example |
---|---|---|---|---|
schema_version | true | string | The webhook schema version. At present, this will always be 2 . | 2 |
resource | true | string | The type of resource this webhook relates to. This can be one of the following: BANK_ACCOUNT , CHARGE , CUSTOMER , PAYMENT_AUTHORIZATION . | BANK_ACCOUNT |
resource_id | true | string | The unique identifier of the resource. You can use this ID to retrieve the resource details. | 7d01c4cf-57ed-4ed9-b109-a5bfb2d8c42b |
resource_version | true | string | The API version used when creating the resource. | v2 |
timestamp | true | date-time | The ISO-8601 timestamp of when the resource was last updated. | 2025-01-16T10:30:45.123456Z |
Once you receive the notification, you will have to get details of the resource by making the following request:
curl --request GET 'https://api.belvo.com/payments/br/{resource}/{id}/' \
-u [Secret Key ID]:[Secret Key PASSWORD] \
-H 'X-Belvo-API-Resource-Version: Payments-BR.V2'
Where:
resource
is the type of resource you want to retrieve (bank-accounts
,charges
,customers
, orpayment-authorizations
).id
is theresource_id
of the bank account (which you receive in the webhook event).
Webhook Events (Legacy)
{
"webhook_id": "3b9a69f7-0f0a-455b-832d-49ad6fd4905c",
"webhook_type": "PAYMENT_INTENTS",
"webhook_code": "STATUS_UPDATE",
"object_id": "d2e40773-19f6-48d1-93c3-3590ec0c74df",
"external_id": "c3c51aaf-aaa3-400c-926d-87ab62e195fd",
"data": {
"status": "FAILED",
"metadata": {"internal_reference_id": "GGq12345w2"},
"failure_code": "consent_expired",
"failure_message": "The payment consent was not accepted in time.",
"end_to_end_id": "E432158152024081610416f2b595b056",
}
}
Parameter | Required | Type | Description | Example |
---|---|---|---|---|
webhook_id | true | string | The Belvo webhook ID. | aadf41a1fc8e4f79a49f7f04027ac999 |
webhook_type | true | string | The resource that this webhook relates to. | CHARGES |
webhook_code | true | string | The event that triggered the webhook. | STATUS_UPDATE |
object_id | true | string | The ID of the object this webhook relates to. | d2e40773-19f6-48d1-93c3-3590ec0c74df |
external_id | true | string | The unique identifier you provided when creating the object. For charges and transactions, this field will always return null . | c3c51aaf-aaa3-400c-926d-87ab62e195fd |
data | true | object | An object containing specific data about the event. The fields returned in this object depend on the webhook_type and webhook_code . | See following rows. |
data.status | false | string | The status of the charge or payment intent. | FAILED |
data.failure_code | false | string | In the case that the charge or payment intent failed, a unique code for the error. | consent_expired |
data.failure_message | false | string | In the case that the charge or payment intent failed, a human-readable description of the error. | The payment consent was not accepted in time. |
data.end_to_end_id | false | string | The ID of the payment in Brazil's payment system. | E432158152024081610416f2b595b056 |
data.metadata | false | object | If you provided any information in the metadata object when creating your payment, it is included in the webhook body. | { "internal_reference_id": "GGq12345w2" } |
For information about the data specific to a given webhook, click on the webhook type in the table below.
Type | Event | Sent whenever... |
---|---|---|
CHARGES | STATUS_UPDATE | There is an update to the status of a Charge:
|
CUSTOMERS | OBJECT_CREATED | There is a new customer created (Legacy schema). That is, when the customer is created asynchronously and not as a result of a direct POST call. |
ENROLLMENTS | STATUS_UPDATE | There is an update to the status of an Enrollment:
|
PAYMENT_INTENTS | STATUS_UPDATE | There is an update on the status of a Payment Intent:
|
TRANSACTIONS | OBJECT_CREATED | There is a new transaction created. |
Once you receive the notification, you will have to get details of the resource by making the following request:
curl --request GET 'https://api.belvo.com/payments/br/{resource}/{id}/' \
-u [Secret Key ID]:[Secret Key PASSWORD] \
Where:
resource
is the type of resource you want to retrieve (bank-accounts
,charges
,customers
,payment-intents
, ortransactions
).id
is theobject_id
of the resource (which you receive in the webhook event).
Failure Codes and Messages
Below is a list of failure_code
s and failure_message
s that you can receive in a Charge or Payment Intents webhook:
Code | Message | When it can occur |
---|---|---|
AMOUNT_OVER_LIMIT | The payment amount or the number of payments exceeds the limits set by the institution. | Status Update |
AUTHORIZATION_EXPIRED | The authorization time has expired. | Status Update |
CONSENT_PENDING_AUTHORIZATION | Consent pending authorization from multiple levels (status 'PARTIALLY_ACCEPTED')." | Status Update |
HOLDER_INFRASTRUCTURE_FAILURE | There was a failure in the infrastructure of the account holder. | Status Update |
ICP_INFRASTRUCTURE_FAILURE | There was a failure in the ICP (Infraestrutura de Chaves Públicas) infrastructure.") | Status Update |
INSUFFICIENT_FUNDS | The account has insufficient funds to make the payment. | Status Update |
INVALID_CHARGE | The charge is invalid or incorrect. | Status Update |
INVALID_PAYMENT_DETAIL | The payment details provided are invalid. | Status Update |
NOT_INFORMED | No error reason was provided by the institution. | On Creation |
PAYMENT_CONSENT_MISMATCH | The payment details do not match the consent provided. | On Creation |
PAYMENT_REFUSED_BY_HOLDER | The payment was refused by the account holder. | On Creation, Status Update |
PAYMENT_REFUSED_BY_SPI | The payment was refused by the SPI (Sistema de Pagamentos Instantâneos). | Status Update |
PAYMENT_SCHEDULING_FAILURE | There was a failure in scheduling the payment. | Status Update |
RECEIVING_PSP_INFRASTRUCTURE_FAILURE | There was a failure in the infrastructure of the receiving PSP (Payment Service Provider). | Status Update |
SAME_ORIGIN_DESTINATION_ACCOUNTS | The origin and destination accounts are the same. | Status Update |
SPI_INFRASTRUCTURE_FAILURE | There was a failure in the SPI infrastructure. | Status Update |
SPI_REJECTED_PAYMENT | Payment rejected in the Instant Payment System (SPI). | Status Update |
USER_REJECTED | The user rejected the authorization of the consent. | Status Update |