NAV Navbar

Introduction to the Open Banking API

The Revolut Open Banking API is the gateway for third-party providers to interact with Revolut customers and products.

You can take advantage of the Open Banking API to build your banking applications whether you are

Related Links

Who can access the API

Regulated Third Party Providers under PSD2

Third Party Providers (TPPs) are authorized online service providers under PSD2 (Revised Payment Services Directive). If you are either a Payment Initiation Service Provider (PISP) or Account Information Service Provider (AISP) in the European Union (EU) or the United Kingdom (UK), you are regulated by financial regulatory bodies in the relevant jurisdictions.

To access our Open Banking API, you must use a valid eIDAS certificate or Open Banking (OBIE) certificate to register your application for production.

Revolut Partners

If you are not a regulated TPP under PDS2, but would like to access the API, you can contact us to see if you’re qualified for access to our endpoints.

Global customer access controls

From the 1st January 2021, we made changes to which third-parties are able to access Revolut customer data across the globe. This depends on the type of certificate held, the regulator of the third-party and the type of endpoints used.

For those that are in possession of both OBIE and eIDAS certificates, please read the below carefully before deciding what certificate to use for your integration.

For Revolut Partners, all functionality is available, please reach out for further details.

Revolut Entity Certificate Type Endpoints
Revolut LTD (UK customers) OBIE, eIDAS (third-parties on the FCA's TPR only), Revolut Partners Accounts, Payments
Revolut Payments UAB (EEA customers) eIDAS, Revolut Partners Accounts, Payments
Revolut Technologies Singapore Pte Ltd OBIE, eIDAS, Revolut Partners Accounts
Revolut Technologies Inc. US OBIE, eIDAS, Revolut Partners Accounts
Revolut Payments Australia Pty Ltd Revolut Partners Accounts, Payments
Revolut Payments New Zealand Pty Ltd Revolut Partners Accounts, Payments
Revolut Technologies Japan Inc Revolut Partners Accounts, Payments

Get Started

To start using our Open Banking API, you must register your application. In addition, you need to set up your Sandbox environment to test your integration.

You can use one of the following ways to register your application:

Register your application in the Developer Portal

Before you begin, sign up for a new Developer account. Sign up for a Developer Account

If you have an OBIE/eIDAS certificate, you can upload the certificate in the Developer Portal and register a production application without any further approval from Revolut. You are returned a client_id that you can use to make requests to our API.

If you are looking to become a Revolut Partner, you must submit a request for your application to be approved via the Developer Portal. On successful approval of your application, you are returned production certificates to be used on our API.

Prepare your Sandbox environment

Set up the Sandbox environment to test the integration before you push it to the production environment.

Download sandbox credentials

Generate RSA

openssl genrsa -out server.key 2048

Generate CSR

openssl req -sha256 -new -key server.key -out server.csr -outform der
  1. Run the commands to generate a private RSA key and CSR file.
  2. Log in to the Developer Portal , navigate to the Sandbox tab, and upload the CSR file in the Sandbox authentication.
  3. Download the Sandbox certificates.

Create test accounts

In addition to your Sandbox credentials, you also need test accounts to test your application.

You can create both retail and business test accounts:

What’s next

You are ready to start requesting user consents and make API calls to our endpoints. For more information, see our tutorials to walk you through the steps for different use cases.

Register your application using DCR

You can use the /register endpoint to register your application.

Before you begin, check the following high-level procedure to register using DCR:

  1. Get the JWKs URL.
  2. Get the software statement. The type of software statement depends on the certificate that you register your application with:
    • Open Banking software statement when you register with your Open Banking certificate.
    • Self-signed software statement when you register with your eIDAS certificate.
  3. Create a JSON Web Token (JWT).
  4. Check if your JWT is valid.
  5. Register your application using the /register endpoint that includes the JWT.

Then, you can get a client_id from the response.

1. Get the JWKs URL

JWKs (JWK Set) is a JSON data structure that represents a set of JWKs. A JSON Web Key (JWK) is a (JSON) data structure that represents a cryptographic key.

If you are using your Open Banking certificate, you should receive your JWKs URL from the Open Banking Directory.

If you are using your eIDAS certificate, the JWK should contain the following fields:

JWK mandatory fields Description
kid The key ID that is used to match a specific key.
kty The cryptographic algorithm family used with the key.
e Contains the exponent value for the RSA public key, represented as a Base64urlUInt-encoded value.
n Contains the modulus value for the RSA public key, represented as a Base64urlUInt-encoded value.
use The intended use of the public key (should always be set to sig).
x5c The base64-encoded DER.

2. Get the software statement

Open Banking software statement

If you're using your Open Banking certificate, use the software statement signed by Open Banking, which you can obtain from the Open Banking Directory. You need this software statement when you create the JWT later.

Self-signed software statement

If you're using your eIDAS certificate, use the self-signed software statement. You need this software statement when you create the JWT later.

Ensure that the software statement meets the following format. You can also check the example on the right:

Example: Self-signed software statement header

{
  "alg": "none"
}
SSA header Type Description Required
alg string Use none as the only value to indicate a self-signed software statement. Yes

Example: Self-signed software statement payload

{
  "org_name": "Revolut TPP",
  "software_client_name": "Revolut TPP",
  "org_jwks_endpoint": "http://openbanking.org.uk/endpoint",
  "software_redirect_uris": ["http://url/one"]
}
SSA payload Type Description Required
org_jwks_endpoint URI The JWKs endpoint. It must contain a signing key (QSealC) that matches with the kid provided in the JWT header of the registration request. Yes
org_name string The name of the software (shown in the UI). Alternatively, software_client_name can be used. Yes
software_client_name string The name of the software (shown in the UI). Yes
software_redirect_uris URI List of allowed redirect URIs, which must contain all redirect URLs from the JWT redirect_uris claim. Yes

3. Create a JWT

To create a JWT, specify the parameters that are required for your application in the JWT header and the payload. For the JWT signature, include both the public key and the signing certificate's RSA private key.

Ensure that the parameters meet the following format. You can also check the examples on the right.

Example: JWT header

{
  "kid": "test-kid",
  "alg": "PS256"
}

Example: JWT payload

{
  "iss": "test-iss",
  "iat": 1591352490,
  "exp": 1591356090,
  "aud": "https://revolut.com",
  "scope": ["openid", "payments", "accounts", "fundsconfirmations"],
  "redirect_uris": ["http://url/one"],
  "token_endpoint_auth_method": "tls_client_auth",
  "application_type": "web",
  "id_token_signed_response_alg": "PS256",
  "request_object_signing_alg": "PS256",
  "tls_client_auth_dn": "test-dn",
  "software_statement": "ewogICJhbGciOiAibm9uZSIKfQ.ewogICJvcmdfaWQiOiAiNzc3NTgwMDAwMTAzVUF2QUFNIiwKICAib3JnX25hbWUiOiAiUmV2b2x1dCBUUFAiLAogICJzb2Z0d2FyZV9jbGllbnRfbmFtZSI6ICJSZXZvbHV0IFRQUCIsCiAgIm9yZ19qd2tzX2VuZHBvaW50IjogImh0dHA6Ly9vcGVuYmFua2luZy5vcmcudWsvZW5kcG9pbnQiLAogICJzb2Z0d2FyZV9yZWRpcmVjdF91cmlzIjogWwogICAgImh0dHA6Ly91cmwvb25lIgogIF0KfQ."
}
JWT header Type Description Required
kid string The key ID of a public key from the JWKs file. Yes
alg string The signing algorithm used. Currently, only PS256 is supported. Yes
JWT payload Type Description REQUIRED
iss string The principal that issued the JWT. Yes
iat numeric The time the JWT was issued, which is used to determine the age of the JWT. Yes
exp numeric The expiration time that the JWT must not be accepted for processing on or after. Yes
aud string The recipients that the JWT is intended for. Yes
scope string List of scopes. The supported scopes are openid (required), accounts, payments, fundsconfirmations. Yes
redirect_uris string List of allowed redirect URIs. Yes
token_endpoint_auth_method string The authorization method for the token endpoint. Currently, only tls_client_auth is supported. Yes
application_type string The application type. Yes
id_token_signed_response_alg string The signing algorithm used. Currently, only PS256 is supported. Yes
request_object_signing_alg string The signing algorithm used. Currently, only PS256 is supported. Yes
tls_client_auth_dn string The distinguished name of the certificate that the TPP uses. Yes
software_statement string The software statement assertion issued by the issuer in JWT format. Yes

certificates in DER format:

openssl x509 -in /path/to/your/cert.der -inform der -noout -subject -nameopt RFC2253

Certificates in PEM format:

openssl x509 -in /path/to/your/cert.pem -inform pem -noout -subject -nameopt RFC2253

To get the value of the tls_client_auth_dn parameter, run the command based on the format of your certificates to obtain the distinguished name.

4. Validate your JWT

Before you register your application, check if your JWT is valid. You can use the JWT debugging tool.

5. Get a client ID

Register your application

curl -X POST https://sandbox-oba.revolut.com/register \
--header 'Content-Type: application/jwt' \
--data-raw '<insert JWT>'
curl -X POST https://oba.revolut.com/register \
--header 'Content-Type: application/jwt' \ 
--data-raw '<insert JWT>'

When you have a valid JWT, you can use the /register endpoint to dynamically register your application. From the response, you can obtain your client_id that you can use to make requests to the Open Banking API.

The /register endpoint is implemented as is described in the Open Banking: Dynamic Client Registration - v3.1 documentation.

What’s next

You are ready to start requesting user consents and make API calls to our endpoints. For more information, see our tutorials to walk you through the steps for different use cases.

Open ID configuration URLs

We use OpenID Connect: ensure to include the openid scope in your JWT payload. For more details, see configurations for Production and Sandbox environments:

Manage your applications

Update an application

Update an application

curl -X PUT https://sandbox-oba.revolut.com/register/17b2738f-26b1-46f9-a979-debbf1f39365
curl -X PUT https://oba.revolut.com/register/17b2738f-26b1-46f9-a979-debbf1f39365

To update the information for an existing application, make a PUT request to the register endpoint:

Fields for updating an application

Application property Corresponding JWT field
Application name The org_name or the software_client_name field that is present in the SSA.
Redirect URIs The redirect_uris field in the SSA.
JWKs URL The org_jwks_endpoint field in the SSA.
Distinguished name The tls_client_auth_dn field in the JWT payload.

Delete an application

Delete an application

curl -X DELETE https://sandbox-oba.revolut.com/register/17b2738f-26b1-46f9-a979-debbf1f39365
--header 'Authorisation: Bearer <your token>'
curl -X DELETE https://oba.revolut.com/register/17b2738f-26b1-46f9-a979-debbf1f39365
--header 'Authorisation: Bearer <your token>'

To request deletion of an existing application, make a DELETE request to the register endpoint. In the request header, provide the client_id and access token.

Tutorials

Get account and transaction information

This tutorial walks you through the steps to pull the data of a user's account from the /accounts endpoint.

Similar steps apply to all of accounts and transactions endpoints. Therefore, after you complete this tutorial, you will know how to use all the accounts and transactions endpoints.

See the API Reference for all the available endpoints.

Before you begin, ensure that you have registered your application with the accounts scope.

1. Generate a client credentials token

Get a token

curl -k --cert transport.pem --key server.key \
--location --request POST 'https://sandbox-oba-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=accounts'
curl --cert transport.pem --key server.key \
--location --request POST 'https://oba-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=accounts'

Response

{
  "access_token":"eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q",
  "token_type":"Bearer",
  "expires_in": 2399
}

Request an access token for client credentials using the /token endpoint and the client_credentials grant type.

You use this token to:

Create a consent

curl --location --request POST 'https://sandbox-oba.revolut.com/account-access-consents' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q' \
--header 'Content-Type: application/json' \
--data-raw '
{
    "Data": {
        "Permissions": [
            "ReadAccountsBasic",
            "ReadAccountsDetail"
        ],
        "ExpirationDateTime": "2020-12-02T00:00:00+00:00",
        "TransactionFromDateTime": "2020-09-03T00:00:00+00:00",
        "TransactionToDateTime": "2020-12-03T00:00:00+00:00"
    },
    "Risk": {}
}'
curl --location --request POST 'https://oba.revolut.com/account-access-consents' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q' \
--header 'Content-Type: application/json' \
--data-raw '
{
    "Data": {
        "Permissions": [
            "ReadAccountsBasic",
            "ReadAccountsDetail"
        ],
        "ExpirationDateTime": "2020-12-02T00:00:00+00:00",
        "TransactionFromDateTime": "2020-09-03T00:00:00+00:00",
        "TransactionToDateTime": "2020-12-03T00:00:00+00:00"
    },
    "Risk": {}
}'

Response

{
  "Data": {
    "Status": "AwaitingAuthorisation",
    "StatusUpdateDateTime": "2020-11-05T16:07:46.506182Z",
    "CreationDateTime": "2020-11-05T16:07:46.506182Z",
    "TransactionToDateTime": "2017-12-03T00:00:00+00:00",
    "ExpirationDateTime": "2021-05-02T00:00:00+00:00",
    "Permissions": [
      "ReadAccountsBasic",
      "ReadAccountsDetail"
    ],
    "ConsentId": "d19ec758-22fd-4f34-9ad4-7437f8628987",
    "TransactionFromDateTime": "2017-05-03T00:00:00+00:00"
  },
  "Risk": {},
  "Links": {
    "Self": "https://oba.revolut.com/account-access-consents"
  },
  "Meta": {
    "TotalPages": 1
  }
}

Create a consent for specific permissions using the /account-access-consents endpoint.

In this tutorial, you create a consent for the following permissions, shown in the code example on the right:

To check all the supported permissions and the dependencies, see the API Reference.

3. Create a JWT URL parameter

After you create a consent, you need the user to authorize the consent so that you can access the data on their behalf.

Header

{
  "alg": "PS256",
  "kid": "test-kid"
}

Body

{
  "response_type": "code id_token",
  "client_id": <insert client_id>,
  "redirect_uri": <insert redirect_uri>,
  "scope": "accounts",
  "claims": {
    "id_token": {
      "openbanking_intent_id": {
        "value": <insert ConsentId>
      }
    }
  }
}

Create a JWT request parameter with the header and body format on the right, signed by your signing certificate’s private key. This signature is validated using the JWKs endpoint that you specified during the registration of your application.

Sample URL

https://sandbox-oba.revolut.com/ui/index.html?response_type=code%26id_token&scope=accounts&redirect_uri=<insert redirect URL>&client_id=<insert client_id>&request=<insert JWT>
https://oba.revolut.com/ui/index.html?response_type=code%26id_token&scope=accounts&redirect_uri=<insert redirect URL>&client_id=<insert client_id>&request=<insert JWT>

Redirect the user to the authorization URL with the following parameters.

Parameter Description Required
response_type Always set to code&id_token. yes
client_id The client ID for your application. yes
redirect_uri One of the redirect URIs that you defined during the application creation. yes
scope The scope that you are requesting, for example, accounts or payments. yes
request The encoded JWT generated from the previous step. yes

Sample redirect after successful response

https://www.revolut_redirect.com/?code=oa_sand_sPoyVs-oMhyR36j5N-ZEVLfK9rQWPNssgIQqsOFZQ-c&id_token=eyJraWQiOiJxRlFQaTRPVkJVLVNaVk5iMjJ5VjVHQVZDN1UiLCJhbGciOiJQUzI1NiJ9.eyJpc3MiOiJodHRwczovL29iYS5yZXZvbHV0LmNvZGVzIiwiaWF0IjoxNjA0OTM2ODUzLCJzdWIiOiI0NjdiYzg3MC1jOTllLTQ0MzQtYTk1OS1iOGM1NmVlNmEwMjciLCJhY3IiOiJ1cm46b3BlbmJhbmtpbmc6cHNkMjpzY2EiLCJvcGVuYmFua2luZ19pbnRlbnRfaWQiOiI0NjdiYzg3MC1jOTllLTQ0MzQtYTk1OS1iOGM1NmVlNmEwMjciLCJhdWQiOiIxZWMxZGIyZC0zZTViLTRkODItYjQyZS0wNjc5NDU2MmUyMGUiLCJub25jZSI6Im4tMFM2X1d6QTJNaiIsImV4cCI6MTYwNDkzNzQ1MywiY19oYXNoIjoiTXNfRnRwdWs0U2VDNW4zdUNMTTc0ZyIsInNfaGFzaCI6IlM2YVhOY3BUZGw3V3B3bnR0V3h1b2cifQ.m-EvhggqLg7ZXh0we_PLKNsc248p8Bn_o5nj7_6CQHkiRI23ZrYjJLlz_1BhvZ_iY1Tll2gybq_0eSKRgHpvOPnhvCbcSAyfkE8YERZoVkIe-64cyiomhaqBzMzjQyghaL4KrnKH667wR1gTjVhwyJyztalTKidoLZ5OFVWRSHkqW3YLm-_q51wP0k7HHvJ-fnkGcIoCv2TYXpb9xykvgGRJv9KIISbQtM_bLBpo5Q6Q1fxNc-LK2iT-o22xQzLhzvGHtXLTl7Kn5xYf8quDjA5zG0iCAGLJ-Fo9NuTobcKjJOaNYpQ_Y2ilKMmtXqRdgAF_in4Lydt2dn9duxFvJA&state=state

On successful completion of the authorization flow, you receive an authorization code (code) as a URL parameter in the redirect.

Check the response example on the right to see what the code looks like.

5. Exchange authorization code for access token

Exchange for access token

curl -k --key private.key --cert transport.pem \
--location --request POST 'https://sandbox-oba-auth.revolut.com/token' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--data-encoded grant_type=authorization_code \
--data-encoded code=<insert auth_code>
curl  --key private.key --cert transport.pem \
--location --request POST 'https://oba-auth.revolut.com/token' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--data-encoded grant_type=authorization_code \
--data-encoded code=<insert auth_code>

Response

{
  "access_token":"oa_sand_tP1Nofi1ixsRfBmVBtVPdIVN0J5x91imqmheQIWTS5s",
  "token_type":"Bearer",
  "expires_in":7775999,
  "id_token":"eyJraWQiOiJxRlFQaTRPVkJVLVNaVk5iMjJ5VjVHQVZDN1UiLCJhbGciOiJQUzI1NiJ9.eyJpc3MiOiJodHRwczovL29iYS5yZXZvbHV0LmNvZGVzIiwic3ViIjoiNDY3YmM4NzAtYzk5ZS00NDM0LWE5NTktYjhjNTZlZTZhMDI3IiwiYXVkIjoiMWVjMWRiMmQtM2U1Yi00ZDgyLWI0MmUtMDY3OTQ1NjJlMjBlIiwibm9uY2UiOiJuLTBTNl9XekEyTWoiLCJleHAiOjE2MDQ5Mzc0Nzk1NjksImlhdCI6MTYwNDkzNjg3OX0.NrcI6qSwmkTC4zhVP7S9Se1RD8Mnwfz5D3RyGp_5CI7MN6-GLqGHnIBNPNzbUBjlmer8ecCvhm0j9tkScT0xDMSZUdMjRyvb7qrsXYTVbj0ogDPthZSe-45tiq3y4oOsIusIwMPFWGHzI2zq_wzxYY8h6QXFIK6TB_oC93jM6J5JEUUQwvDR23ntcCoH_9uNaGM2PXO2ppxhxZiJe92TYcoZFCIMxqrcVxuUYM1VLQ8d7TcpoIDWdOmtOVqDYmblUHyjFpO3IcBHalua0LRGmU3ZuaEv2iG3YzpqV0OMIHFUe9fQ95z_jID4rGIWwxRL6URIdzw6ZSSyxRXKRWNh3g"
}

After the user authorize your consent, you use the /token endpoint with grant_type=authorization_code to get the access token that you can use to access the Accounts API.

6. Get a list of accounts

Get a list of accounts

curl -X GET https://sandbox-oba.revolut.com/accounts \
--header 'Authorization: Bearer <insert access_token>' \
--header 'x-fapi-financial-id: 001580000103UAvAAM'
curl -X GET https://oba.revolut.com/accounts \
--header 'Authorization: Bearer <insert access_token>' \
--header 'x-fapi-financial-id: 001580000103UAvAAM'

Response

{
  "Data": {
    "Account": [
      {
        "AccountId": "A1086696-D134-472D-B83E-A3F4D201C058",
        "Currency": "GBP",
        "AccountType": "Personal",
        "AccountSubType": "CurrentAccount",
        "Nickname": "Bills",
        "Account": [
          {
            "SchemeName": "UK.OBIE.SortCodeAccountNumber",
            "Identification": "80200110203345",
            "Name": "Mr Kevin",
            "SecondaryIdentification": "00021"
          }
        ]
      }
    ]
  },
  "Links": {
    "Self": "https://oba.revolut.com/accounts/"
  },
  "Meta": {
    "TotalPages": 1
  }
}

After you generate this access token, you can use it to send requests to the API. Make a call to the /accounts endpoint to retrieve a list of the user's accounts.

Congratulations! You have successfully made your first API request to one of our Accounts and Transactions endpoints.

What’s next

Initiate your first payment

This tutorial walks you through the steps to initiate a domestic-payment.

Similar steps apply to all of our payments endpoints. Therefore, after you complete this tutorial, you will know how to use all the payments endpoints.

See the API Reference for all the supported payments.

Before you begin, ensure that:

1. Generate a client credentials token

Get access token

curl -k --cert transport.pem --key server.key \
--location --request POST 'https://sandbox-oba-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=payments'
curl --cert transport.pem --key server.key \
--location --request POST 'https://oba-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=payments'

Response

{
  "access_token":"eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q",
  "token_type":"Bearer",
  "expires_in":2399
}

Request an access token for client credentials using the /token endpoint and the client_credentials grant type.

You use this token to:

x-jws-signature header

{
  "alg": "PS256",
  "kid": "test-kid",
  "crit": ["http://openbanking.org.uk/tan"],
  "http://openbanking.org.uk/tan": <insert JWKs root domain>
}

Create a consent

curl --location --request POST 'https://sandbox-oba.revolut.com/domestic-payment-consents' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Content-Type: application/json' \
--header 'x-idempotency-key: 123' \
--header 'Authorization: Bearer <insert client_credentials token>' \
--header 'x-jws-signature: <insert jws signature>' \
--data '
{
  "Data": {
    "Initiation": {
      "InstructionIdentification": "ID412",
      "EndToEndIdentification": "E2E123",
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698",
        "Name": "Receiver Co."
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipment fee"
      }
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceGoods",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "1238808123123",
    "DeliveryAddress": {
      "AddressLine": ["7"],
      "StreetName": "Apple Street",
      "BuildingNumber": "1",
      "PostCode": "E2 7AA",
      "TownName": "London",
      "Country": "UK"
    }
  }
}'
curl --location --request POST 'https://oba.revolut.com/domestic-payment-consents' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Content-Type: application/json' \
--header 'x-idempotency-key: 123' \
--header 'Authorization: Bearer <insert client_credentials token>' \
--header 'x-jws-signature: <insert jws signature>' \
--data '
{
  "Data": {
    "Initiation": {
      "InstructionIdentification": "ID412",
      "EndToEndIdentification": "E2E123",
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698",
        "Name": "Receiver Co."
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipment fee"
      }
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceGoods",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "1238808123123",
    "DeliveryAddress": {
      "AddressLine": ["7"],
      "StreetName": "Apple Street",
      "BuildingNumber": "1",
      "PostCode": "E2 7AA",
      "TownName": "London",
      "Country": "UK"
    }
  }
}

Response

{
  "Data": {
    "Status": "AwaitingAuthorisation",
    "StatusUpdateDateTime": "2020-11-20T08:35:53.523806Z",
    "CreationDateTime": "2020-11-20T08:35:53.523806Z",
    "ConsentId": "6686e444-c103-4077-8085-8e094200c425",
    "Initiation": {
      "InstructionIdentification": "ID412",
      "EndToEndIdentification": "E2E123",
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698",
        "Name": "ReceiverCo."
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipmentfee"
      }
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceGoods",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "1238808123123",
    "DeliveryAddress": {
      "AddressLine": [
        "7"
      ],
      "StreetName": "AppleStreet",
      "BuildingNumber": "1",
      "PostCode": "E27AA",
      "TownName": "London",
      "Country": "UK"
    }
  },
  "Links": {
    "Self": "https://oba.revolut.com/domestic-payment-consents/6686e444-c103-4077-8085-8e094200c425"
  },
  "Meta": {
    "TotalPages": 1
  }
}

Create a consent to initiate a domestic payment on behalf of a Revolut customer.

When you create the consent, ensure that you

3. Create a JWT URL parameter

After you create a consent, you need the users to authorize the consent so that you can initiate a payment on their behalf.

Header

{
  "alg": "PS256",
  "kid": "test-kid"
}

Body

{
  "response_type": "code id_token",
  "client_id": <insert client_id>,
  "redirect_uri": <insert redirect_uri>,
  "scope": "payments",
  "claims": {
    "id_token": {
      "openbanking_intent_id": {
        "value": <insert ConsentId>
      }
    }
  }
}

Create a JWT request parameter with the header and body format on the right, signed by your signing certificate’s private key. This signature is validated using the JWKs endpoint that you specified during the registration of your application.

Sample URL

https://sandbox-oba.revolut.com/ui/index.html?response_type=code%26id_token&scope=payments&redirect_uri=<insert redirect URL>&client_id=<insert client_id>&request=<insert JWT>
https://oba.revolut.com/ui/index.html?response_type=code%26id_token&scope=accounts&redirect_uri=<insert redirect URL>&client_id=<insert client_id>&request=<insert JWT>

Redirect the user to the authorization URL with the following parameters.

Parameter Description Required
response_type Always set to code&id_token. yes
client_id The client ID for your application. yes
redirect_uri One of the redirect URIs that you defined during the application creation. yes
scope The scope that you are requesting, for example, accounts or payments. yes
request The encoded JWT generated from the previous step. yes

Sample redirect after successful response

https://www.revolut_redirect.com/?code=oa_sand_sPoyVs-oMhyR36j5N-ZEVLfK9rQWPNssgIQqsOFZQ-c&id_token=eyJraWQiOiJxRlFQaTRPVkJVLVNaVk5iMjJ5VjVHQVZDN1UiLCJhbGciOiJQUzI1NiJ9.eyJpc3MiOiJodHRwczovL29iYS5yZXZvbHV0LmNvZGVzIiwiaWF0IjoxNjA0OTM2ODUzLCJzdWIiOiI0NjdiYzg3MC1jOTllLTQ0MzQtYTk1OS1iOGM1NmVlNmEwMjciLCJhY3IiOiJ1cm46b3BlbmJhbmtpbmc6cHNkMjpzY2EiLCJvcGVuYmFua2luZ19pbnRlbnRfaWQiOiI0NjdiYzg3MC1jOTllLTQ0MzQtYTk1OS1iOGM1NmVlNmEwMjciLCJhdWQiOiIxZWMxZGIyZC0zZTViLTRkODItYjQyZS0wNjc5NDU2MmUyMGUiLCJub25jZSI6Im4tMFM2X1d6QTJNaiIsImV4cCI6MTYwNDkzNzQ1MywiY19oYXNoIjoiTXNfRnRwdWs0U2VDNW4zdUNMTTc0ZyIsInNfaGFzaCI6IlM2YVhOY3BUZGw3V3B3bnR0V3h1b2cifQ.m-EvhggqLg7ZXh0we_PLKNsc248p8Bn_o5nj7_6CQHkiRI23ZrYjJLlz_1BhvZ_iY1Tll2gybq_0eSKRgHpvOPnhvCbcSAyfkE8YERZoVkIe-64cyiomhaqBzMzjQyghaL4KrnKH667wR1gTjVhwyJyztalTKidoLZ5OFVWRSHkqW3YLm-_q51wP0k7HHvJ-fnkGcIoCv2TYXpb9xykvgGRJv9KIISbQtM_bLBpo5Q6Q1fxNc-LK2iT-o22xQzLhzvGHtXLTl7Kn5xYf8quDjA5zG0iCAGLJ-Fo9NuTobcKjJOaNYpQ_Y2ilKMmtXqRdgAF_in4Lydt2dn9duxFvJA&state=state

On successful completion of the authorization flow, you receive an authorization code (code) as a URL parameter in the redirect.

Check the response example on the right to see what the code looks like.

5. Exchange authorization code for access token

Exchange for access token

curl -k --key private.key --cert transport.pem \
--location --request POST 'https://sandbox-oba-auth.revolut.com/token' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--data-encoded grant_type=authorization_code \
--data-encoded code=<insert auth_code>
curl  --key private.key --cert transport.pem \
--location --request POST 'https://oba-auth.revolut.com/token' \
--header 'Content-Type:application/x-www-form-urlencoded' \
--data-encoded grant_type=authorization_code \
--data-encoded code=<insert auth_code>

Response

{
  "access_token":"oa_sand_tP1Nofi1ixsRfBmVBtVPdIVN0J5x91imqmheQIWTS5s",
  "token_type":"Bearer",
  "expires_in":7775999,
  "id_token":"eyJraWQiOiJxRlFQaTRPVkJVLVNaVk5iMjJ5VjVHQVZDN1UiLCJhbGciOiJQUzI1NiJ9.eyJpc3MiOiJodHRwczovL29iYS5yZXZvbHV0LmNvZGVzIiwic3ViIjoiNDY3YmM4NzAtYzk5ZS00NDM0LWE5NTktYjhjNTZlZTZhMDI3IiwiYXVkIjoiMWVjMWRiMmQtM2U1Yi00ZDgyLWI0MmUtMDY3OTQ1NjJlMjBlIiwibm9uY2UiOiJuLTBTNl9XekEyTWoiLCJleHAiOjE2MDQ5Mzc0Nzk1NjksImlhdCI6MTYwNDkzNjg3OX0.NrcI6qSwmkTC4zhVP7S9Se1RD8Mnwfz5D3RyGp_5CI7MN6-GLqGHnIBNPNzbUBjlmer8ecCvhm0j9tkScT0xDMSZUdMjRyvb7qrsXYTVbj0ogDPthZSe-45tiq3y4oOsIusIwMPFWGHzI2zq_wzxYY8h6QXFIK6TB_oC93jM6J5JEUUQwvDR23ntcCoH_9uNaGM2PXO2ppxhxZiJe92TYcoZFCIMxqrcVxuUYM1VLQ8d7TcpoIDWdOmtOVqDYmblUHyjFpO3IcBHalua0LRGmU3ZuaEv2iG3YzpqV0OMIHFUe9fQ95z_jID4rGIWwxRL6URIdzw6ZSSyxRXKRWNh3g"
}

After the user authorize your consent, you use the /token endpoint with grant_type=authorization_code to get the access token to use the /domestic-payments endpoint.

6. Initiate a domestic payment

Create a domestic payment

curl --location --request POST 'https://sandbox-oba.revolut.com/domestic-payments' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Content-Type: application/json' \
--header 'x-idempotency-key: 123' \
--header 'Authorization: Bearer <insert acces_token>' \
--header 'x-jws-signature: <insert jws signature>' \
--data '
{
  "Data": {
    "ConsentId":<insert consent_id>
    "Initiation": {
      "InstructionIdentification": "ID412",
      "EndToEndIdentification": "E2E123",
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698",
        "Name": "Receiver Co."
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipment fee"
      }
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceGoods",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "1238808123123",
    "DeliveryAddress": {
      "AddressLine": ["7"],
      "StreetName": "Apple Street",
      "BuildingNumber": "1",
      "PostCode": "E2 7AA",
      "TownName": "London",
      "Country": "UK"
    }
  }
}
curl --location --request POST 'https://oba.revolut.com/domestic-payments' \
--header 'x-fapi-financial-id: 001580000103UAvAAM' \
--header 'Content-Type: application/json' \
--header 'x-idempotency-key: 123' \
--header 'Authorization: Bearer <insert acces_token>' \
--header 'x-jws-signature: <insert jws signature>' \
--data '
{
  "Data": {
    "ConsentId":<insert consent_id>
    "Initiation": {
      "InstructionIdentification": "ID412",
      "EndToEndIdentification": "E2E123",
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "CreditorAccount": {
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698",
        "Name": "Receiver Co."
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipment fee"
      }
    }
  },
  "Risk": {
    "PaymentContextCode": "EcommerceGoods",
    "MerchantCategoryCode": "5967",
    "MerchantCustomerIdentification": "1238808123123",
    "DeliveryAddress": {
      "AddressLine": ["7"],
      "StreetName": "Apple Street",
      "BuildingNumber": "1",
      "PostCode": "E2 7AA",
      "TownName": "London",
      "Country": "UK"
    }
  }
}

Response

{
  "Data": {
    "DomesticPaymentId": "dd817a13-3198-48ca-a5dc-f22b09ee82c0",
    "Status": "AcceptedSettlementInProcess",
    "StatusUpdateDateTime": "2020-11-20T08:54:30.115047Z",
    "CreationDateTime": "2020-11-20T08:54:30.115047Z",
    "ConsentId": "6686e444-c103-4077-8085-8e094200c425",
    "Initiation": {
      "CreditorAccount": {
        "Name": "ReceiverCo.",
        "SchemeName": "UK.OBIE.SortCodeAccountNumber",
        "Identification": "11223321325698"
      },
      "InstructedAmount": {
        "Amount": "55.00",
        "Currency": "GBP"
      },
      "RemittanceInformation": {
        "Reference": "ReceiverRef",
        "Unstructured": "Shipmentfee"
      },
      "EndToEndIdentification": "E2E123",
      "InstructionIdentification": "ID412"
    }
  },
  "Links": {
    "Self": "https://oba.revolut.com/domestic-payments/dd817a13-3198-48ca-a5dc-f22b09ee82c0"
  },
  "Meta": {
    "TotalPages": 1
  }
}


After you generate this access token, you can initiate a domestic payment on the user's behalf. Make a call to the /domestic-payments endpoint to initiate the payment.

Congratulations! You have successfully initiated your first payment.

What’s next

Create your first draft payment

To use our draft payments endpoint, you must register your application and request an approval in the Developer Portal.

1. Get user's authorization

Draft Payments authorization URL

https://sandbox-business.revolut.com/partner-confirm?response_type=code&state=state&scope=draftpayments&client_id=your_client_id&redirect_uri=your_redirect_uri
https://business.revolut.com/partner-confirm?response_type=code&state=state&scope=draftpayments&client_id=your_client_id&redirect_uri=your_redirect_uri

Response

https://www.revolut_redirect.com/revolut_redirect?code=oa_sand_kiLg3m7xrNua0rbShC1GQZfbk0DthUhOpVA9xX2oRY0&state=state

Before you can start creating draft payments, you must get authorization from the user to make draft payments on their behalf.

Redirect the user to the authorization URL with the following parameters.

Parameter Description Required
scope The scope for authorization required from the user. yes
client_id The client ID for your application. yes
redirect_uri One of the redirect URIs that you defined during the application creation. yes
state The generated string to verify the response is initiated by the same user. yes

On successful completion of the authorization flow, you receive an authorization code (code).

Check the response example on the right to see what the code looks like.

2. Exchange authorization code for access token

Token request via MTLS

curl -k --key your_private.key --cert your_transport.pem \
--location --request POST 'https://sandbox-mtls-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=<insert authorisation_code>'
curl  --key your_private.key --cert your_transport.pem \
--location --request POST 'https://mtls-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=<insert authorisation_code>'

MTLS response

{"access_token":"oa_sand_tG6kRPb2LAYJZx1c3w1NZ7ntuscssWqsC6WkaW9jbER-E","token_type":"Bearer","expires_in":7775999}

Exchange your authorization code for an access token using the token endpoint. Check the request example on the right.

3. Create a draft payment

Create a draft payment

curl --location --request POST 'https://sandbox-apis.revolut.com/draft-payments' \
--header 'Authorization: Bearer <insert access_token.' \
--header 'Content-Type: text/csv' \
--data-binary @draft_payments.csv
curl --location --request POST 'https://apis.revolut.com/draft-payments' \
--header 'Authorization: Bearer <insert access_token.' \
--header 'Content-Type: text/csv' \
--data-binary @draft_payments.csv

Response

{"DraftPaymentId":"4bc0a477-2c81-4f49-bf5b-c6705bb7a6d9"}

After you have an access token, you can use the /draft-payments endpoint to create a draft payment on behalf of the user. Include a CSV file with the supported format shown in the following tables.

After you create the draft payment, it appears in the user's Revolut Business account where user can approve or reject.

For information about which fields are required based on the country and the currency, See International payments.

Parameters

Name Located in Description Required Schema
scheduledDate query The date and time the draft payment is executed. Any draft payment in the CSV file is created as a scheduled payment. No date in "YYYY-MM-DD" format

CSV format

Field Required Description
Name Yes Can contain up to 80 characters. If recipient type is INDIVIDUAL, this field must contain a first and a last name, separated by a space.
Recipient type Yes Can be either INDIVIDUAL or COMPANY.
Account number For non-IBAN countries Must contain valid account number if provided.
Sort code or Routing number For UK/US local transfers Must contain valid sort code or routing number if provided.
IBAN For IBAN countries Must contain valid IBAN if provided.
BIC All the countries except for UK/US local Must contain valid BIC if provided.
Recipient bank country Yes Must contain valid ISO 3166-1 country code.
Currency Yes Must contain valid ISO 4217 currency code.
Amount Yes Must match following pattern [0-9]*(\\.[0-9]*)?
Payment reference Yes Can contain up to 100 characters.
Recipient country No Must contain valid ISO 3166-1 country code if provided.
State or province No Can contain up to 50 characters.
Address line 1 No Can contain up to 50 characters.
Address line 2 No Can contain up to 50 characters.
City No Can contain up to 50 characters.
Postal code No Can contain up to 50 characters.

4. Get a draft payment

Get the details of a draft payment

curl -X GET https://sandbox-apis.revolut.com/draft-payments/{DraftPaymentId} \
--header 'Authorization: Bearer <insert access_token>'
curl -X GET https://apis.revolut.com/draft-payments/{DraftPaymentId} \
--header 'Authorization: Bearer <insert access_token>'

Response

{
    "Status": "Processed",
    "Transfers": [
        {
            "InstructedAmount": {
                "Amount": "10.00",
                "Currency": "GBP"
            },
            "Reference": "User comment",
            "Status": "Created",
            "Index": 1
        },
        {
            "InstructedAmount": {
                "Amount": "20.00",
                "Currency": "GBP"
            },
            "Reference": "User reference",
            "Status": "Failed",
            "FailedReason": "Something went wrong",
            "FailedReasonCode": 3067,
            "Index": 2
        }
    ]
}

Get the details about a specific draft payment with the given draft payment ID.

Index indicates the row number the draft payment represents in the CSV file.

What’s next

Work with draft payments

Review the important considerations when you build your draft payments integration.

International payments

In the CSV file that you upload to create draft payments, the following fields and multiple address fields are provided for draft payments made to bank accounts across the globe.

For each draft payment, the following fields are required:

However, depending on the currency and the country of the bank account, some fields are also required for a draft payment in the CSV file, which is shown in the following table:

Country Currency Fields Required
GB GBP Account Number, SortCode
SEPA Country EUR IBAN, BIC
DK, NO, SE Local currency (DKK, NOK, SEK) IBAN, BIC
IBAN Country Any supported (with exception of Euros in SEPA) IBAN, BIC, Address
US USD Account number, Routing number, Address, State or province
US Any supported (with exception of USD) Account number, BIC, Address, State or province
HK Any supported Account number, BIC, Address
PH Any supported + PHP Account number, BIC, Address
ID Any supported + IDR Account number, BIC, Address

See the following lists for IBAN/SEPA countries and currencies supported.

Type List
SEPA countries AT, AX, BE, BG, BL, CH, CZ, DE, DK, EE, ES, FI, FR, GB, GF, GP, GR, HR, HU, IC, IE, IS, IT, LT, LU, LV, MF, MQ, NL, NO, PL, PM, PT, RE, RO, SE, SI, SK, SM, TF, VA, YT
IBAN countries AD, AE, AL, AO, AT, BA, BE, BG, BH, CH, CR, CY, CZ, DE, DK, DO, DZ, EE, ES, FI, FO, FR, GB, GE, GF, GI, GL, GR, HR, HU, IE, IL, IS, IT, JO, KW, KZ, LB, LI, LT, LU, LV, MC, MD, ME, MG, MK, MQ, MR, MT, MU, NL, NO, PK, PL, PM, PS, PT, QA, RO, RS, SA, SE, SI, SK, SM, TF, TN, TR, VA, VG, YT
Currencies supported AED, AUD, BGN, CAD, CHF, CZK, DKK, EUR, GBP, HKD, HRK, HUF, ILS, JPY, MXN, NOK, NZD, PLN, QAR, RON, SAR, SEK, SGD, THB, TRY, USD, ZAR

Account selection

In Revolut Business, an account can have multiple pockets in different currencies.

The pocket selected for a draft payment is the pocket with the highest amount of currency that matches the currency of the payment.

If no pocket matches the currency of the payment, the pocket with the default currency of the account is chosen and there is an automatic currency conversion while the payment is being executed.

CSV validation

CSV with errors

Name,Recipient type,Account number,Sort code or Routing number,IBAN,BIC,Recipient bank country,Currency,Amount,Payment reference,Recipient country,State or province,Address line 1,Address line 2,City,Postal code
Dmitry Vim,INDIVIDUAL,40513598,207409,,,GB,GBP,10,Comment Comment Comment Comment Comment Comment Comment Comment Comment Comment Comment Comment Comment Comment,GB,,Revolutest LTD, Level 39,Somewhere in London,E14 5AB
Dmitry Vim,INDIVIDUAL,40513598,207409,,,GB,abc,25,Second comment,uk,,Revolutest LTD, Level 39,Somewhere in London,E14 5AB
,INDIVIDUAL,,,,,GB,GBP,25,Second comment,GB,,Revolutest LTD Level 39,Somewhere in London,Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwhenuakitanatahu,E14 5AB
Dmitry Vim,INDIVIDUAL,776644,,,BOFMHKHH,CN,USD,10,User comment,CN,,1 Yuan,,Beijing City,100046
Dmitry Vim,,40513598,207409,,,GB,GBP,0.10,User comment,GB,,Revolutest LTD, Level 39,Somewhere in London,E14 5AB
Dmitry Vim,INDIVIDUA,40513598,207409,,,GB,GBP,10,User comment,GB,,Revolutest LTD, Level 39,Somewhere in London,E14 5AB
Dmitry Vim,INDIVIDUAL,ÓŁ,2409,1234,ABC,GB,GBP,10,User comment,GB,,Revolutest LTD, Level 39,Somewhere in London,E14 5AB
DmitryVim,INDIVIDUAL,40513598,207409,,,GB,GBP,10,User comment,GB,,,Somewhere in London,123
Dmitry Vim,INDIVIDUAL,40513598,207409,,,GB,GBP,10,User comment,GB,,Revolutest LTD, Level 39,Somewhere in London,123

Response

{
  "Id": "a3805a6c-ae21-4871-b9a3-2c2c9db60ffa",
  "Message": "File validation failed",
  "Errors": [{
    "Row": 2,
    "Errors": [{
      "Field": "Payment reference",
      "Code": 2003,
      "Message": "Payment reference cannot be longer than 100 symbols"
    }]
  }, {
    "Row": 3,
    "Errors": [{
      "Field": "Currency",
      "Code": 2004,
      "Message": "Invalid Currency: abc"
    }, {
      "Field": "Recipient country",
      "Code": 2004,
      "Message": "Invalid Recipient country: uk"
    }]
  }, {
    "Row": 4,
    "Errors": [{
      "Field": "Name",
      "Code": 2001,
      "Message": "Name is required"
    }, {
      "Field": "City",
      "Code": 2003,
      "Message": "City cannot be longer than 50 symbols"
    }]
  }, {
    "Row": 5,
    "Errors": [{
      "Code": 2008,
      "Message": "Invalid BIC for CN bank country"
    }]
  }, {
    "Row": 6,
    "Errors": [{
      "Field": "Recipient type",
      "Code": 2001,
      "Message": "Recipient type is required"
    }]
  }, {
    "Row": 7,
    "Errors": [{
      "Field": "Recipient type",
      "Code": 2004,
      "Message": "Invalid Recipient type: INDIVIDUA"
    }]
  }, {
    "Row": 8,
    "Errors": [{
      "Field": "Account number",
      "Code": 2004,
      "Message": "Invalid Account number: �?"
    }, {
      "Field": "Sort code or Routing number",
      "Code": 2004,
      "Message": "Invalid Sort code or Routing number: 2409"
    }, {
      "Field": "IBAN",
      "Code": 2004,
      "Message": "Invalid IBAN: 1234"
    }, {
      "Field": "BIC",
      "Code": 2004,
      "Message": "Invalid BIC: ABC"
    }]
  }, {
    "Row": 9,
    "Errors": [{
      "Field": "Name",
      "Code": 2005,
      "Message": "First and last name are required for individuals"
    }]
  }, {
    "Row": 10,
    "Errors": [{
      "Code": 2008,
      "Message": "Postcode 123 is invalid, please change it before continuing"
    }]
  }],
  "Code": 3039
}

We validate if the fields in the CSV match the format required and if the bank account details provided are valid for a payment to be made.

If there is an issue with the CSV uploaded, the API responds with a 3039 error code and give details of the CSV validation errors row by row. Each error message is accompanied by a corresponding code.

Error codes

Check the example file on the right and the response with relevant errors.

Code Reason Sample error messages
2001 The fields that are required are missing in the CSV. Name is required, Recipient type is required.
2002 The amount field is not a valid decimal number. Invalid amount format: 0;10, use only numbers and dot to separate cents, Invalid amount format: A, use only numbers and dot to separate cents.
2003 The string size is too large. Name cannot be longer than 80 symbols, City cannot be longer than 50 symbols.
2004 One of the fields in the CSV is invalid. Invalid Recipient type: INDIVIDUA, Invalid IBAN: 1234, Invalid Recipient country: uk.
2005 The first and last name is required when recipient type is INDVIDUAL. First and last name are required for individuals
2008 It was not possible to create counterparty based on the details provided。 Invalid BIC for <some_country> bank country, Unsupported currency for external beneficiary, Postcode <postcode> is invalid, please change it before continuing.
2009 Payments must be greater than 0 Amount has to be greater than zero.
1000 Unknown reason Something went wrong. Please contact support., Something went wrong: <error_id>

Error codes

Check the following table to understand the error messages for draft payments:

Http Error Code Message Reason
400 2101 Maximum file size limit of 10MB bytes exceeded File size uploaded was too large.
400 2101 Multiple currencies in single file are not allowed Only payments in one currency can be uploaded.
400 3039 File validation failed There was an error in the details provided in the CSV.
403 9002 This action is forbidden The user that tried to make this action was not the Business owner of the account.
404 3070/11101 Not found error Draft payment was not found.
422 3058/11102 Invalid state error Draft payment was not in the right state for a certain action. For example trying to delete a draft payment that had already been processed.

Payment orders vs transfers

When you create a bulk draft payment, it consists of a draft payment order, which in turn contains a set of transfers.

Both a draft payment order and transfers have own independent states.

Draft payment order

A draft payment order is what the user either approves or deletes from the user interface. It can have the following possible states:

Draft Payment Order Status Description
Awaiting The draft payment order is created and awaiting approval from user.
Approved The draft payment order is approved by the user and the transfers are in the process of being executed.
Processed The draft payment order is processed.
Deleted The draft payment order is deleted by the user.

Transfers

When the user approves a draft payment order, each transfer is executed individually. Each transfer can have the following possible states:

Transfer Status Description
Created The transfer is created but hasn't been executed yet.
Pending The transfer is in the queue to be executed.
Completed The transfer is completed successfully and a payment has been made from the users account.
Failed The transfer fails and no payment has been made. Accompanying failure reason code and message are returned in GET endpoint.
Deleted The transfer is deleted by the user.

Failure codes

There are a number of different reasons that transfers can fail.

Check the following table about different values of FailedReasonCode:

Failure Code Description
1003 Recipient is unable to receive funds.
1006 User has insufficient balance to execute the payment.
4000 Internal transfer error. Typically occurs when a user is trying to send a payment to a sub-account or sending to an account with the incorrect currency.
4032 Invalid transfer reference. The transfer reference that was detailed in the payment was invalid.
3067 Unknown error. Please ask user to reach out to support.

Each FailedReasonCode is accompanied by a custom FailedReasonMessage to give detail on the failure.

Work with webhooks

Webhooks allow you to receive real-time notifications for events that are happening in relation to your application.

When a supported event occurs, a real-time notification is posted, via HTTP POST method, to the specified endpoint.

1. Generate a client credentials token

Get a token

curl -k --cert transport.pem --key server.key \
--location --request POST 'https://sandbox-mtls-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=draftpayments'
curl --cert transport.pem --key server.key \
--location --request POST 'https://mtls-auth.revolut.com/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=draftpayments'

Response

{
  "access_token":"eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q",
  "token_type":"Bearer",
  "expires_in": 2399
}

Request an access token for client credentials using the /token endpoint and the client_credentials grant type.

2. Create a webhook

Create webhook

curl --location --request POST 'https://sandbox-apis.revolut.com/webhooks/subscribe' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q' \
--data-raw '
{
    "Topic": "draftpayments/transfers",
    "Version": 1,
    "Uri": "https://revolut_test.com" 
}'
curl --location --request POST 'https://apis.revolut.com/webhooks/subscribe' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjFlYzFkYjJkLTNlNWItNGQ4Mi1iNDJlLTA2Nzk0NTYyZTIwZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDQ5MzAzOTh9.pMMtYxYh8_M8P0v9_yfJ29iq3h2x_1RT6BLJPbrJ6SSsai_fQmMNGWXtDapPCSvWtn-ol0aN8Pl725uSSJqWHFxdh0PwvKP1762s5jy7xcLTkb8tgg-AoTPm87-vsnHnw5z63yiDW1Migdx7vDN_jRe3WUSfE-u0Qv7W3SLVo8kB5-qxn2VHZTBSaBr5XReINBHJgh7Xi9LzqxqUh0yCiZSSRnu8o7-I_Q1K0jPK1D7ve7BxlkOb5fSR59CbtzfkZpI6jKDOWSqU_5mftqRRylle382nfS6AeY2eubdH6OS-lJRFcwsYplauE-tZ__54G4LTjPhUWQezvewCc5gq2Q' \
--data-raw '
{
    "Topic": "draftpayments/transfers",
    "Version": 1,
    "Uri": "https://revolut_test.com" 
}'

For draft payments, the following types of topic are supported:

This means that when the state of transfers and orders that your application previously created changes, a notification is sent. Each topic that you subscribe to requires an individual API call.

To create a webhook, make a call to the /webhooks/subscribe endpoint.

3. Get list of webhook URIs

Get list of webhooks

curl --location --request GET 'https://sandbox-oba.revolut.com/webhooks' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjQ4ZjllZWJjLTA0YmItNGM2NS1hMzE1LWIwYjQ1OWJhN2I5ZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDk3Nzk0NzF9.ihoDIi5bELncONFL68uAmKgGJPe7ShyUCpOXHwjjzwYSW8M9G-kb6As9ybaNFYsaK2ee3BhPo0eIhnXCPFocpWc7OLeaJq_q4ytCHafvvgQNBNJH6lKJEGAne6QYyAtkYxR7hIaaX-AKOGNBy_-gtigrgyb5-qqtg5KP25eBF9JkygTlAIYZPq7IhENjBocWCYXNetUVOy7oA2tGyW_r3QdI9adMKu-Iqhx2cBh6aXMOjydmz8K6iv9quzNHB-Oh32Riz9V9kX1XEt5We32VgRM_S1Vdw7x1-sVZKMTPkh0CVnORpDYns9rwcEBfm3qEidd0HqcBgBXqWuoxBhQAhA'
curl --location --request GET 'https://oba.revolut.com/webhooks' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjQ4ZjllZWJjLTA0YmItNGM2NS1hMzE1LWIwYjQ1OWJhN2I5ZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDk3Nzk0NzF9.ihoDIi5bELncONFL68uAmKgGJPe7ShyUCpOXHwjjzwYSW8M9G-kb6As9ybaNFYsaK2ee3BhPo0eIhnXCPFocpWc7OLeaJq_q4ytCHafvvgQNBNJH6lKJEGAne6QYyAtkYxR7hIaaX-AKOGNBy_-gtigrgyb5-qqtg5KP25eBF9JkygTlAIYZPq7IhENjBocWCYXNetUVOy7oA2tGyW_r3QdI9adMKu-Iqhx2cBh6aXMOjydmz8K6iv9quzNHB-Oh32Riz9V9kX1XEt5We32VgRM_S1Vdw7x1-sVZKMTPkh0CVnORpDYns9rwcEBfm3qEidd0HqcBgBXqWuoxBhQAhA'

Response

[{
  "Topic": "draftpayments/orders",
  "Version": 1,
  "Uri": "https://revolut_test.com"
}, {
  "Topic": "draftpayments/transfers",
  "Version": 1,
  "Uri": "https://revolut_test.com"
}]

When the webhooks are created, make a call to the /webhooks endpoint and you can see them returned in the response.

4. Listen for notifications

Draft payment order notification payload

{
  "Topic": "draftpayments/orders",
  "Version": 1,
  "IdempotencyKey": "8e3cffda-15d9-4596-8068-e95321319973",
  "Data": {
    "Id": "b36b0bb7-c162-4919-8205-32f914b4fa29",
    "Status": "Processed"
  }
}

Draft payment transfer notification payload

{
  "Topic": "draftpayments/transfers",
  "Version": 1,
  "IdempotencyKey": "51350d68-e285-406e-8571-6f7b13f9e024",
  "Data": {
    "Id": "7e18d804-b154-4035-bc8e-7a038acbb104",
    "Status": "Pending"
  }
}

JWKS endpoint

https://sandbox-apis.revolut.com/jwk
https://apis.revolut.com/jwk

When draft payments are approved from the Revolut Business UI, you receive a notification that indicates a change to the state of draft payment order and its individual transfers.

The Status field corresponds to those detailed here.

Please see examples of two payloads to the right. The ID field indicates the relevant object that has changed state, while IdempotencyKey can be used as a unique identifier for a specific event.

The header in the request will contain a detached JWS containing a kid. Please use the JWKS endpoint to the right to validate this signature.

5. Delete a webhook

Unsubscribe from a topic

curl --location --request POST 'https://sandbox-oba.revolut.com/webhooks/unsubscribe' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjQ4ZjllZWJjLTA0YmItNGM2NS1hMzE1LWIwYjQ1OWJhN2I5ZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDk3Nzk0NzF9.ihoDIi5bELncONFL68uAmKgGJPe7ShyUCpOXHwjjzwYSW8M9G-kb6As9ybaNFYsaK2ee3BhPo0eIhnXCPFocpWc7OLeaJq_q4ytCHafvvgQNBNJH6lKJEGAne6QYyAtkYxR7hIaaX-AKOGNBy_-gtigrgyb5-qqtg5KP25eBF9JkygTlAIYZPq7IhENjBocWCYXNetUVOy7oA2tGyW_r3QdI9adMKu-Iqhx2cBh6aXMOjydmz8K6iv9quzNHB-Oh32Riz9V9kX1XEt5We32VgRM_S1Vdw7x1-sVZKMTPkh0CVnORpDYns9rwcEBfm3qEidd0HqcBgBXqWuoxBhQAhA' \
--data-raw '
{
    "Topic": "draftpayments/transfers"
}
'
curl --location --request POST 'https://oba.revolut.com/webhooks/unsubscribe' \
--header 'Authorization: Bearer eyJhbGciOiJQUzI1NiJ9.eyJjbGllbnRJZCI6IjQ4ZjllZWJjLTA0YmItNGM2NS1hMzE1LWIwYjQ1OWJhN2I5ZSIsInNjb3BlcyI6WyJhY2NvdW50cyJdLCJleHAiOjE2MDk3Nzk0NzF9.ihoDIi5bELncONFL68uAmKgGJPe7ShyUCpOXHwjjzwYSW8M9G-kb6As9ybaNFYsaK2ee3BhPo0eIhnXCPFocpWc7OLeaJq_q4ytCHafvvgQNBNJH6lKJEGAne6QYyAtkYxR7hIaaX-AKOGNBy_-gtigrgyb5-qqtg5KP25eBF9JkygTlAIYZPq7IhENjBocWCYXNetUVOy7oA2tGyW_r3QdI9adMKu-Iqhx2cBh6aXMOjydmz8K6iv9quzNHB-Oh32Riz9V9kX1XEt5We32VgRM_S1Vdw7x1-sVZKMTPkh0CVnORpDYns9rwcEBfm3qEidd0HqcBgBXqWuoxBhQAhA' \
--data-raw '
{
    "Topic": "draftpayments/transfers"
}'

If you no longer want to receive notifications on a webhook, you can unsubscribe by running a POST request to the /webhooks/unsubscribe endpoint.

Congratulations! You have successfully set up webhooks to receive relevant notifications about your application.

API Metrics

You can review detailed Open Banking metrics here. You can also compare the performance of our Open Banking API vs the performance of our direct user interfaces for Retail and Business products here.

We update these reports daily and keep them for the last 90 days.

Usage and limits

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

Please make sure to stay under this limit. Should you estimate this limit to be a problem for your use case of our API, please reach out to us directly.

Glossary

For the complete list of Open Banking terms, we recommend viewing the official glossary.

Name Term Definition
TPP Third Party Provider Third Party Providers are organisations or natural persons that use APIs developed to Standards to access customer’s accounts, in order to provide account information services and/or to initiate payments. Third Party Providers are either/both Payment Initiation Service Providers (PISPs) and/or Account Information Service Providers (AISPs).
AISP Account Information Service Provider An Account Information Service provides account information services as an online service to provide consolidated information on one or more payment accounts held by a payment service user with one or more payment service provider(s).
ASPSP Account Servicing Payment Service Provider Account Servicing Payment Service Providers provide and maintain a payment account for a payer as defined by the PSRs and, in the context of the Open Banking Ecosystem are entities that publish Read/Write APIs to permit, with customer consent, payments initiated by third party providers and/or make their customers’ account transaction data available to third party providers via their API end points.





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.
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.