Guides • Manage Accounts
About webhooks
doc

About webhooks

A webhook (also called a web callback) allows your system to receive updates about your account to an HTTPS endpoint that you provide. When a supported event occurs, a notification is sent via HTTP POST method to the specified endpoint.

note

This guide applies to the Webhooks API in v2.

For the previous version of the API, check the API Reference: Webhooks (v1) (deprecated).

Supported event types

You can subscribe to the following event types:

To subscribe to selected event types, provide their names on webhook creation or update.

Default event types

If you don't specify which event types you want to subscribe to, you're automatically subscribed to the default event types: TransactionCreated and TransactionStateChanged.

Supported operations

The Business API supports the following operations on webhooks:

tip

For more information on how to work with webhooks, see Manage webhooks.

Webhook examples

See below the examples of different types of events that webhooks can receive.

Transaction created event

See an example of the TransactionCreated event:

{
"event": "TransactionCreated",
"timestamp": "2023-01-26T16:22:21.753463Z",
"data": {
"id": "63d2a8bd-8b67-a2de-b1d2-b58ee21d7073",
"type": "transfer",
"state": "pending",
"request_id": "6a8b2ad9-d8b9-4348-9207-1c5737ccf11b",
"created_at": "2023-01-26T16:22:21.765313Z",
"updated_at": "2023-01-26T16:22:21.765313Z",
"reference": "To John Doe",
"legs": [
{
"leg_id": "63d2a8bd-8b67-a2de-0000-b58ee21d7073",
"account_id": "05018b0d-e67c-4fec-bea6-415e9da9432c",
"counterparty": {
"id": "7e18625a-3e6c-4d4f-8429-216c25309a5f",
"account_type": "external",
"account_id": "ff29e658-f07f-4d81-bc0f-7ad0ff141357"
},
"amount": -10,
"currency": "GBP",
"description": "To Acme Corp"
}
]
}
}
See the field details
FieldDescriptionTypeFormat
eventThe event name.StringText
timestampThe event time.StringISO date/time
dataThe transaction data.ObjectJSON

Data object for transaction created

The data object contains the following fields:

FieldDescriptionTypeFormat
idThe ID of transaction.StringUUID
typeThe transaction type.StringText
stateThe transaction state: pending, completed, declined or failed.StringText
request_idThe request ID provided by the client.StringText
reason_codeThe optional reason code for declined or failed transaction state.StringText
created_atThe date and time the transaction was created.StringISO date/time
updated_atThe date and time the transaction was last updated.StringISO date/time
completed_atThe date and time the transaction was completed, mandatory for completed state only.StringISO date/time
scheduled_forThe optional date the transaction was scheduled for.StringISO date
referenceThe payment reference provided by the user.StringText
related_transaction_idThe ID of the related transaction. Only applicable when type=refund.StringUUID
legsThe legs of a transaction. There are 2 legs between your Revolut accounts and 1 leg in other cases.Array of objectsJSON

Legs object

An object in the legs array contains the following fields:

FieldDescriptionTypeFormat
leg_idThe ID of the leg.StringUUID
account_idThe ID of the account the transaction is associated with.StringUUID
counterpartyThe counterparty object.ObjectJSON
amountThe transaction amount.NumberDecimal
feeThe optional transaction fee amount.NumberDecimal
currencyThe transaction currency.String3-letter ISO currency code
bill_amountThe billing amount for cross-currency payments.StringDecimal
bill_currencyThe billing currency for cross-currency payments.String3-letter ISO currency code
descriptionThe transaction leg purpose.StringText
balanceThe total balance of the account the transaction is associated with (optional).NumberDecimal

Counterparty object

A counterparty object contains the following fields:

FieldDescriptionTypeFormat
idThe counterparty ID.StringUUID
account_idThe counterparty account ID.StringUUID
account_typeThe type of counterparty account: self, revolut, external.StringText

Transaction state changed event

See an example of the TransactionStateChanged event:

{
"event": "TransactionStateChanged",
"timestamp": "2023-04-06T12:21:49.865Z",
"data": {
"id": "9a6434d8-3581-4faa-988b-48875e785be7",
"request_id": "6a8b2ad9-d8b9-4348-9207-1c5737ccf11b",
"old_state": "pending",
"new_state": "reverted"
}
}
See the field details
FieldDescriptionTypeFormat
eventThe event name.StringText
timestampThe event time.StringISO date/time
dataThe transaction data.ObjectJSON

Data object for transaction state changed

The data object contains the following fields:

