NAV Navbar

Introduction to the Business API

As a Revolut Business customer, you can use the Business API to automate your own business processes.

For example, you can view accounts, add counterparties, make payments or currency exchanges without manual effort in the WebUI interfaces. This saves time and reduces costs and errors.

Sign up for a Revolut Business account to start using the Business API. You can also get a Sandbox account to test your application before you pushes the changes to production.

Sign up for a Revolut Business account

Related links

Get Started

Sign up for Revolut Business account

The Business API is available only to Revolut Business account holders. You must sign up to start using the API.

Sign up for a Revolut Business Account

Prepare your Sandbox environment

The Sandbox environment is a non-production environment that you can use to start working with the Business API.

To prepare your Sandbox environment, create a Sandbox account first, and then you can use mock data and test your application safely in a simulated environment.

You can sign up for a Sandbox account in a similar way you apply for your Revolut Business account.

Create a Sandbox Business account

Make your first API request

To start making your first API request, you must complete the initial setup, which is shown in the following high-level procedure:

  1. Upload your certificate to authorize your application to access your Revolut Business account via the Business API.
  2. Consent the application and you obtain an authorization code and the client ID.
  3. Provide a client assertion JWT to exchange your authorization code for access token.
  4. Exchange authorization code for access token that you can use to access the Business API.
  5. When the access token expires, request a new access token.
  6. Try your first API request to get a list of all your accounts.

After you complete and validate the setup, you can make different requests to the Business API.

1. Upload your certificate

Authorize your application to access your Revolut Business account via the Business API. To do this, you need to first upload your certificate on the API settings page of the Revolut Business portal.

Before you begin

Create a private and public key

$ openssl genrsa -out privatekey.pem 1024
$ openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825

Create a public/private key pair, and then copy and paste the publickey.cer into the required field when you complete the following steps.

Procedure

  1. Log in to your Revolut Business portal, and go to Settings > API.
  2. Click Add certificate.
  3. Copy and paste the publickey.cer to the X509 public key field.
  4. Specify the OAuth redirect URI. This is the URL where you are redirected after you consent the application to access your Revolut Business account.
  5. Click Continue.

You are directed to the API Certificate page where you need to consent the application.

Sample Confirmation URL

https://business.revolut.com/app-confirm?client_id=n0z4gsis9cGhwaYxxMlLQ7FScijU6NuqZV1MEP8YQI0&redirect_uri=http://revolutredirect.com/&response_type=code#authorise

Sample Redirect

https://www.revolutredirect.com/?code=oa_prod_vYo3mAI9TmJuo2_ukYlHVZMh3OiszmfQdgVqk_gLSkU
  1. On the API Certificate page, get your client ID from the ClientId field.
  2. Click Enable API access to your account. You are redirected to the /app-confirm URL where you grant your application to access your account via the Business API.

    Note: You can also see the client_id in the app-confirm URL. Check the sample confirmation URL on the right.

  3. Click Authorise. This triggers two-factor authentication process. On successful authorization, you are redirected to the OAuth redirect URI tht you specified.

  4. Get the authorization_code from the redirect URI. Check the sample direct on the right.

3. Generate a client assertion

JWT Header

{
  "alg": "RS256",
  "typ": "JWT"
}

JWT Payload

{
  "iss": <insert your_domain>,
  "sub": <insert client_id>,
  "aud": "https://revolut.com",
  "exp": <insert expiry_date>
}

Generate a client-assertion JWT that you use to exchange your authorization code for access token. The client-assertion JWT should be signed with your private key.

Ensure that the parameters meet the following format. Check the JWT header and the payload examples on the right.

