# Subscriptions with prebuilt payment page

Redirect customers to a MONEI-hosted payment page to activate their subscription. This is the simplest way to start collecting recurring payments — no frontend code required.

## Before You Begin[​](#before-you-begin "Direct link to Before You Begin")

* You need a MONEI account and your [API key](https://dashboard.monei.com/settings/api) (test or live).
* Use your [test mode keys](https://docs.monei.com/testing/.md) during development.
* Ensure at least one [payment method is enabled](https://dashboard.monei.com/settings/payment-methods) in your account settings.

## How It Works[​](#how-it-works "Direct link to How It Works")

<!-- -->

1. Your **backend** creates a subscription with amount, currency, and billing interval
2. The subscription is **activated**, returning a `redirectUrl` for the initial payment
3. The customer is **redirected** to the MONEI-hosted payment page
4. The customer completes the **initial payment** (including 3D Secure if required)
5. After payment, the customer is redirected back to your `completeUrl`
6. MONEI sends **webhooks** for both the initial payment and subscription status changes — recurring payments are charged automatically at each billing interval

## Integration Steps[​](#integration-steps "Direct link to Integration Steps")

<!-- -->

### 1. Create a subscription (Server-side)[​](#1-create-a-subscription-server-side "Direct link to 1. Create a subscription (Server-side)")

Create a [Subscription](https://docs.monei.com/apis/rest/subscriptions-create/.md) on your server with the billing amount, currency, and interval.

* cURL
* Node.js
* PHP
* Python

POST https\://api.monei.com/v1/subscriptions

```
curl --request POST 'https://api.monei.com/v1/subscriptions' \

--header 'Authorization: YOUR_API_KEY' \

--header 'Content-Type: application/json' \

--data-raw '{

  "amount": 1500,

  "currency": "EUR",

  "interval": "month",

  "intervalCount": 1,

  "description": "Pro Plan Monthly",

  "customer": {

    "name": "John Doe",

    "email": "john.doe@example.com"

  },

  "callbackUrl": "https://example.com/subscriptions/callback",

  "paymentCallbackUrl": "https://example.com/payments/callback"

}'
```

(Replace `YOUR_API_KEY` with your actual MONEI API key)

server.js

```
import {Monei} from '@monei-js/node-sdk';



// Replace YOUR_API_KEY with your actual MONEI API key

const monei = new Monei('YOUR_API_KEY');



const subscription = await monei.subscriptions.create({

  amount: 1500,

  currency: 'EUR',

  interval: 'month',

  intervalCount: 1,

  description: 'Pro Plan Monthly',

  customer: {

    name: 'John Doe',

    email: 'john.doe@example.com'

  },

  callbackUrl: 'https://example.com/subscriptions/callback',

  paymentCallbackUrl: 'https://example.com/payments/callback'

});



// You will need the subscription id in the next step

const subscriptionId = subscription.id;
```

server.php

```
<?php

require_once 'vendor/autoload.php';



use Monei\MoneiClient;

use Monei\Model\CreateSubscriptionRequest;

use Monei\Model\PaymentCustomer;



// Replace YOUR_API_KEY with your actual MONEI API key

$monei = new MoneiClient('YOUR_API_KEY');



$subscription = $monei->subscriptions->create(

  new CreateSubscriptionRequest([

    'amount' => 1500,

    'currency' => 'EUR',

    'interval' => 'month',

    'interval_count' => 1,

    'description' => 'Pro Plan Monthly',

    'customer' => new PaymentCustomer([

      'name' => 'John Doe',

      'email' => 'john.doe@example.com'

    ]),

    'callback_url' => 'https://example.com/subscriptions/callback',

    'payment_callback_url' => 'https://example.com/payments/callback'

  ])

);



// You will need the subscription id in the next step

$subscriptionId = $subscription->getId();

?>
```

server.py

```
import Monei

from Monei import CreateSubscriptionRequest, PaymentCustomer



# Replace YOUR_API_KEY with your actual MONEI API key

monei = Monei.MoneiClient(api_key="YOUR_API_KEY")



subscription = monei.subscriptions.create(

    CreateSubscriptionRequest(

        amount=1500,

        currency="EUR",

        interval="month",

        interval_count=1,

        description="Pro Plan Monthly",

        customer=PaymentCustomer(

            name="John Doe",

            email="john.doe@example.com"

        ),

        callback_url="https://example.com/subscriptions/callback",

        payment_callback_url="https://example.com/payments/callback"

    )

)



# You will need the subscription id in the next step

subscription_id = subscription.id
```

**Key parameters:**

* **amount** positive integer — Amount in the smallest currency unit (e.g., 1500 = €15.00).
* **currency** string — Three-letter [ISO currency code](https://en.wikipedia.org/wiki/ISO_4217) (e.g., `EUR`).
* **interval** string — Billing interval: `day`, `week`, `month`, or `year`.
* **intervalCount** number — Number of intervals between each charge (e.g., `3` with `month` = quarterly).
* **callbackUrl** string — URL that receives subscription status change webhooks.
* **paymentCallbackUrl** string — URL that receives payment webhooks for each recurring charge.

Check all available [request parameters](https://docs.monei.com/apis/rest/subscriptions-create/.md).

### 2. Activate the subscription (Server-side)[​](#2-activate-the-subscription-server-side "Direct link to 2. Activate the subscription (Server-side)")

Activate the subscription to start the billing process. The response includes a `redirectUrl` to send the customer to the MONEI-hosted payment page.

* cURL
* Node.js
* PHP
* Python

POST https\://api.monei.com/v1/subscriptions/{id}/activate

```
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/activate' \

--header 'Authorization: YOUR_API_KEY' \

--header 'Content-Type: application/json' \

--data-raw '{

  "completeUrl": "https://example.com/checkout/complete"

}'
```

(Replace `YOUR_SUBSCRIPTION_ID` and `YOUR_API_KEY`)

server.js

```
const activation = await monei.subscriptions.activate('YOUR_SUBSCRIPTION_ID', {

  completeUrl: 'https://example.com/checkout/complete'

});



// Redirect the customer to this URL

const redirectUrl = activation.nextAction.redirectUrl;
```

server.php

```
<?php

use Monei\Model\ActivateSubscriptionRequest;



$activation = $monei->subscriptions->activate(

  'YOUR_SUBSCRIPTION_ID',

  new ActivateSubscriptionRequest([

    'complete_url' => 'https://example.com/checkout/complete'

  ])

);



// Redirect the customer to this URL

$redirectUrl = $activation->getNextAction()->getRedirectUrl();

?>
```

server.py

```
from Monei import ActivateSubscriptionRequest



activation = monei.subscriptions.activate(

    "YOUR_SUBSCRIPTION_ID",

    ActivateSubscriptionRequest(

        complete_url="https://example.com/checkout/complete"

    )

)



# Redirect the customer to this URL

redirect_url = activation.next_action.redirect_url
```

The activation response is a [Payment object](https://docs.monei.com/apis/rest/schemas/payment/.md) for the initial charge. Redirect the customer to `nextAction.redirectUrl`.

Check all available [request parameters](https://docs.monei.com/apis/rest/subscriptions-activate/.md).

### 3. Customer completes the payment[​](#3-customer-completes-the-payment "Direct link to 3. Customer completes the payment")

The customer enters their payment details on the MONEI-hosted payment page and completes any required 3D Secure verification.

### 4. Customer is redirected back to your site[​](#4-customer-is-redirected-back-to-your-site "Direct link to 4. Customer is redirected back to your site")

The customer is redirected to `completeUrl` with `payment_id` and `subscription_id` query parameters.

Use the [get payment](https://docs.monei.com/apis/rest/payments-get/.md) endpoint to check the initial payment status, and the [get subscription](https://docs.monei.com/apis/rest/subscriptions-get/.md) endpoint to verify the subscription status (it should be `ACTIVE` or `TRIALING`).

note

Do not rely solely on the redirect to confirm the payment — always use the webhook (next step) as the authoritative source of truth.

### 5. Handle webhooks (Server-side)[​](#5-handle-webhooks-server-side "Direct link to 5. Handle webhooks (Server-side)")

MONEI sends two types of webhook notifications:

* **Payment callback** — sent to `paymentCallbackUrl` for the initial payment and each recurring charge. The request body contains the full [Payment object](https://docs.monei.com/apis/rest/schemas/payment/.md).
* **Subscription callback** — sent to `callbackUrl` when the subscription status changes (e.g., `PENDING` → `ACTIVE`). The request body contains the full [Subscription object](https://docs.monei.com/apis/rest/schemas/subscription/.md).

Each request includes a `MONEI-Signature` header. [Verify this signature](https://docs.monei.com/guides/verify-signature/.md) to confirm the request is from MONEI, and return a `200` HTTP status code to acknowledge receipt.

If MONEI does not receive a `200` response, the notification will be retried.

## Before You Go Live[​](#before-you-go-live "Direct link to Before You Go Live")

* Switch to your [live mode](https://dashboard.monei.com/settings/api) API key.
* Ensure your [payment methods are enabled](https://dashboard.monei.com/settings/payment-methods) in live mode.
* Test your webhook endpoints handle both payment and subscription callbacks correctly.

Test mode limits

In test mode, subscriptions have the following limits:

* Maximum **3 active subscriptions** per account
* Subscriptions are **auto-canceled after 12 payments**
* **Minute and hour** billing intervals are available for faster testing