FieldDescriptionTypeFormat
idThe ID of the updated transaction.StringUUID
request_idThe request ID provided by the client.StringText
old_stateThe previous state of the transaction.StringText
new_stateThe new state of the transaction.StringText

See an example of the PayoutLinkCreated event:

{
"event": "PayoutLinkCreated",
"timestamp": "2023-07-05T16:22:21.753463Z",
"data": {
"id": "3b9087bb-290a-4321-8ef6-96b9a2f071e8",
"state": "created",
"request_id": "ff5fadff-aae1-4848-87f8-53d515eea3b5"
}
}
See the field details
FieldDescriptionTypeFormat
eventThe event name.StringText
timestampThe event time.StringISO date/time
dataThe transaction data.ObjectJSON

The data object contains the following fields:

FieldDescriptionTypeFormat
idThe ID of the link.StringUUID
stateThe state that the link is in: created, failed, awaiting, active, expired, cancelled, processing or processed.StringText
request_idThe request ID provided by the client.StringText

See an example of the PayoutLinkStateChanged event:

{
"event": "PayoutLinkStateChanged",
"timestamp": "2023-07-06T10:12:38.568Z",
"data": {
"id": "0e1a8d4b-1d1e-457d-9f10-3e7007a82ea8",
"request_id": "2e2837f5-828d-473f-85e8-5614afd3f8e8",
"old_state": "active",
"new_state": "processed"
}
}
See the field details
FieldDescriptionTypeFormat
eventThe event name.StringText
timestampThe event time.StringISO date/time
dataThe transaction data.ObjectJSON

The data object contains the following fields:

FieldDescriptionTypeFormat
idThe ID of the updated link.StringUUID
request_idThe request ID provided by the client.StringText
old_stateThe previous state of the link.StringText
new_stateThe new state of the link.StringText

Retries and errors

If the webhook URL returns an HTTP error response and the delivery of the webhook fails, Revolut will retry the webhook event 3 more times, each with a 10-minute interval.

If, despite the retries, the event is still not delivered, you can check it by retrieving the list of failed webhook events.

warning

Webhook notifications might occasionally be sent more than once. Make sure that your webhook endpoints are idempotent by checking if you have already received a given webhook event.

warning

We cannot guarantee the delivery of events in the order in which they are generated, so make sure your server does not rely on the temporal order of events.

For example, for a transaction, normally, you should first receive the TransactionCreated webhook event, and then the TransactionStateChanged event.
However, if the TransactionCreated status isn't sent successfully in the first place, it's moved to the queue to be resent in the next few minutes.
Before then, if the TransactionStateChanged status is already sent, you first get TransactionStateChanged, and then TransactionCreated.

IP Allowlisting

Webhook notifications are sent from the following IP addresses, in case you need to allowlist them:

  • 35.246.21.235
  • 34.89.70.170

Security

Each webhook notification contains the following headers:

  • Revolut-Request-Timestamp: Timestamp of the webhook event, for example: 1683650202360.

  • Revolut-Signature: Signature of the request payload. Contains the current version of the signature generating algorithm, and the hexadecimal-encoded signature itself, for example: v1=09a9989dd8d9282c1d34974fc730f5cbfc4f4296941247e90ae5256590a11e8c.

    note

    The Revolut-Signature header can contain multiple signatures if multiple signing secrets are active at a given moment. If that's the case, they are separated by a comma. For example:

    Revolut-Signature: v1=4fce70bda66b2e713be09fbb7ab1b31b0c8976ea4eeb01b244db7b99aa6482cb,v1=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39

Webhook signing secret

To ensure that a webhook request originates from Revolut and not a third party, we recommend that you verify the request's signature using a signing secret.

Revolut uses the HMAC SHA-256 algorithm to sign its webhooks. The secret is generated on webhook creation, and it only changes on the secret's rotation. After you've created a webhook, you can retrieve the signing secret when you retrieve a specific webhook's details.

If you suspect that your webhook signing secret has been compromised, you can rotate it.

On rotation, you can pass the optional expiration_period parameter for the old secret to remain valid until the expiration period has passed. Otherwise, it is invalidated immediately.

In the period when multiple signing secrets remain valid, multiple signatures are sent.

Timestamp validation

You can mitigate replay attacks in your webhooks by applying timestamp validation.

For each webhook event, Revolut sends a Revolut-Request-Timestamp header with the exact date-time in which it was delivered.
To validate the event, make sure that the Revolut-Request-Timestamp date-time is within a 5-minute time tolerance of the current universal time (UTC).

Was this page helpful?