Field Description Required Schema
iss Domain from redirect_url (without http://) Yes Text
sub Your client_id Yes Text
aud https://revolut.com Yes Text
exp JWT expiration date Yes UNIX timestamp in seconds

4. Exchange authorization code for access token

Exchange for an access token

curl https://sandbox-b2b.revolut.com/api/1.0/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded"\
  --data "grant_type=authorization_code"\
  --data "code=<insert authorisation_code>"\
  --data "client_id=<insert client_id>"\
  --data "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer"\
  --data "client_assertion=<insert JWT>"
curl https://b2b.revolut.com/api/1.0/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded"\
  --data "grant_type=authorization_code"\
  --data "code=<insert authorisation_code>"\
  --data "client_id=<insert client_id>"\
  --data "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer"\
  --data "client_assertion=<insert JWT>"

Response

{
  "access_token": "oa_sand_rPo9OmbMAuguhQffR6RLR4nvmzpx4NJtpdyvGKkrS3U",
  "token_type": "bearer",
  "expires_in": 2399,
  "refresh_token": "oa_prod_hQacSGnwx-luIfj3dlVByrytVV9rWAnyHkpJTwG_Tr8"
}

Use the authorization_code, client_assertion, and client_id generated from the previous steps to exchange for an access token that you can use to access the Business API.

Request fields (URL-encoded)

Field Description Required Schema
grant_type The OAuth grant type: authorization_code. Yes Text
code The authorization code. Yes Text
client_id The application ID. Yes Text
client_assertion_type The type of the client assertion: urn:ietf:params:oauth:client-assertion-type:jwt-bearer. Yes Text
client_assertion The JWT token that you generated. Yes Text

5. Refresh access token

Refresh access token

curl https://sandbox-b2b.revolut.com/api/1.0/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded"\
  --data "grant_type=refresh_token"\
  --data "refresh_token=<insert refresh_token>"\
  --data "client_id=<insert client_id>"\
  --data "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer"\
  --data "client_assertion=<insert JWT>"
curl https://b2b.revolut.com/api/1.0/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded"\
  --data "grant_type=refresh_token"\
  --data "refresh_token=oa_prod_gg-_wDV66wYfKKpnF4RIrpOZs2oPTwNp4TXOra5pS0g"\
  --data "client_id=<insert client_id>"\
  --data "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer"\
  --data "client_assertion=<insert JWT>"

Response

{
  "access_token": "oa_prod_rPo9OmbMAuguhQffR6RLR4nvmzpx4NJtpdyvGKkrS3U",
  "token_type": "bearer",
  "expires_in": 2399
}

After the access token expires, use the refresh_token to request a new one.

Request fields (URL-encoded)

Field Description Required Schema
grant_type The OAuth grant type: refresh_token. Yes Text
refresh_token The refresh token. Yes Text
client_id The application ID. Yes Text
client_assertion_type The type of the client assertion: urn:ietf:params:oauth:client-assertion-type:jwt-bearer. Yes Text
client_assertion The JWT token that you generated. Yes Text

6. Try your first API request

Get a list of accounts

curl https://sandbox-b2b.revolut.com/api/1.0/accounts \
  -H "Authorization: Bearer <your access token>"
curl https://b2b.revolut.com/api/1.0/accounts \
  -H "Authorization: Bearer <your access token>"

Response

[
  {
    "id": "2a0d4d03-e26c-4159-9de1-c6bf3adfd8a1",
    "name": "Current GBP account",
    "balance": 100.0,
    "currency": "GBP",
    "state": "active",
    "public": false,
    "updated_at": "2017-06-01T11:11:11.1Z",
    "created_at": "2017-06-01T11:11:11.1Z"
  },
  {
    "id": "df8d6b20-0725-482e-a29e-fb09631480cf",
    "name": "EUR expenses account",
    "balance": 1234.0,
    "currency": "EUR",
    "state": "active",
    "public": false,
    "created_at": "2017-06-01T11:11:11.1Z",
    "updated_at": "2017-06-01T11:11:11.1Z"
  }
]

Congratulations! You're ready to make requests to the Business API with an access token.

To verify that everything is working, make a request to the /accounts endpoint to get a list of all your accounts.

What’s next

Tutorials

Create a counterparty

To make a fund transfer or payment, add the counterparty that you intend to transact with.

Depending on whether a counterparty has a Revolut account and which country a counterparty account is based on, the fields that you need to specify are different.

Add a Revolut counterparty

Add a Revolut user as counterparty

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "profile_type": "personal",
  "name": "John Smith",
  "phone": "+44723456789"
}
EOF
curl -X POST https://b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "profile_type": "personal",
  "name": "John Smith",
  "phone": "+44723456789"
}
EOF

Response

{
  "id": "830e79d9-7b0a-45d3-a2a3-c0b291be3bf7",
  "name": "John Smith",
  "phone": "+44723456789",
  "profile_type": "personal",
  "country": "GB",
  "state": "created",
  "created_at": "2017-12-19T15:58:34.485Z",
  "updated_at": "2017-12-19T15:58:34.485Z"
}

