Meter what your customers consume, report it through the API, and bill for actual usage at cycle end.
Usage-based pricing bills for consumption rather than a flat fee: API calls, gigabytes stored, messages sent. Your integration meters the consumption, reports it to Revolut as it happens, and we aggregate the reports and charges the saved payment method after each cycle closes.
Unlike per-seat pricing, where a latest-aggregated usage item tracks a single gauge, a metered plan typically accumulates many small reports per cycle - and both the pricing and the reporting need a bit more configuration.
In this guide, you sell an API usage plan - a £29.00 monthly platform fee plus metered API calls, billed after each cycle closes. Customers pick how the calls are priced: £0.10 per call, or a tier ladder that starts free and gets cheaper as volume grows.
The example demonstrates how to model metered pricing on a single plan: a flat item carries the platform fee, and each variation prices the same api_calls meter differently - per-unit on one, graduated on the other. Map your own pricing the same way - every consumption metric becomes a usage item, and each pricing style becomes a variation.
How it works
This guide walks the full flow: all API calls run between your backend and the Merchant API, and only step 3 - collecting the first payment - reaches the customer's browser.
- Create a usage-based plan - model each meter as a
usageitem with an aggregation method and a price - per-unit or a tier ladder - sharing its phase with a flat platform fee. - Subscribe the customer - create the subscription, which starts in
pendingstate until the first payment is collected. - Collect the first payment - retrieve the setup order, hand the customer a payment widget or Revolut's Hosted Checkout Page, and confirm the subscription is
active. - Report and settle usage - report consumption through the cycle, correct records while it's open, and Revolut charges the aggregated total after the cycle closes.
The aggregation method on each usage item decides how reports become a charge:
| Method | Charges | Business example |
|---|---|---|
sum | The total of all reported values in the cycle | API calls, data transferred, messages sent |
latest | The most recently reported value | Active seats - see Per-seat subscription |
max | The highest reported value | Peak concurrent connections |
Because consumption accrues through the cycle, the charge lands at the end of it: the cycle closes at its end_date, reports and corrections stay open for another 12 hours - the usage_cutoff_date - and once it passes, Revolut aggregates each item's records, applies the per-unit price or tier ladder, and charges the saved payment method through a post-billing order.
The API usage plan you'll build in this guide looks like this:
Before you begin
Before you start, make sure you have the following:
- You've completed Get started with the Subscriptions API - it introduces the universal subscription flow this guide builds on
- An existing customer - see Create a customer
- A way to meter consumption on your side - the API records what you report, it doesn't measure anything itself
- Familiarity with the core subscription concepts - see Subscription plans and Subscription lifecycle
Implement usage-based subscription
The steps below follow the API usage plan narrative: you create the plan with its two pricing styles, subscribe a customer to the pay-as-you-go variation, collect the first payment, and confirm the subscription is active.
1. Create plan for usage-based pricing
Your API usage plan sells the same meter two ways. Each variation is a single phase, and the charges live on items in the phase: a flat item carries the £29.00 platform fee, and a usage item prices the api_calls meter.
The usage item differs per variation - £0.10 per call on pay-as-you-go, a graduated ladder on volume tiers. Every usage item needs an aggregation method and a price, and the per-unit amount and tiers are mutually exclusive - the schema rejects both.
For the plan, variation, and phase hierarchy these items sit in, see Get started with the Subscriptions API.
Call Create a subscription plan, turning your metered pricing into a plan your customers can subscribe to:
POST /api/subscription-plans HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
Content-Type: application/json
{
"name": "API usage plan",
"variations": [
{
"phases": [
{
"ordinal": 1,
"cycle_duration": "P1M",
"subscription_items": [
{
"type": "flat",
"name": "Platform fee",
"unit": "subscription",
"quantity": 1,
"amount": 2900,
"currency": "GBP"
},
{
"type": "usage",
"name": "API calls",
"unit": "call",
"code": "api_calls",
"usage_aggregation_method": "sum",
"amount": 10,
"currency": "GBP"
}
]
}
]
},
{
"phases": [
{
"ordinal": 1,
"cycle_duration": "P1M",
"subscription_items": [
{
"type": "flat",
"name": "Platform fee",
"unit": "subscription",
"quantity": 1,
"amount": 2900,
"currency": "GBP"
},
{
"type": "usage",
"name": "API calls",
"unit": "call",
"code": "api_calls",
"usage_aggregation_method": "sum",
"currency": "GBP",
"tiers": [
{
"upper_quantity_threshold": 1000,
"amount": 0
},
{
"upper_quantity_threshold": 10000,
"amount": 10
},
{
"amount": 5
}
]
}
]
}
]
}
]
}| Parameter | Description |
|---|---|
name | The plan name - what your customers subscribe to |
variations | Purchasing options for the plan - here, two pricing styles for the same meter |
phases | Sequential pricing stages within a variation, executed in ordinal order |
ordinal | Execution order of the phase, starting at 1 |
cycle_duration | Length of the billing cycle, as an ISO 8601 duration, e.g., P1M |
subscription_items | The charges on the phase - here, a platform fee plus a metered item per variation |
subscription_items[].type | flat bills a fixed amount every cycle; usage bills consumption you report |
subscription_items[].quantity | Units billed on a flat item - the platform fee bills amount * quantity, here 1 x £29.00 |
subscription_items[].unit | What the item bills - a free-form label, call for the meter here |
subscription_items[].package_size | Units grouped into one billable package - optional, defaults to 1; leave it at 1 to price every unit |
subscription_items[].code | Merchant-defined identifier for a usage item - unique within the phase; you supply it when reporting usage |
subscription_items[].usage_aggregation_method | How reported values become the charge - sum adds them all up at cycle end |
subscription_items[].amount | Per-unit price on a usage item, in minor units - 10 is £0.10 per call. Mutually exclusive with tiers |
subscription_items[].currency | Charge currency, as an ISO 4217 code |
subscription_items[].tiers | Graduated pricing ladder - mutually exclusive with amount |
subscription_items[].tiers[].upper_quantity_threshold | Exclusive upper bound of the tier - omit it or set null for an unlimited final tier |
subscription_items[].tiers[].amount | Per-unit price within the tier's range, in minor units |
In terms of the API's fields and types, a usage item and its optional tier ladder look like this - the delta this model adds to the plan structure:
The usage flavour carries fields a flat item never has - code, usage_aggregation_method, and tiers - while quantity exists only on flat items.
How the same meter prices under the two styles - say the customer makes 4,500 calls in a cycle:
| Pricing style | Usage charge for a 4,500-call cycle |
|---|---|
| Pay-as-you-go | 4,500 * £0.10 = £450.00 |
| Volume tiers | First 1,000 calls free, next 3,500 * £0.10 = £350.00 |
Both sit on top of the cycle's £29.00 platform fee.
A phase can carry several usage items - api_calls and storage_gb, say - each with its own aggregation method and price. The code you set on each item is what targets the right meter when you report usage.
2. Subscribe customer
When a customer wants to subscribe to your API usage plan, you create a subscription. The subscription connects the customer - and their consent to use their payment details for recurring charges - to the variation they chose: the pay-as-you-go variation in this guide.
Subscription creation is the same for every pricing model - the pricing lives entirely in the plan you built. Once created, the subscription starts in pending state - it becomes active once the customer completes the first payment.
Call Create a subscription to connect the customer to the pay-as-you-go variation. Send an idempotency key, so you can safely retry the request without creating duplicate subscriptions:
POST /api/subscriptions HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
Content-Type: application/json
Idempotency-Key: f5e4ba66-6465-4015-b3b4-966598ee41a5
{
"plan_variation_id": "aedec485-0e72-49ed-ad5b-ea9e722f9cec",
"customer_id": "650e8400-e29b-41d4-a716-446655440001",
"external_reference": "api_7c5d21",
"setup_order_redirect_url": "https://example.com/subscription/complete"
}| Parameter | Description |
|---|---|
plan_variation_id | The variation the customer subscribes to - the pay-as-you-go variation id you saved in step 1 |
customer_id | The customer to bill |
external_reference | Optional: your own identifier for the subscription, e.g., the customer's ID in your system - returned in responses and echoed in webhook events |
setup_order_redirect_url | Optional: where the customer lands after completing payment on the hosted checkout page |
The setup order collects the first payment before any usage is reported - usage items contribute nothing until your reports land in the cycle.
On this plan, the first charge is the £29.00 platform fee. Make sure your metering starts reporting as soon as the subscription is active, so the first cycle settles with the real consumption.
3. Collect first payment
In the previous step you created the subscription. It is in pending state, and becomes active once the customer completes the first payment. That payment is collected through a setup order - an order that exists to start a subscription.
Revolut creates the setup order in the background when you create the subscription: it takes the first charge - £29.00 for the platform fee - and saves the customer's payment method for the recurring cycles that follow. You already saved its setup_order_id.
3.1 Retrieve setup order
Retrieve the setup order with Retrieve an order, passing the setup_order_id you saved in step 2 as the order_id:
GET /api/orders/{order_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17| Parameter | Description |
|---|---|
order_id | The ID of the setup order you saved in step 2 |
Like the calls in the previous steps, this is a server-side operation - it happens between your backend and the Merchant API.
3.2 Build your payment acceptance solution
Collecting the payment reaches beyond your backend: the customer pays in their browser or mobile app, so this part of the flow has client-side work alongside your server. The goal is to hand the customer a way to pay the first charge and save their payment method. Revolut supports two approaches, and both do this for you:
Choose the approach that fits your integration:
Keep the customer on your site with an embedded payment widget or a card-not-present method:
- Build your payment acceptance solution on your frontend with the widget or payment method of your choice, initialising it with the
tokenfrom the response. - Configure it to save the customer's payment method for merchant-initiated recurring transactions.
- The customer completes payment without leaving your site, and Revolut saves their payment method.
This step assumes you're familiar with a standard payment method integration, see Introduction to online payments.
4. Verify subscription state
When the customer completes the first payment in step 3, the subscription becomes active. There's no webhook event for activation, so retrieve the subscription to confirm it's live.
Check the subscription details with Retrieve a subscription, passing the subscription id from step 2 in the request path:
GET /api/subscriptions/{subscription_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17| Parameter | Description |
|---|---|
subscription_id | The ID of the subscription you saved in step 2 |
Once the subscription is active, your usage-based subscription is live. From here, the work splits between you and Revolut.
We handle the billing: charging the customer's saved payment method the platform fee for each cycle and the aggregated usage after each cycle closes, and retrying failed payments automatically - see Failed payments and retries.
Your part is the metering: report consumption through every cycle, because an unreported cycle still bills the platform fee but no usage. How to report is covered in Report usage.
You've completed the usage-based subscription flow! The API usage plan is live with both pricing styles, and Revolut bills the customer automatically from here.
Next, operate the subscription: report consumption through each cycle, correct or delete records while cycles are open, audit the usage records and billing cycles as they accrue, and cancel the subscription when the customer leaves.
Operate usage-based subscription
With the subscription active, Revolut bills the saved payment method automatically - the platform fee at each cycle boundary, the aggregated usage after each cycle closes.
What remains yours while it runs is the metering: report consumption through every cycle, keep the records accurate while cycles are open, audit the usage records and billing cycles - for reconciliation, billing history, and entitlement checks - and cancel the subscription when the customer leaves.
Report usage
Reporting usage is a recurring operation: meter consumption on your side, then send records to Revolut as it happens - one per consumption event, or batched totals if you report in intervals. The example below follows the guide's subscription in its second cycle, reporting a day's batch of 1,200 API calls.
The Idempotency-Key header is required for this endpoint - it prevents retries from creating duplicate usage records.
Call Create a subscription usage, passing the subscription id and the subscription_item_code you configured in step 1, to tell Revolut what was consumed:
POST /api/subscription-usages HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
Content-Type: application/json
Idempotency-Key: e991efb1-8e92-40a6-a1e9-e8f6ad49b0ad
{
"subscription_id": "f0eb534f-e3e9-42a5-8e1f-3902e8ef141f",
"subscription_item_code": "api_calls",
"quantity": 1200,
"usage_date": "2026-03-05T14:22:00Z",
"metadata": {
"user_id": "12345",
"api_version": "v2"
}
}| Parameter | Description |
|---|---|
subscription_id | The ID of the subscription being metered |
subscription_item_code | The code you gave the usage item in step 1 - here api_calls |
quantity | The consumed amount - for sum and max items report increments or event counts; for latest items report the current total |
usage_date | When the consumption happened - Revolut resolves the billing cycle from this date |
metadata | Optional: your own data on the record - useful for reconciliation and audit trails |
Where reports land
Revolut resolves every usage report to a billing cycle based on the usage_date. Where that date falls decides which cycle the record settles:
| Reporting window | What happens |
|---|---|
| Active cycle | usage_date falls within the current cycle - the record counts towards its settlement |
| Past-cycle correction | usage_date falls within a recently ended cycle, and the request arrives before that cycle's usage_cutoff_date - 12 hours after end_date by default |
| Next upcoming cycle | usage_date falls within the upcoming cycle - Revolut holds the record in a pending cycle until it starts |
| Any other date | Rejected - before the subscription's start date, after the last cycle, or too far in the future |
Handle reporting errors
When a report falls outside the accepted windows - or targets an item the plan doesn't carry - the API rejects it with a typed error code. Handle these in your integration:
| Error code | Description |
|---|---|
subscription_item_code_not_found | The item code doesn't exist on the subscription's current plan phase |
subscription_usage_locked | The cycle is past its usage_cutoff_date - records can no longer be modified |
subscription_usage_future_cycle_limit_exceeded | The usage_date is too far in the future |
subscription_usage_before_subscription_start | The usage_date precedes the subscription's start date |
subscription_usage_after_last_cycle | The usage_date falls after the last cycle - the subscription is finished |
subscription_finished | Usage can't be added to a finished subscription |
Update usage records
Reports can be wrong - double-counted batches, late-arriving events, meter drift. Records stay editable while the cycle is open. After the usage_cutoff_date, the cycle locks and modifications return 422 subscription_usage_locked.
Correct a record with Update a subscription usage to keep the cycle's bill accurate - it updates the quantity or metadata of a single record. The {usage_id} in the request path is the record's id from the Report usage response.
If you didn't save the usage record's id, see Retrieve usage records on how to find the record to be corrected.
The guide's example batch double-counted 50 calls, so correct the day's report from 1,200 to 1,150:
PATCH /api/subscription-usages/{usage_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
Content-Type: application/json
{
"quantity": 1150
}| Parameter | Description |
|---|---|
usage_id | The ID of the record you saved from the report response |
quantity | The corrected amount - replaces the recorded value |
Delete usage records
Some records shouldn't exist at all - a duplicate report, a metering glitch, usage logged for a test run. Where an update corrects a record's quantity, deletion removes the record entirely, so it never reaches the cycle's settlement.
Call Delete a subscription usage to remove the wrong record from the cycle's settlement, passing the record's id in the path:
DELETE /api/subscription-usages/{usage_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17| Parameter | Description |
|---|---|
usage_id | The ID of the record being removed - the same id you'd use to update |
The same cycle lock applies: after the usage_cutoff_date, deletions return 422 subscription_usage_locked.
If you need the record's history, correct its quantity instead - deletion leaves nothing behind.
Retrieve usage records
Every report you send becomes a stored record - its quantity, usage_date, cycle, and metadata - so a complete metering history builds up as the subscription runs.
Retrieving that history powers the audit side of your billing: check what a cycle will bill before its cutoff, reconcile settled cycles against your own metering, build customer-facing usage views, and find records to update when you didn't save their ids.
The list call gives you that history in one request. Call Retrieve a subscription usage list, filtering to the subscription and the cycle you want to audit - here, our current guide's cycle 2 before its cutoff:
GET /api/subscription-usages?subscription_id={subscription_id}&subscription_cycle_id={subscription_cycle_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17| Parameter | Description |
|---|---|
subscription_id | Filter to one subscription - here, the walkthrough subscription's id |
subscription_cycle_id | Filter to one billing cycle - here, the current cycle's id |
from_usage_date / to_usage_date | Optional: filter by when the consumption happened - records come back ordered by usage_date |
The response shows two usage records so far, on the subscription's current billing cycle: 900 calls on 27 February, and the corrected 1,150 from 5 March - 2,050 calls on the meter, £205.00 of usage at the pay-as-you-go price.
To retrieve a single record instead, call Retrieve a subscription usage with the record's id in the path - it returns the same object as the report response.
Retrieve billing cycles
While the subscription is active, Revolut creates a billing cycle for every billing period - one a month on the walkthrough variation. Cycles with usage items carry two extra fields: usage_cutoff_date, the deadline for reports and corrections, and post_billing_order_id, the order that settles the cycle's usage once the cutoff passes.
The subscription's runtime resources look like this:
The examples below cover two common use cases - a billing-history view and an entitlement check - but they're just a starting point. Explore how the same calls can serve your own business cases: the cycle data can power reconciliation, customer-facing billing pages, dunning workflows, and anything else your product needs.
Retrieve cycle list
The cycle list gives you the subscription's billing history in one call - every cycle so far, its state, and the orders that charged it. Use it for reconciliation and billing-history views, and to discover the current cycle's id if you don't have it saved.
Call Retrieve a subscription cycle list, passing the id of the subscription you created in step 2 as the subscription_id:
GET /api/subscriptions/{subscription_id}/cycles HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17When a cycle closes, settlement runs after its usage_cutoff_date - 12 hours after end_date by default. Revolut aggregates each usage item's records with its usage_aggregation_method, applies the per-unit price or tier ladder, and charges the saved payment method through a post-billing order. The walkthrough's first cycle reported 4,500 calls: the post-billing order charged £450.00 of usage together with the next cycle's £29.00 platform fee - £479.00 in total - and also became cycle 2's order_id.
| Scenario | Post-billing order behaviour |
|---|---|
| Ongoing subscription | The order combines usage settlement for the closing cycle with pre-billing for the next - it also acts as the next cycle's order_id |
| Last cycle | A standalone finishing order charges all the cycle's usage |
| Subscription ended with unpaid cycles | The finishing order consolidates all outstanding usage charges, including failed ones from earlier cycles |
If a settlement charge fails, the subscription moves to overdue and Revolut retries it automatically - see Failed payments and retries. Reconcile each settled cycle by matching its post_billing_order_id against your own metering.
Run an entitlement check
A common pattern is gating platform access on the subscription's state: each time the customer logs in, retrieve the current cycle - its id is the current_cycle_id from the subscription response - and grant access while its state is active.
The check runs on every login, so keep it lightweight: retrieve just the current cycle instead of pulling the whole list. Call Retrieve a subscription cycle, passing the current cycle's id as the cycle_id:
GET /api/subscriptions/{subscription_id}/cycles/{cycle_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17Cancel subscription
When the customer wants to leave, cancel the subscription - Revolut stops billing and cancels any pending orders. You can cancel in any state except cancelled or finished.
Call Cancel a subscription, passing the id of the subscription you created in step 2 as the subscription_id:
POST /api/subscriptions/{subscription_id}/cancel HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17The subscription moves to cancelled - a final state: it can't be reactivated, so if the customer returns, create a new subscription for them. A SUBSCRIPTION_CANCELLED webhook event is sent whether the cancellation came from you or the customer - see Subscription states and Track subscriptions with webhooks.
If you run the entitlement check, this is where it stops granting access: end access immediately, or - if you let customers finish what they paid for - stop at the current cycle's end_date. Cancelling stops future charges only - it doesn't refund completed cycles.
Implementation checklist
Confirm your usage-based integration works end to end. Run the checks in the Sandbox environment first - set the base URL of your API calls to sandbox-merchant.revolut.com - then repeat them in production before going live:
- Created a plan with usage items - each with an aggregation method and either a per-unit
amountortiers(never both) - and saved the variationidthe customer subscribes to - Subscribed a customer, collected the first payment - the platform fee upfront - and confirmed the subscription is
active - Usage reports send an
Idempotency-Keyon every request and target the correctsubscription_item_code - Corrections and deletions land before the cycle's
usage_cutoff_date-subscription_usage_lockederrors are handled - Audited a cycle's usage records before its cutoff - the list call, filtered by subscription and cycle, reconciles the totals against your own metering
- Retrieved a settled cycle and reconciled its
post_billing_order_idcharge against your own metering - Cancelled a test subscription -
204response, no new cycles created,SUBSCRIPTION_CANCELLEDevent received
For verifying the payment solution itself - widget behaviour, test cards, webhook receipt for the order - use the implementation checklist in the payment method guide you followed.