CIIFragments Studio is CII-accredited: recover up to 20% of your software development spendLearn more

API integration for Revolut Business

We build your Revolut Business connector

Your tool queries the Revolut Business API to read transactions, send transfers and reconcile cash with no bank export.

  • Senior product team
  • banking integrations in production
  • from scoping to monitoring
In short

What does the Revolut Business API provide and why connect Revolut to your software?

Revolut Business is an online business bank with currency exchange, team card and international transfer capabilities. Its API lets your application read accounts and transactions, create transfers and manage cards, turning treasury management into a function of your software rather than a manually reviewed export. You integrate it in financial management tools, multi-currency payment platforms or accounting software that needs a real-time view of balances and movements without manually logging into the Revolut portal.

Use cases

What our clients build on the Revolut API

01

Reconciliation when the money lands

TransactionCreated triggers matching on amount plus reference. No bank export ticked off at month end.

02

Paying suppliers from the product

The application prepares, a human approves the draft in Revolut. The software cannot empty an account on a loop bug.

03

Payout with no IBAN on file

A payout link for an indemnity, a fee, a refund. PayoutLinkStateChanged closes the file.

04

Multi-currency cash

Accounts, transactions and FX exposed in the director portal. The rate is no longer a frozen cell in a spreadsheet.

For you

What it changes in your cash position

Engineering in service of a measurable outcome: up-to-date cash, framed transfers, less manual export.

You see the money when it arrives

The invoice is matched on TransactionCreated, not on a statement 15 days later. Reminders stop on the day of the credit.

A transfer stays a human decision

Draft in the application, approval in Revolut. That is the boundary a director wants to see on an outbound payment.

Fewer double transfers

request_id derived from the invoice, plus a lock beyond Revolut's 2-week memory. A timeout does not pay twice.

A shorter close

Entries arrive already attached. The accountant stops rebuilding flows from a CSV.

Method

How we ship your Revolut connector

01

Scoping

Business API, not Merchant. Read or transfer, PAY scope, IP allowlist. We drop READ_SENSITIVE_CARD_DATA if the product does not need it.

02

Development

JWT client, access_token refreshed before 40 minutes, business request_id, v1.{timestamp}.{body} signature with a 5-minute window.

03

Acceptance testing

Official signature vector, sandbox simulations (complete, revert, decline, fail), 400 on duplicate request_id treated as success.

04

Monitoring

Alerts on unprocessed events, a transfer log, a health dashboard. The failed-webhook endpoint is the safety net, not an option.

What the API allows

What the Revolut Business API allows

Accounts and transactions
Read accounts and history. Time pagination (from, to, count up to 1,000), not a cursor: equal timestamps have to be handled.
Transfers and drafts
POST /pay with request_id. Drafts materialise human approval: the application prepares, an authorised user approves in Revolut.
Payout links
Pay someone whose IBAN you do not have. PayoutLinkCreated and PayoutLinkStateChanged follow actual collection.
v2 webhooks
Four types only, 10 webhooks maximum. TransactionCreated and TransactionStateChanged cover reconciliation, the rest is swept.
Glossary

The vocabulary of the Revolut Business API

private_key_jwt
Assertion signed with your private key. iss is the redirect URI domain, without https://. sub is the client_id, aud is https://revolut.com. The token exchange body is form-encoded, not JSON.
request_id
Idempotency identifier in the POST /pay body, not a header. Remembered for 2 weeks. A duplicate returns 400 Bad Request, not 409.
Revolut-Signature
v1=<hex>, HMAC-SHA256 of v1.{Revolut-Request-Timestamp}.{raw body}. 5-minute window. During rotation, several signatures, one match is enough.
READ_SENSITIVE_CARD_DATA
Card scope. Without an IP allowlist, you lose access to every Business API endpoint, not only cards. If the product does not need it, do not request it.
40-minute access_token
A 401 mid-job is a nominal case. The refresh_token, per the documentation, does not expire: actual consent duration is confirmed at scoping.
Business vs Merchant
Business: b2b.revolut.com, JWT, TransactionCreated. Merchant: merchant.revolut.com, collection, ORDER_COMPLETED. Same developer domain, two products.
Good to know

The real constraints of the Revolut Business API

01

This is not the Merchant API