If a counterparty has a Revolut account, you need to only provide the phone number and name, and you don't need full account details to add. However, if you add full account details, this also works.

Add a UK counterparty

Add a UK bank account as counterparty

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "company_name": "John Smith Co.",
  "bank_country": "GB",
  "currency": "GBP",
  "account_no": "12345678",
  "sort_code": "223344",
  "email": "john@smith.co",
  "phone": "+447771234455",
  "address": {
    "street_line1": "1 Canada Square",
    "street_line2": "Canary Wharf",
    "region": "East End",
    "postcode": "E115AB",
    "city": "London",
    "country": "GB"
  }
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "company_name": "John Smith Co.",
  "bank_country": "GB",
  "currency": "GBP",
  "account_no": "12345678",
  "sort_code": "223344",
  "email": "john@smith.co",
  "phone": "+447771234455",
  "address": {
    "street_line1": "1 Canada Square",
    "street_line2": "Canary Wharf",
    "region": "East End",
    "postcode": "E115AB",
    "city": "London",
    "country": "GB"
  }
}

EOF

Response

{
  "id": "97380d65-0478-4673-9e79-21918b4ae93a",
  "company_name": "Acme Corp.",
  "state": "created",
  "created_at": "2017-12-19T16:17:05.141Z",
  "updated_at": "2017-12-19T16:17:05.141Z",
  "accounts": [
    {
      "id": "4e32d331-68aa-4e4b-a295-3e3d7625819b",
      "currency": "GBP",
      "type": "external",
      "account_no": "12345678",
      "sort_code": "223344",
      "email": "acm@me.ccq",
      "name": "Acme Corp.",
      "bank_country": "GB",
      "recipient_charges": "free"
    }
  ]
}

If a counterparty doesn't have a Revolut account and has a UK account, the following details are required:

Add an international counterparty

Add an IBAN bank account as counterparty

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "company_name": "John Smith Co.",
  "bank_country": "FR",
  "currency": "EUR",
  "iban": "FR1420041010050500013M02606",
  "bic": "0500013M026",
  "email": "john@smith.co",
  "phone": "+447771234455",
  "address": {
    "street_line1": "20 Central Paris",
    "street_line2": "Champ de Mars",
    "region": "Paris",
    "postcode": "75007",
    "city": "Paris",
    "country": "FR"
  }
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/counterparty \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "company_name": "John Smith Co.",
  "bank_country": "FR",
  "currency": "EUR",
  "iban": "FR1420041010050500013M02606",
  "bic": "0500013M026",
  "email": "john@smith.co",
  "phone": "+447771234455",
  "address": {
    "street_line1": "20 Central Paris",
    "street_line2": "Champ de Mars",
    "region": "Paris",
    "postcode": "75007",
    "city": "Paris",
    "country": "FR"
  }
}

EOF

Response

{
  "id": "97380d65-0478-4673-9e79-21918b4ae93a",
  "company_name": "John Smith Co.",
  "state": "created",
  "created_at": "2017-12-19T16:17:05.141Z",
  "updated_at": "2017-12-19T16:17:05.141Z",
  "accounts": [
    {
      "id": "4e32d331-68aa-4e4b-a295-3e3d7625819b",
      "currency": "EUR",
      "type": "external",
      "iban": "FR1420041010050500013M02606",
      "bic": "0500013M026",
      "email": "john@smith.co",
      "name": "John Smith Co..",
      "bank_country": "FR",
      "recipient_charges": "free"
    }
  ]
}

If a counterparty doesn't have a Revolut account and has a non-UK bank account, depending on the country that the account is based on, you must specify the required fields.

See the example of an IBAN request on the right.

Check the following tables about the different fields required depending on the country:

Fields for US USD accounts

Field Description Required Schema
account_no bank account number Yes Text
routing_number routing transit number Yes Text

Fields for IBAN countries

Field Description Required Schema
iban IBAN Yes Text
bic BIC Yes Text

Fields for SWIFT

Field Description Required Schema
account_no bank account number Yes Text
bic bank BIC Yes Text

Fields for SWIFT MX

