Sandbox
Help

Build a usage-based subscription model

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.

  1. Create a usage-based plan - model each meter as a usage item with an aggregation method and a price - per-unit or a tier ladder - sharing its phase with a flat platform fee.
  2. Subscribe the customer - create the subscription, which starts in pending state until the first payment is collected.
  3. 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.
  4. 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:

MethodChargesBusiness example
sumThe total of all reported values in the cycleAPI calls, data transferred, messages sent
latestThe most recently reported valueActive seats - see Per-seat subscription
maxThe highest reported valuePeak 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:

API usage plan Pay-as-you-go variation Phase 1 - monthly cycle Subscription items Volume-tiers variation Phase 1 - monthly cycle Subscription items Platform feeflat item - £29.00 API callsusage item - sum x £0.10 per call Platform feeflat item - £29.00 API callsusage item - sum x tier ladderfirst 1,000 calls free

Before you begin

Before you start, make sure you have the following:


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:

Request example
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
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
ParameterDescription
nameThe plan name - what your customers subscribe to
variationsPurchasing options for the plan - here, two pricing styles for the same meter
phasesSequential pricing stages within a variation, executed in ordinal order
ordinalExecution order of the phase, starting at 1
cycle_durationLength of the billing cycle, as an ISO 8601 duration, e.g., P1M
subscription_itemsThe charges on the phase - here, a platform fee plus a metered item per variation
subscription_items[].typeflat bills a fixed amount every cycle; usage bills consumption you report
subscription_items[].quantityUnits billed on a flat item - the platform fee bills amount * quantity, here 1 x £29.00
subscription_items[].unitWhat the item bills - a free-form label, call for the meter here
subscription_items[].package_sizeUnits grouped into one billable package - optional, defaults to 1; leave it at 1 to price every unit
subscription_items[].codeMerchant-defined identifier for a usage item - unique within the phase; you supply it when reporting usage
subscription_items[].usage_aggregation_methodHow reported values become the charge - sum adds them all up at cycle end
subscription_items[].amountPer-unit price on a usage item, in minor units - 10 is £0.10 per call. Mutually exclusive with tiers
subscription_items[].currencyCharge currency, as an ISO 4217 code
subscription_items[].tiersGraduated pricing ladder - mutually exclusive with amount
subscription_items[].tiers[].upper_quantity_thresholdExclusive upper bound of the tier - omit it or set null for an unlimited final tier
subscription_items[].tiers[].amountPer-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:

subscription_item PK id uuid usage type string name string what the item meters - call unit string merchant-defined - targets usage reports code string sum | latest | max usage_aggregation_method string per-unit price - exclusive with tiers amount integer currency string units per billable package - optional, defaults to 1 package_size number usage items only - exclusive with amount tiers array tier exclusive upper bound - omitted or null means unlimited upper_quantity_threshold number per-unit price within the tier's range amount integer tiers

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 styleUsage charge for a 4,500-call cycle
Pay-as-you-go4,500 * £0.10 = £450.00
Volume tiersFirst 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:

Request example
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"
}
ParameterDescription
plan_variation_idThe variation the customer subscribes to - the pay-as-you-go variation id you saved in step 1
customer_idThe customer to bill
external_referenceOptional: 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_urlOptional: where the customer lands after completing payment on the hosted checkout page
The first payment precedes any usage

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:

Request example
GET /api/orders/{order_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
ParameterDescription
order_idThe 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:

Payment widget
Embed the payment flow in your site: you build the customer experience, and the customer never leaves your page
Hosted Checkout Page
Redirect to a payment page Revolut hosts for you: no payment UI to build, and Revolut handles the payment experience

Choose the approach that fits your integration:

Keep the customer on your site with an embedded payment widget or a card-not-present method:

  1. Build your payment acceptance solution on your frontend with the widget or payment method of your choice, initialising it with the token from the response.
  2. Configure it to save the customer's payment method for merchant-initiated recurring transactions.
  3. 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:

Request example
GET /api/subscriptions/{subscription_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
ParameterDescription
subscription_idThe 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:

Request example
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"
  }
}
ParameterDescription
subscription_idThe ID of the subscription being metered
subscription_item_codeThe code you gave the usage item in step 1 - here api_calls
quantityThe consumed amount - for sum and max items report increments or event counts; for latest items report the current total
usage_dateWhen the consumption happened - Revolut resolves the billing cycle from this date
metadataOptional: 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 windowWhat happens
Active cycleusage_date falls within the current cycle - the record counts towards its settlement
Past-cycle correctionusage_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 cycleusage_date falls within the upcoming cycle - Revolut holds the record in a pending cycle until it starts
Any other dateRejected - 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 codeDescription
subscription_item_code_not_foundThe item code doesn't exist on the subscription's current plan phase
subscription_usage_lockedThe cycle is past its usage_cutoff_date - records can no longer be modified
subscription_usage_future_cycle_limit_exceededThe usage_date is too far in the future
subscription_usage_before_subscription_startThe usage_date precedes the subscription's start date
subscription_usage_after_last_cycleThe usage_date falls after the last cycle - the subscription is finished
subscription_finishedUsage 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:

Request example
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
}
ParameterDescription
usage_idThe ID of the record you saved from the report response
quantityThe 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:

Request example
DELETE /api/subscription-usages/{usage_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17
ParameterDescription
usage_idThe 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:

Request example
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
ParameterDescription
subscription_idFilter to one subscription - here, the walkthrough subscription's id
subscription_cycle_idFilter to one billing cycle - here, the current cycle's id
from_usage_date / to_usage_dateOptional: 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:

Subscription f0eb534f - state: active Cycle 264f26a7 - current, state: active Cycle 6f68ad11 - state: finished Usage reports - settle after the cutoff Setup order 95061a11 pre-billed the £29.00 platform fee Post-billing order 710ed088 charged £479.00: cycle 1 usage + cycle 2 platform fee

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:

Request example
GET /api/subscriptions/{subscription_id}/cycles HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17

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

ScenarioPost-billing order behaviour
Ongoing subscriptionThe 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 cycleA standalone finishing order charges all the cycle's usage
Subscription ended with unpaid cyclesThe 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:

Request example
GET /api/subscriptions/{subscription_id}/cycles/{cycle_id} HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17

Cancel 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:

Request example
POST /api/subscriptions/{subscription_id}/cancel HTTP/1.1
Host: merchant.revolut.com
Authorization: Bearer sk_abcdef12347890_...
Revolut-Api-Version: 2026-08-17

The 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 amount or tiers (never both) - and saved the variation id the 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-Key on every request and target the correct subscription_item_code
  • Corrections and deletions land before the cycle's usage_cutoff_date - subscription_usage_locked errors 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_id charge against your own metering
  • Cancelled a test subscription - 204 response, no new cycles created, SUBSCRIPTION_CANCELLED event 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.


What's next

Build a fixed-rate subscription
Charge a fixed recurring amount - the simplest subscription flow
Build a per-seat subscription
Bill per seat, with a stable or changing seat count
Build a subscription with trials and introductory pricing
Offer free trials and promotional pricing phases
Track subscriptions with webhooks
Receive real-time events when subscription states change
Rate this page