Hosts, scopes and events differ. Mixing them up is the most common scoping error: you collect on one side, you read the account on the other. Modules, secrets and webhook routes stay separate.

02

Idempotency limited to 2 weeks

Replaying a request_id after 2 weeks can create a second transfer. A 400 on a duplicate is an idempotent success, not a validation error. The mapping is persisted on the response: request_id search is capped at 14 days.

03

The card scope can cut everything

READ_SENSITIVE_CARD_DATA without an IP allowlist blocks access to the whole Business API. It is a configuration trap, not a refusal limited to one endpoint.

04

Four events, unpublished rate limits

No balance, card or counterparty event: the rest is swept. No rate limit is published. The failed-webhook endpoint is the safety net, retry policy not being reliably documented.

Two Revolut products

Business API or Merchant API?

Two products, one developer domain. The right one depends on whether you read an account or you take payment.

CriterionBusiness APIThe accountMerchant APICollection
Hostb2b.revolut.com/api/1.0merchant.revolut.com
AuthenticationJWT assertion, READ WRITE PAY scopesMerchant key, version header
EventsTransactionCreated, PayoutLink*ORDER_COMPLETED, DISPUTE_WON
Outbound moneyPOST /pay, drafts, linksRefund of an order
Idempotencyrequest_id, 2 weeks, 400 on duplicateSpecific to collection
Webhook signaturev1.{timestamp}.{body}, HMACSame mechanism, different events
The right caseCash, transfers, reconciliationCheckout, subscription, card dispute

The two combine on one product, with distinct modules. This page covers the Business API. Online collection is scoped separately.

Our expertise

What we measure on a Revolut integration

15 d
first Revolut flow in production
100 %
of webhooks verified against the official vector
< 1 min
latency between the transaction and your app
4
senior developers on the project
Compare

The other banking APIs

If your accounts are not all at Revolut, these options are worth discussing during scoping.

We combine Revolut with

The stack that surrounds Revolut Business on our projects.

  • Pennylane
  • Qonto
  • Stripe
  • PostgreSQL
  • Node.js
FAQ

Revolut integration: your questions

Three steps. First the key pair, the public certificate in the Revolut Business portal, and a client that signs a JWT assertion (iss = domain without scheme, token exchange as form body). Then a connector that refreshes the access_token before 40 minutes, reads transactions in time windows, and sets a request_id derived from the invoice on every POST /pay. Finally v2 webhooks: HMAC of v1.{timestamp}.{raw body}, reject outside the 5-minute window, several signatures during rotation. The sensitive part is not the call, it is not mixing up Business and Merchant, and persisting the request_id mapping on the response.

A first useful flow, typically syncing transactions into a dashboard, ships in two to three weeks. A chain with transfers, drafts, payout links and reconciliation is closer to six to eight weeks. Scoping first settles Business API or Merchant API, and drops READ_SENSITIVE_CARD_DATA if card details are not needed, because that scope without an IP allowlist can cut access to the whole API. We give a firm estimate before we start.

The Business API lives on b2b.revolut.com/api/1.0, authenticates with a JWT assertion, and talks about TransactionCreated, transfers and accounts. The Merchant API lives on merchant.revolut.com, takes online payment, and talks about ORDER_COMPLETED, ORDER_AUTHORISED, DISPUTE_WON. The webhook signing mechanism is similar, which misleads. This page covers the account. If you collect from customers online, that is another connector, other secrets, other routes.

Derive request_id from intent (transfer:{supplier_invoice_id}), never a UUID regenerated on every attempt. Persist the request_id plus transaction id pair on the response, because GET /transactions filtered by request_id only accepts 14 days. Treat a 400 duplicate request_id as success: re-read the transaction in the window, continue. Beyond 2 weeks, Revolut may create a second payment: the application lock covers that window. This is the most concrete bug on this API.

Yes. We push Revolut transactions into Pennylane with the invoice reference, and a periodic consistency check flags the gap, with no silent fix. Qonto combines when some accounts sit elsewhere: the Qonto API for those accounts, Revolut for its own, possibly PSD2 aggregation for the rest. It is not an exclusive choice, it is an account map drawn at scoping. A bank entry is not repaired behind the accountant's back.

A Revolut integration project?

Let's talk. 30 minutes to scope the account and transfers, check what the API actually allows and tell you honestly what is feasible.

Discuss my Revolut project
Discuss my Revolut project