Field Description Required Schema
clabe CLABE Yes Text
bic bank BIC Yes Text

Fields for IN INR accounts

Field Description Format
account_no bank account number Text
ifsc IFSC Text

Fields for AU AUD accounts

Field Description Format
account_no bank account number Text
bsb_code BSB Text

Create a payment

This tutorial walks you through the steps to make an instant payment and schedule a payment.

An incoming or outgoing payment is represented as a transaction. A transaction is processed in two stages:

  1. A transaction is created,
  2. The transaction is processed in either of the following ways:

If the payment is made to an external payment network, when the transaction is created, it has the the pending state. When it’s processed, it can have one of the following states:

If the payment is made between Revolut accounts, the transaction is executed instantly, and skips the pending state.

Make an instant payment

Pay a counterparty

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/pay \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "request_id": "e0cbf84637264ee082a848b",
  "account_id": "bdab1c20-8d8c-430d-b967-87ac01af060c",
  "receiver": {
    "counterparty_id": "5138z40d1-05bb-49c0-b130-75e8cf2f7693",
    "account_id": "db7c73d3-b0df-4e0e-8a9a-f42aa99f52ab"
  },
  "amount": 123.11,
  "currency": "EUR",
  "reference": "Invoice payment #123"
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/pay \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "request_id": "e0cbf84637264ee082a848b",
  "account_id": "bdab1c20-8d8c-430d-b967-87ac01af060c",
  "receiver": {
    "counterparty_id": "5138z40d1-05bb-49c0-b130-75e8cf2f7693",
    "account_id": "db7c73d3-b0df-4e0e-8a9a-f42aa99f52ab"
  },
  "amount": 123.11,
  "currency": "EUR",
  "reference": "Invoice payment #123"
}

EOF

Response for an instantly processed payment:

{
  "id": "d56dd396-523b-4613-8cc7-54974c17bcac",
  "state": "completed",
  "created_at": "2017-10-01T10:10:10.0Z",
  "completed_at": "2017-10-01T10:10:10.0Z"
}

Response for a payment that is processed asynchronously or is scheduled for processing in the future:

{
  "id": "d56dd396-523b-4613-8cc7-54974c17bcac",
  "state": "created",
  "created_at": "2017-10-01T10:10:10.0Z"
}

Create a payment using the /pay endpoint.

If you make the payment to another Revolut account, either business or personal, the transaction is executed instantly.

Schedule a payment

Schedule an internal payment

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/pay \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "request_id": "e0cbf84637264ee082a848b",
  "account_id": "bdab1c20-8d8c-430d-b967-87ac01af060c",
  "receiver": {
    "counterparty_id": "5138z40d1-05bb-49c0-b130-75e8cf2f7693",
    "account_id": "db7c73d3-b0df-4e0e-8a9a-f42aa99f52ab"
  },
  "amount": 123.11,
  "currency": "EUR",
  "reference": "Invoice payment #123",
  "schedule_for": "2017-10-10"
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/pay \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "request_id": "e0cbf84637264ee082a848b",
  "account_id": "bdab1c20-8d8c-430d-b967-87ac01af060c",
  "receiver": {
    "counterparty_id": "5138z40d1-05bb-49c0-b130-75e8cf2f7693",
    "account_id": "db7c73d3-b0df-4e0e-8a9a-f42aa99f52ab"
  },
  "amount": 123.11,
  "currency": "EUR",
  "reference": "Invoice payment #123",
  "schedule_for": "2017-10-10"
}

EOF

You can schedule payments between Revolut accounts for up to 30 days ahead. Scheduling payments to an external payment network is not supported at the moment.

Scheduled payments must be in the currency of the account that you pay from. To schedule a future payment, as opposed to immediate execution, add the schedule_for field in the POST /pay request:

Field Description Format
schedule_for The future date and time that you schedule the payment. ISO date/time

Retrieve transaction data

Get historical transactions list

curl https://sandbox-b2b.revolut.com/api/1.0/transactions \
  -H "Authorization: Bearer <your access token>" 
curl https://b2b.revolut.com/api/1.0/transactions \
  -H "Authorization: Bearer <your access token>"

