---
api: 'Merchant API'
---

# Create a subscription

Create a new subscription for a customer using a subscription plan variation.

There are several supported flows for creating and activating subscriptions, depending on your integration needs.

:::note
The customer must already exist in the API. The `customer_id` is required for all subscription flows.
:::

<details>
<summary>

#### Flow 1: Hosted Payment Page (HPP)

</summary>

Use this flow to redirect the customer to Revolut's Hosted Payment Page to complete the first payment and save their payment method.

**Backend flow:**
1. Create a subscription with optional `setup_order_redirect_url`:

   | `setup_order_redirect_url` | Behaviour |
   | -------------------------- | --------- |
   | **Provided** | The setup order's `redirect_url` field is set to this value. |
   | **Omitted** | The setup order uses Revolut's default redirect behaviour. |

1. The subscription is created in a `pending` state with a `setup_order_id` in the response.
1. [Retrieve the order](/docs/api/merchant#retrieve-an-order) using `setup_order_id` as the `order_id` in the path to get the `checkout_url`.
1. Redirect the customer to the `checkout_url` for the Hosted Payment Page.

**Customer flow:**
1. Customer is redirected to Revolut's Hosted Payment Page.
1. Customer completes payment on the HPP, and their payment method is saved.
1. Customer redirect after payment depends on your setup:

   | `setup_order_redirect_url` | Customer redirect |
   | -------------------------- | ----------------- |
   | **Provided** | Customer is redirected to your custom URL. |
   | **Omitted** | Customer sees the default Revolut completion screen. |

**Key characteristics:**
- Customer completes payment on Revolut's hosted page
- Payment method is automatically saved for future billing cycles
- Optional custom redirect after payment
- Best for web-based integrations

</details>

<details>

<summary>

#### Flow 2: Widget or card-not-present (CNP) payment

</summary>

Use this flow when you want to embed the payment experience directly on your website using one of Revolut's payment widgets or handle card-not-present payments.

**Backend flow:**
1. Create a subscription with minimal required parameters.
1. The subscription is created in a `pending` state with a `setup_order_id` in the response.
1. [Retrieve the order](/docs/api/merchant#retrieve-an-order) using `setup_order_id` as the `order_id` in the path to get order details for your integration.
1. Integrate your payment solution (widget, SDK, or CNP method) on your frontend, ensuring it's configured to save the customer's payment method for recurring billing.

**Customer flow:**
1. Customer stays on your website/application.
1. Customer completes payment, and their payment method is saved for future billing cycles.

**Key characteristics:**
- Payment experience embedded directly in your application
- Customer never leaves your website
- Payment method is saved for future billing cycles
- Best for native mobile apps or fully custom web experiences

</details>

## Endpoint

POST `/api/subscriptions`

## Parameters

### header parameters

- `Idempotency-Key` (string, optional)
  The `Idempotency-Key` ensures that requests are processed only once, preventing multiple executions of the same operation due to retries or duplicate requests.
  
  This header is optional and can accept any unique string value the merchant uses.
  
  A recommended practice is to use a unique identifier from your system (such as the entity's ID or a request UUID) as the idempotency key. This facilitates tracking and managing requests effectively.

## Request body

### Attributes

- `plan_variation_id` (string)
    Unique identifier for the subscription plan variation.
- `customer_id` (string)
    Unique identifier for the customer.
- `external_reference` (string, optional)
    Optional external reference for the subscription.
    
    Use this field to store your own system's identifier for easy tracking and correlation.
- `setup_order_redirect_url` (string, optional)
    The URL to which the customer is redirected after completing the setup order on the Revolut Hosted Payment Page.
    
    When provided, the response will include a `setup_order_id`. Use the [Retrieve an order](/docs/api/merchant#retrieve-an-order) endpoint with this `setup_order_id` to get the `checkout_url` for redirecting the customer to the Hosted Payment Page.
    
    :::warning
    Restrictions:
    - Must be a valid URI as defined by [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986)
    - URI scheme is required and must be either `http` or `https`
    - URI host is required and cannot be `localhost` or an IP address
    - Max length: `2000`
    - Reserved or invalid characters must be percent-encoded (for example, use `%20` instead of a space)
    :::
- `trial_duration` (string, optional)
    The trial period duration for this subscription in [ISO 8601 duration format](https://en.wikipedia.org/wiki/ISO_8601#Durations) (e.g., "P14D" for 14 days).
    
    ### Override plan defaults
    
    Subscription plans can define a default trial duration. When creating a subscription, you can use this field to override the plan's default trial period:
    
    | Field value | Behaviour | Example |
    | ----------- | -------- | ------- |
    | **Not provided** | Uses the trial duration defined in the plan (if any) | Plan has `"P7D"` → subscription gets 7-day trial |
    | **Different value** | Overrides the plan's default trial duration | Plan has `"P7D"` → set to `"P30D"` for promotional offer, or `"P3D"` to reduce |
    | **`"P0D"`** | Explicitly skips the trial period | Plan has `"P7D"` → set to `"P0D"` to skip trial entirely |
    
    :::note
    Only days (`D`) are allowed. Time components such as hours, minutes, or seconds are not permitted.
    :::

## Returns

### 201

Subscription created successfully

#### Response attributes

- `id` (string)
    Unique identifier for the subscription.
- `external_reference` (string, optional)
    Optional external reference for the subscription.
    
    Use this field to store your own system's identifier for easy tracking and correlation.
- `state` (enum)
    The state of the subscription.
    
    | State | Description |
    | ----- | ----------- |
    | `pending` | The subscription has been created but is not yet active. This typically occurs when awaiting the first payment or setup completion. |
    | `active` | The subscription is currently active and billing cycles are processing normally. |
    | `overdue` | The subscription has a failed payment and is awaiting resolution. |
    | `paused` | The subscription has been temporarily paused and no billing will occur. |
    | `cancelled` | The subscription has been cancelled and will not renew. |
    | `finished` | The subscription has completed all billing cycles (for limited-duration subscriptions). |
    Possible enum values:

    - `pending`
    - `active`
    - `overdue`
    - `paused`
    - `cancelled`
    - `finished`
- `customer_id` (string)
    Unique identifier for the customer.
- `plan_id` (string)
    Unique identifier for the subscription plan.
- `plan_variation_id` (string)
    Unique identifier for the subscription plan variation.
- `payment_method_type` (enum)
    The type of payment method used for the subscription.
    
    | Type | Description |
    | ---- | ----------- |
    | `automatic` | Payments are automatically charged to the customer's saved payment method. |
    | `manual` | Payments require manual processing by the customer. |
    Possible enum values:

    - `automatic`
    - `manual`
- `payment_method_id` (string, optional)
    Unique identifier for the payment method.
- `created_at` (string)
    The date and time the subscription was created in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
- `updated_at` (string)
    The date and time the subscription was last updated in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
- `start_date` (string | null, optional)
    The date and time the subscription started in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
    
    This field is `null` until the subscription becomes active.
- `current_cycle_id` (string)
    Unique identifier for the subscription cycle.
- `trial_duration` (string, optional)
    The trial period duration for this subscription in [ISO 8601 duration format](https://en.wikipedia.org/wiki/ISO_8601#Durations) (e.g., "P14D" for 14 days).
    
    ### Override plan defaults
    
    Subscription plans can define a default trial duration. When creating a subscription, you can use this field to override the plan's default trial period:
    
    | Field value | Behaviour | Example |
    | ----------- | -------- | ------- |
    | **Not provided** | Uses the trial duration defined in the plan (if any) | Plan has `"P7D"` → subscription gets 7-day trial |
    | **Different value** | Overrides the plan's default trial duration | Plan has `"P7D"` → set to `"P30D"` for promotional offer, or `"P3D"` to reduce |
    | **`"P0D"`** | Explicitly skips the trial period | Plan has `"P7D"` → set to `"P0D"` to skip trial entirely |
    
    :::note
    Only days (`D`) are allowed. Time components such as hours, minutes, or seconds are not permitted.
    :::
- `trial_end_date` (string | null, optional)
    The date and time when the subscription's trial period ends in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format.
    
    This value is automatically calculated by the system as: `start_date` + `trial_duration`
    
    The `trial_duration` used in the calculation comes from either:
    - The subscription's custom `trial_duration` (if provided at creation time), or
    - The plan's default `trial_duration` (if no override was specified)
    
    This field is `null` when the subscription has no trial period (e.g., when `trial_duration` is not set or is `"P0D"`).
- `setup_order_id` (string, optional)
    The ID of the order created for handling the setup payment for the subscription.
    
    Use the [Retrieve an order](/docs/api/merchant#retrieve-an-order) endpoint with this ID to get order details, including the `checkout_url` for redirecting customers to the Hosted Payment Page or the `token` for widget integration.
    
    :::note
    The order is created in parallel to the subscription and is used to collect the initial payment and save the customer's payment method for future billing cycles.
    :::
- `scheduled_action` (object, optional)
    A pending scheduled action on the subscription, applied at the end of the current billing cycle.

## Error responses

| HTTP status code | Description |
| --- | --- |
| 400 | Bad Request |
| 401 | Unauthorized |
