Sandbox
Help

Webhooks for subscriptions

Receive real-time notifications when subscription states change - and know which changes to poll for instead.

Webhook events push subscription state changes to your server as they happen, so you can provision access, trigger dunning flows, and keep your records in sync without polling.

The setup flow - registering the webhook URL, subscribing to events, verifying payload signatures - is shared with the rest of the Merchant API. The rest of this guide covers what's specific to subscriptions.

How it works

Revolut sends each event as an HTTP POST request to the url you registered with Create a webhook. The following events are sent for subscriptions:

EventFires whenTypical reaction
SUBSCRIPTION_INITIATEDThe subscription is createdMark the customer's account as provisioning - access starts once the subscription activates
SUBSCRIPTION_FINISHEDThe subscription completes its last cycle naturallyEnd access gracefully - the customer completed their commitment
SUBSCRIPTION_CANCELLEDThe subscription is cancelled - by you or the customerStop provisioning immediately, record the cancellation
SUBSCRIPTION_OVERDUEA renewal or settlement payment failsTrigger your dunning flow - notify the customer, consider restricting access

The payload is minimal by design - the Webhook event API reference documents the exact shape you'll receive:

POST /your-webhook-endpoint HTTP/1.1
Host: your-server.example.com
Content-Type: application/json
Revolut-Request-Timestamp: 1721050064
Revolut-Signature: v1=4fce70bda66b2e713be09fbb7ab1b31b0c8976ea4eeb01b2

{
  "event": "SUBSCRIPTION_OVERDUE",
  "subscription_id": "550e8400-e29b-41d4-a716-446655440000",
  "external_reference": "cus_8f3a91"
}
ParameterDescription
eventThe event type - one of the subscription events above.
subscription_idThe affected subscription - use it to Retrieve a subscription for the full current state.
external_referenceYour identifier, echoed from creation. Optional - match it to your records instead of the UUID if you prefer.
Payloads are pointers, not state snapshots

The payload tells you that something changed, not the full subscription state.

Always retrieve the subscription before acting on an event - the state may have moved on since the event was generated.

Before you begin

Before you start, make sure you have the following:

Handle subscription events

Respond and retry

  • Acknowledge fast - respond with any 200-399 code within the timeout (204 is recommended) and do heavy processing off the request thread.
  • Retries - if delivery times out or your endpoint responds 4XX, Revolut retries the event 3 more times, each with a 10-minute delay. Make your handler idempotent - the same event can arrive more than once.
  • Ordering isn't guaranteed - handle events based on the subscription's current retrieved state rather than assuming events arrive in lifecycle order.
  • IP allowlisting - events originate from these addresses:
EnvironmentWebhook IP addresses
Production35.246.21.235, 34.89.70.170
Sandbox35.242.130.242, 35.242.162.241

Poll what webhooks don't tell you

Subscription webhooks cover a small set of state changes. Several lifecycle moments emit no event - track those by polling Retrieve a subscription or the cycle list:

ChangeEventHow to track
Subscription createdSUBSCRIPTION_INITIATEDWebhook
Activation - first payment collected or payment method attachedNoneRetrieve the subscription, check state: "active"
Plan change scheduled or appliedNoneRetrieve the subscription
Cycle created or completedNoneRetrieve a subscription cycle list
Usage settlement chargedNoneRetrieve the cycle - the post_billing_order_id appears after the cutoff
Renewal or settlement payment failedSUBSCRIPTION_OVERDUEWebhook - see Failed payments and retries
CancellationSUBSCRIPTION_CANCELLEDWebhook
Natural completionSUBSCRIPTION_FINISHEDWebhook

For activation specifically, a practical pattern is to poll the subscription after the customer completes the setup order - there's no activation event to wait for.

Implementation checklist

Confirm your webhook integration handles subscription events correctly:

  • Webhook registered and subscribed to the SUBSCRIPTION_* events - see Use webhooks
  • Every payload's signature is verified before processing - see Verify the payload signature
  • Handler responds 200-399 quickly and processes asynchronously
  • Handler is idempotent - the 3 retries with 10-minute delays can deliver duplicates
  • Events are matched to your records via external_reference or subscription_id
  • SUBSCRIPTION_OVERDUE triggers your dunning flow; SUBSCRIPTION_CANCELLED and SUBSCRIPTION_FINISHED stop provisioning
  • Activation, plan changes, and cycle completions are covered by polling - no events exist for them

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 usage-based subscription
Meter usage, report it via the API, and settle charges at cycle end
Build a subscription with trials and introductory pricing
Offer free trials and promotional pricing phases
Rate this page