Response

 [
    {
      "id": "602ee3c3-67s4-ac64-baec-6ede391ba9b5",
      "type": "fee",
      "state": "completed",
      "created_at": "2021-02-18T22:01:39.223762Z",
      "updated_at": "2021-02-18T22:01:39.223762Z",
      "completed_at": "2021-02-18T22:01:39.223930Z",
      "legs": [
                {
                  "leg_id": "2fe2f7fa-7a81-4722-8c0e-88e1b788250f",
                  "account_id": "041c7846-4c5e-44af-b8f6-206f61e9f60a",
                  "amount": -7,
                  "currency": "GBP",
                  "description": "Freelance Pro plan fee",
                  "balance": 11.37
                }
              ]
    },
    {
      "id": "6ebc74ed-01db-4a56-b555-d5d0be6938de",
      "type": "transfer",
      "state": "completed",
      "request_id": "f5c2d005-f10c-4d19-9d97-01b3746b365b",
      "created_at": "2021-02-11T12:02:37.286562Z",
      "updated_at": "2021-02-11T12:02:40.207817Z",
      "completed_at": "2021-02-11T12:02:40.201404Z",
      "reference": "Test",
      "legs": [
                {
                  "leg_id": "e1dc29a0-41e0-4cd0-a6a4-2014fe6903f3",
                  "account_id": "a50d90ef-dd4a-4167-938b-03737c9af50f",
                  "counterparty":
                                 {
                                    "id": "95fde753-5dd3-4e3b-895b-5345f4f1e86d",
                                    "account_type": "external",
                                    "account_id": "ad598215-5997-4d8e-a65f-0b992842c2cd"
                                  },
                  "amount": -0.01,
                  "currency": "EUR",
                  "description": "To John Smith",
                  "balance": 0
                }
              ] 
    }

]

Learn how to retrieve the historical transactions based on the provided query criteria.

The API returns a maximum of 1,000 transactions per request.

Filter transactions

Get a filtered transaction list

curl https://sandbox-b2b.revolut.com/api/1.0/transactions? \
  counterparty=5138z40d1-05bb-49c0-b130-75e8cf2f7693 \
  &from=2017-06-01 \
  &to=2017-06-10 \
  &count=10 \
  &account=041c7846-4c5e-44af-b8f6-206f61e9f60a \
  -H "Authorization: Bearer <your access token>"
curl https://b2b.revolut.com/api/1.0/transactions? \
  counterparty=5138z40d1-05bb-49c0-b130-75e8cf2f7693 \
  &from=2017-06-01 \
  &to=2017-06-10 \
  &count=10 \
  &account=041c7846-4c5e-44af-b8f6-206f61e9f60a \
  -H "Authorization: Bearer <your access token>"

You can filter the transactions returned by adding one or more of the following parameters to the URL.

The following table lists the parameters that you can optionally add as filters:

Parameter Description Required Schema
from The date and time you retrieve the historical transactions from. No ISO date/time
to The date and time you retrieve the historical transactions to. The default value is now. No ISO date/time
counterparty The ID of the counterparty. No UUID
account The account ID. No UUID
count The number of the historical transactions to retrieve. The maximum number is 1,000. The default number is 100. No Number
type The type of the historical transactions to retrieve, which can be atm, card_payment, card_refund, card_chargeback, card_credit, exchange, transfer, loan, fee, refund, topup, topup_return, tax, or tax_refund. No Text

Pagination of transactions

The /transactions endpoint supports time-based pagination. It returns transactions in reverse chronological order (from <= created_at < to) limited to most recent count entities. Thus, to get the next page of results, you should set parameter to with the value of created_at last item of the previous page.

Exchange money

Make an exchange

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/exchange \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "from": {
    "account_id": "d56dd396-523b-4613-8cc7-54974c17bcac",
    "currency": "USD",
    "amount": 100.0
  },
  "to": {
    "account_id": "a44dd365-523b-4613-8457-54974c8cc7ac",
    "currency": "EUR"
  },
  "reference": "Time to sell",
  "request_id": "e0cbf84637264ee082a848b"
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/exchange \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "from": {
    "account_id": "d56dd396-523b-4613-8cc7-54974c17bcac",
    "currency": "USD",
    "amount": 100.0
  },
  "to": {
    "account_id": "a44dd365-523b-4613-8457-54974c8cc7ac",
    "currency": "EUR"
  },
  "reference": "Time to sell",
  "request_id": "e0cbf84637264ee082a848b"
}

