Create your first draft payment
To use our draft payments endpoint, you must register your application and request an approval in the Developer Portal.
Before you begin, ensure that you have:
- Registered your application with the
draftpaymentsin Developer Portal - Obtained a sandbox/production
client_idfrom Developer Portal - Obtained a sandbox/production
transport.pemcertificate from Developer Portal
The draft payment function is available only for Revolut Business customers.
If you get certificate errors when using curl with Sandbox, it usually means your system doesn't trust our certificate issuer. The recommended approach is to add the certificate to your trusted store.
As a quick workaround, you can use the -k (or --insecure) option to skip certificate checks. Be aware this disables all SSL verification, which can hide issues like expired or mismatched certificates and leaves you vulnerable to man-in-the-middle attacks. For these reasons, avoid using -k in production or as a permanent solution.
1. Get user's authorization
https://business.revolut.com/partner-confirm?response_type=code&state=state&scope=draftpayments&client_id=<your client_id>&redirect_uri=<your redirect_uri>
Response would look like this:
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 when you created the application. Keep it static without variable parameters (https://example.com). | yes |
state | The generated string to verify the response is initiated by the same user. | yes |
response_mode | If set to fragment parameters will be passed in fragment section of redirect URI. Otherwise, parameters are passed in URI query. Passing parameters in fragment considered to be more secure. | no |
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.
The code is valid only for two minutes.
2. Exchange authorization code for access token
Token request via MTLS:
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-urlencode 'grant_type=authorization_code' \
--data-urlencode 'client_id=<your client_id>' \
--data-urlencode 'code=<insert authorization_code>'
MTLS response:
{
"access_token":"oa_prod_uuWhyiJt1oSoE6aeSxVO8ZpuR_VtgrgPllZKSvHoQ-I",
"refresh_token":"oa_prod_tUf_3gZJA6vNH4AnBMVEPqbykkfgBomWwDGRo8tBThA",
"access_token_id":"3d3ef8a1-f920-4d6d-9106-e7fcf350125c",
"token_type":"Bearer",
"expires_in":7775999,
}
Exchange your authorization code for an access token using the token endpoint.
Check the request and response example on the right, where:
access_tokenis the access token you received.expires_inis the time duration in seconds that the token is valid for. An access token is valid for 90 days. Before it expires, you must refresh the access token. For more information, see: Tutorials: Create your first draft payment - Refresh access token.access_token_idis used in conjunction with thetokenwebhook to identify tokens where the user has revoked their consent.
3. Refresh access token
Refresh access token:
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-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=<insert refresh_token>'
Response:
{
"access_token":"oa_prod_h_M1nWyehXEkx3kF1QhEoqksQT0NaYKfBuEEBv1dSOY",
"token_type":"Bearer",
"expires_in":7775999
}
Each access token is valid for 90 days. When it expires, you must refresh the access token before you create a draft payment.
To do that, use the refresh_token returned in the previous step to request a new access token that can be used for a further 90 days. Check the request and response example on the right.
4. Create a draft payment
Create a draft payment
curl --location --request POST 'https://apis.revolut.com/draft-payments' \
--header 'Authorization: Bearer <insert access_token>' \
--header 'x-idempotency-key: 2c199c8c-671f-11eb-ae93-0242ac130002' \
--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 and a unique idempotency-key of uuid format.
After you create the draft payment, it appears in the user's Revolut Business account where user can approve or reject.
The maximum number of rows in a CSV file is 50 and all the payments must be in the same currency.
For information about which fields are required based on the country and the currency, see: Tutorials: Work with draft payments - 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 |
title | query | Title field for the Draft Payment order. Note that this is an API-only field, it won't appear in the user interface. | No | string |
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. |
5. Get a draft payment
Get the details of a draft payment:
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.
6. Get list of draft payments
Get a list of draft payments:
curl -X GET https://apis.revolut.com/draft-payments?from=<insert_datefrom>&to=<insert_dateto>&limit=<insert_limit> \
--header 'Authorization: Bearer <insert access_token>'
Response:
{
"Items": [
{
"Id": "d9805904-f722-432c-accd-d0f288c3532e",
"CreatedAt": "2021-03-28T15:16:20.444101Z",
"Status": "Awaiting",
"Title": "test_1"
},
{
"Id": "d9ab7bf0-5781-46ab-b503-d962ae5715ea",
"CreatedAt": "2021-03-24T19:03:03.367473Z",
"Status": "Awaiting",
"Title": "test_2"
}
],
"Links":
{
"Next": "/draft-payments?to=2021-03-24T19:02:21.351937Z&limit=2"
}
}
Get a list of draft payments created by your application.
This endpoint returns draft payments in descending order of creation time and supports pagination: use the limit field to specify the number of orders returned in the request. The location of the next page of results will be returned in the Links.Next field.
Use the to and from parameters to specify the date range that you want to pull Draft Payments from by creation date. from and to dates are inclusive and exclusive of Draft Payments respectively.
Parameters
| Name | Located in | Description | Required | Schema |
|---|---|---|---|---|
from | query | Date and time you retrieve the draft payment orders from. | No | date in "YYYY-MM-2DDThh:mm:ssZ" format |
to | query | The date and time you retrieve the draft payment orders to. The default is now. | No | date in "YYYY-MM-2DDThh:mm:ssZ" format |
limit | query | The number of draft payment orders returned via API. | No | integer |
What's next
- See the Open Banking API: Create a draft payment for full details on draft payments.
- To check important considerations when you build your draft payments integration, see Tutorials: Work with draft payments.
- To request a new endpoint that meets your business requirements, fill out this short form.