EOF

Response

{
  "id": "d56d5596-523b-4613-2cc7-54974a37bcac",
  "state": "completed",
  "created_at": "2018-10-01T10:10:10.0Z",
  "completed_at": "2018-10-01T10:10:10.0Z"
}

You can exchange the money in either of the following cases:

To check the exchange rate and fees for the operation, use the /rate endpoint.

Work with 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 posted, via HTTP POST method, to the specified endpoint.

If the receiver returns an HTTP error response, there are two more consequent attempts for delivery.

Currently, the following events are supported:

Set up a webhook

Set up a webhook

curl -X POST https://sandbox-b2b.revolut.com/api/1.0/webhook \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "url": "https://example.com/example/path"
}

EOF
curl -X POST https://b2b.revolut.com/api/1.0/webhook \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "url": "https://example.com/example/path"
}

EOF
Request

Set up a webhook URL so that event notifications are pushed to the specified URL. Only HTTPS URLs are supported.

Field Description Schema
url The valid webhook URL that event notifications are sent to. The supported protocol is https. URL
Delete a webhook

Delete a webhook

curl -X DELETE https://sandbox-b2b.revolut.com/api/1.0/webhook \
  -H "Authorization: Bearer <your access token>"
curl -X DELETE https://b2b.revolut.com/api/1.0/webhook \
  -H "Authorization: Bearer <your access token>"

Delete a webhook so that events are not sent to the specified URL any more.

Set up multiple webhooks

Set up a webhook

curl -X POST https://sandbox-b2b.revolut.com/api/2.0/webhook \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "url": "https://example.com/example/path"
}

EOF
curl -X POST https://b2b.revolut.com/api/2.0/webhook \
  -H "Authorization: Bearer <your access token>" \
  --data @- << EOF

{
  "url": "https://example.com/example/path"
}

EOF

Response

{
  "url": "https://example.com/example/path",
  "id": "67b51b40-a6bc-4f87-c3e6-c05ea203a762"
}

Set up to 3 webhooks by leveraging version 2.0 of our webhooks API. The response will contain an id that can be used to then delete a specific webhook.

The same notifications go to each webhook. The request_id field can be used to distinguish payments from different sources if needed.

Get list of webhooks

Get a list of webhooks

curl -X GET https://sandbox-b2b.revolut.com/api/2.0/webhook \
  -H "Authorization: Bearer <your access token>" 
curl -X GET https://b2b.revolut.com/api/2.0/webhook/ \
  -H "Authorization: Bearer <your access token>" 

Response

[{
  "id": "8fd82ac5-4bc2-40b0-b6a5-1e8fc8f66792",
  "url": "https://example.com/example/path1"
}, {
  "id": "0bcab550-2e36-4245-8f84-d663192a5fa3",
  "url": "https://example.com/example/path2"
}, {
  "id": "1023de5b-8a57-4a89-8025-b30504c3a25b",
  "url": "https://example.com/example/path3"
}]

Make a GET request to the /webhooks endpoint to get a list of webhooks. Pass the id as a parameter on the URL to return only a specific one.

Update a webhook

Update a webhook

curl -X PATCH https://sandbox-b2b.revolut.com/api/2.0/webhook/67b51b40-a6bc-4f87-c3e6-c05ea203a762 \
  -H "Authorization: Bearer <your access token>" 
--data @- << EOF
{
  "url": "https://example.com/example/path"
}
EOF
curl -X PATCH https://b2b.revolut.com/api/2.0/webhook/67b51b40-a6bc-4f87-c3e6-c05ea203a762 \
  -H "Authorization: Bearer <your access token>" 
--data @- << EOF
{
  "url": "https://example.com/example/path"
}
EOF

Pass the id on a PATCH request to replace the webhook URL.

Delete a specific webhook

Delete a specific webhook

curl -X DELETE https://sandbox-b2b.revolut.com/api/2.0/webhook/67b51b40-a6bc-4f87-c3e6-c05ea203a762 \
  -H "Authorization: Bearer <your access token>" 
curl -X DELETE https://b2b.revolut.com/api/2.0/webhook/67b51b40-a6bc-4f87-c3e6-c05ea203a762 \
  -H "Authorization: Bearer <your access token>" 

Pass the id on a DELETE request to delete a specific webhook.

Transaction created event

See the example response of a TransactionCreated event on the right.

Payload example

{
  "event": "TransactionCreated",
  "timestamp": "2017-12-06T12:21:49.865Z",
  "data": {
    "id": "cad82fa6-ead6-11eb-9a03-0242ac130003",
    "request_id":"d0c0009c-ead6-11eb-9a03-0242ac130003",
    "type": "transfer",
    "request_id": "e0cbf84637264ee082a848b",
    "state": "completed",
    "created_at": "2017-12-06T12:21:48.865Z",
    "updated_at": "2017-12-06T12:21:48.865Z",
    "completed_at": "2017-12-06T12:21:48.865Z",
    "reference": "Payment for Blows & Wistles Co.",
    "legs": [
      {
        "leg_id": "e2fdd0e2-3881-4804-8a8c-6573a97488fa",
        "account_id": "87b51b40-a6bc-4f87-a3e6-c05ea203a762",
        "counterparty": {
          "type": "revolut",
          "account_id": "54c0150f-64de-4653-93e5-af89d21385a0"
        },
        "amount": -120.0,
        "currency": "GBP",
        "balance": 102
      }
    ]
  }
}

Response

Field Description Schema
event The event name. Text
timestamp The event time. ISO date/time
data.id The ID of transaction. UUID
data.request_id The client provided request ID. Text
data.state The transaction state: pending, completed, declined or failed. Text
data.reason_code The optional reason code for declined or failed transaction state. Text
data.created_at The date and time the transaction was created. ISO date/time
data.updated_at The date and time the transaction was last updated. ISO date/time
data.completed_at The date and time the transaction was completed, mandatory for completed state only. ISO date/time
data.scheduled_for The optional date the transaction was scheduled for. ISO date
data.reference The user provided payment reference. Text
data.legs The legs of a transaction. There are 2 legs between your Revolut accounts and 1 leg in other cases. Array
data.legs[n].leg_id The ID of the leg. UUID
data.legs[n].amount The transaction amount. Decimal
data.legs[n].fee The optional transaction fee amount. Decimal
data.legs[n].currency The transaction currency. 3-letter ISO currency code
data.legs[n].bill_amount The billing amount for cross-currency payments. Decimal
data.legs[n].bill_currency The billing currency for cross-currency payments. 3-letter ISO currency code
data.legs[n].account_id The ID of the account the transaction is associated with. UUID
data.legs[n].counterparty.id The counterparty ID. UUID
data.legs[n].counterparty.account_id The counterparty account ID. UUID
data.legs[n].counterparty.account_type The type of counterparty account: self, revolut, external. Text
data.legs[n].description The transaction leg purpose. Text
data.legs[n].balance The total balance of the account the transaction is associated with (optional). Decimal

Transaction state changed event

Payload example

{
  "event": "TransactionStateChanged",
  "timestamp": "2017-12-06T12:21:49.865Z",
  "data": {
    "id": "9a6434d8-3581-4faa-988b-48875e785be7",
    "request_id":"d0c0009c-ead6-11eb-9a03-0242ac130003",
    "old_state": "pending",
    "new_state": "reverted"
  }
}

See the example response of a TransactionStateChanged event on the right.

Field Description Schema
event The event name. Text
timestamp The event time. ISO date/time
data.id The ID of the transaction. UUID
data.request_id The client provided request ID. UUID
data.old_state The previous state of the transaction. Text
data.new_state The new state of the transaction. Text

Usage and limits

In order to ensure safe and fair resource sharing, we define the following usage limits:

As businesses on a Freelancer plan, you are also required to ask users for explicit authorization to access their account via the API every 90 days.

This means that access tokens expire every 90 days and you (or your users) will need to authorize access to the app once more. This is due to the recent PSD2 SCA regulations.

Errors

HTTP Response errors

The API uses the following error codes:

CODE MEANING
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your access token is wrong.
403 Forbidden -- Access to the requested resource or action is forbidden.
404 Not Found -- The requested resource could not be found.
405 Method Not Allowed -- You tried to access an endpoint with an invalid method.
406 Not Acceptable -- You requested a format that isn't JSON.
409 Conflict -- Your request conflicts with current state of a resource.
429 Too Many Requests -- You're sending too many requests.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.