Manage subscriptions
After a subscription is activated, you can manage its lifecycle using the MONEI API — pause, resume, cancel, skip payments, update the payment method, modify subscription details, and prorate plan changes.
Pause a subscription
Temporarily suspend billing without canceling the subscription. There are several ways to pause:
Pause immediately
The subscription moves to PAUSED status right away. No further payments are charged until you resume it.
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/pause' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json'
const subscription = await monei.subscriptions.pause('YOUR_SUBSCRIPTION_ID');
<?php
$subscription = $monei->subscriptions->pause('YOUR_SUBSCRIPTION_ID');
?>
subscription = monei.subscriptions.pause("YOUR_SUBSCRIPTION_ID")
Pause at the end of the current billing period
The subscription stays ACTIVE until the current billing period ends, then transitions to PAUSED.
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/pause' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"pauseAtPeriodEnd": true,
"pauseIntervalCount": 3
}'
const subscription = await monei.subscriptions.pause('YOUR_SUBSCRIPTION_ID', {
pauseAtPeriodEnd: true,
pauseIntervalCount: 3
});
<?php
use Monei\Model\PauseSubscriptionRequest;
$subscription = $monei->subscriptions->pause(
'YOUR_SUBSCRIPTION_ID',
new PauseSubscriptionRequest([
'pause_at_period_end' => true,
'pause_interval_count' => 3
])
);
?>
from Monei import PauseSubscriptionRequest
subscription = monei.subscriptions.pause(
"YOUR_SUBSCRIPTION_ID",
pause_subscription_request=PauseSubscriptionRequest(
pause_at_period_end=True,
pause_interval_count=3
)
)
Auto-resume after N billing cycles
Set pauseIntervalCount to automatically resume the subscription after a specific number of billing cycles. For example, if the subscription bills monthly and you set pauseIntervalCount: 3, it will pause for 3 months and then automatically resume.
When the count reaches 0, the subscription transitions back to ACTIVE and billing resumes.
Resume a subscription
Resume a paused subscription to restart billing. The next payment is scheduled at the end of the current billing period.
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/resume' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json'
const subscription = await monei.subscriptions.resume('YOUR_SUBSCRIPTION_ID');
<?php
$subscription = $monei->subscriptions->resume('YOUR_SUBSCRIPTION_ID');
?>
subscription = monei.subscriptions.resume("YOUR_SUBSCRIPTION_ID")
Resuming clears any pending pause or cancel-at-period-end flags.
Cancel a subscription
Permanently stop a subscription. Once canceled, no further payments will be charged.
Cancel immediately
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/cancel' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json'
const subscription = await monei.subscriptions.cancel('YOUR_SUBSCRIPTION_ID');
<?php
$subscription = $monei->subscriptions->cancel('YOUR_SUBSCRIPTION_ID');
?>
subscription = monei.subscriptions.cancel("YOUR_SUBSCRIPTION_ID")
Cancel at the end of the current billing period
The subscription stays active until the current period ends, then transitions to CANCELED. The customer continues to have access until their paid period expires.
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/cancel' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"cancelAtPeriodEnd": true
}'
const subscription = await monei.subscriptions.cancel('YOUR_SUBSCRIPTION_ID', {
cancelAtPeriodEnd: true
});
<?php
use Monei\Model\CancelSubscriptionRequest;
$subscription = $monei->subscriptions->cancel(
'YOUR_SUBSCRIPTION_ID',
new CancelSubscriptionRequest([
'cancel_at_period_end' => true
])
);
?>
from Monei import CancelSubscriptionRequest
subscription = monei.subscriptions.cancel(
"YOUR_SUBSCRIPTION_ID",
cancel_subscription_request=CancelSubscriptionRequest(
cancel_at_period_end=True
)
)
If a customer changes their mind before the period ends, you can resume the subscription to clear the cancel-at-period-end flag.
Skip billing cycles
Skip one or more billing cycles without changing the subscription status. The subscription remains ACTIVE — the payment is simply not charged during the skipped cycles.
Use the update subscription endpoint with skipIntervalCount (1–31):
- cURL
- Node.js
- PHP
- Python
curl --request PUT 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"skipIntervalCount": 2
}'
const subscription = await monei.subscriptions.update('YOUR_SUBSCRIPTION_ID', {
skipIntervalCount: 2
});
<?php
use Monei\Model\UpdateSubscriptionRequest;
$subscription = $monei->subscriptions->update(
'YOUR_SUBSCRIPTION_ID',
new UpdateSubscriptionRequest([
'skip_interval_count' => 2
])
);
?>
from Monei import UpdateSubscriptionRequest
subscription = monei.subscriptions.update(
"YOUR_SUBSCRIPTION_ID",
UpdateSubscriptionRequest(
skip_interval_count=2
)
)
For example, setting skipIntervalCount: 2 on a monthly subscription skips the next 2 monthly payments. Billing resumes automatically after the skipped cycles.
Skip is only available for subscriptions in ACTIVE, TRIALING, or PAST_DUE status. It cannot be used on paused, canceled, or pending subscriptions.
Update payment method
To change the payment method on an active subscription, call the activate endpoint again. MONEI creates a €0 verification payment to validate the new payment method without charging the customer.
The activation flow is the same as the initial activation — use either the Hosted Payment Page or custom checkout approach. After the new payment method is verified, all future recurring charges will use it.
Update subscription details
Modify subscription properties like amount, billing interval, description, metadata, or the next payment date using the update subscription endpoint.
- cURL
- Node.js
- PHP
- Python
curl --request PUT 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 2500,
"description": "Pro Plan Monthly (upgraded)"
}'
const subscription = await monei.subscriptions.update('YOUR_SUBSCRIPTION_ID', {
amount: 2500,
description: 'Pro Plan Monthly (upgraded)'
});
<?php
use Monei\Model\UpdateSubscriptionRequest;
$subscription = $monei->subscriptions->update(
'YOUR_SUBSCRIPTION_ID',
new UpdateSubscriptionRequest([
'amount' => 2500,
'description' => 'Pro Plan Monthly (upgraded)'
])
);
?>
from Monei import UpdateSubscriptionRequest
subscription = monei.subscriptions.update(
"YOUR_SUBSCRIPTION_ID",
UpdateSubscriptionRequest(
amount=2500,
description="Pro Plan Monthly (upgraded)"
)
)
Updatable fields:
- amount — Change the recurring charge amount. The new amount applies from the next billing cycle. To charge or refund the difference now, prorate the change.
- interval / intervalCount — Change the billing frequency. The maximum period is 1 year. The current period runs to its end, and the new interval applies from the next one.
- nextPaymentAt — Move the next charge to a new date, without a change to the price. See Move the next charge date.
- trialPeriodEnd — Extend the trial period on a
TRIALINGsubscription (must be a future timestamp). - description / metadata — Update descriptive fields and custom metadata.
If the subscription uses Bizum as the payment method, the amount cannot be changed after activation, and charges cannot be prorated.
Move the next charge date
Send nextPaymentAt (a Unix timestamp in seconds) to move the next charge. Later charges follow on from the new date. On its own, the move charges and refunds nothing.
- The date must be in the future and no more than five years ahead.
- The subscription must be
ACTIVEorPAST_DUE. To move a trial, updatetrialPeriodEnd. To move a paused subscription, resume it first. - A pending skip, pause or cancellation blocks the move, because the charge on the new date would not happen. Clear it in the same request: send
skipIntervalCount: 0,pauseIntervalCount: null,pauseAtPeriodEnd: falseorcancelAtPeriodEnd: false. - On a
PAST_DUEsubscription, a move stops the retries and schedules the charge on the new date.
To charge or refund for the time the move adds or removes, send prorate: true with it.
Prorate a change
By default, a new price or interval takes effect at the next billing cycle. Send prorate: true with the update to settle the difference now: MONEI credits the unused time at the current price, charges the new price, and charges or refunds the difference.
What MONEI charges depends on what you change:
| Change | Credit | Charge | Billing period |
|---|---|---|---|
amount | Unused time at the current price | Remaining time at the new price | Unchanged |
interval / intervalCount | Unused time at the current price | The full new price | Restarts now |
nextPaymentAt | Unused time at the current price | Time from now to the new date, at the current price | Ends on the new date |
A later date charges for the time it adds. An earlier date refunds the time it removes.
For example, a customer on a €10 monthly plan upgrades to €20 halfway through the month. MONEI credits €5 for the unused half at €10, charges €10 for the same half at €20, and charges the €5 difference to the saved payment method. The next €20 charge happens on the original date.
1. Preview the change
Call preview subscription update with the same fields you plan to send. It returns what the change would settle, and changes nothing. Show it to the customer before they confirm.
- cURL
- Node.js
- PHP
- Python
curl --request POST 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID/preview' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 2000
}'
const preview = await monei.subscriptions.preview('YOUR_SUBSCRIPTION_ID', {
amount: 2000
});
<?php
use Monei\Model\PreviewSubscriptionUpdateRequest;
$preview = $monei->subscriptions->preview(
'YOUR_SUBSCRIPTION_ID',
new PreviewSubscriptionUpdateRequest([
'amount' => 2000
])
);
?>
from Monei import PreviewSubscriptionUpdateRequest
preview = monei.subscriptions.preview(
"YOUR_SUBSCRIPTION_ID",
PreviewSubscriptionUpdateRequest(
amount=2000
)
)
{
"credit": 500,
"charge": 1000,
"net": 500,
"direction": "charge",
"refundCapped": false,
"effectiveAt": 1790000000,
"currentPeriodEnd": 1791296000
}
- credit — Unused time at the current price, in the smallest currency unit.
- charge — Time at the new price. An interval change charges the full new price.
- net —
chargeminuscredit: the amount that moves. - direction —
charge,refundornone.nonemeans the difference rounds to zero. - newPeriodEnd / nextPaymentAt — Only when the change restarts or moves the billing period.
The figures are an estimate: the update recalculates them when you apply it. The preview runs the same checks as the update, so a change the preview rejects is also rejected on update.
2. Apply the change
Send the same fields to update subscription with prorate: true:
- cURL
- Node.js
- PHP
- Python
curl --request PUT 'https://api.monei.com/v1/subscriptions/YOUR_SUBSCRIPTION_ID' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
"amount": 2000,
"prorate": true
}'
const subscription = await monei.subscriptions.update('YOUR_SUBSCRIPTION_ID', {
amount: 2000,
prorate: true
});
<?php
use Monei\Model\UpdateSubscriptionRequest;
$subscription = $monei->subscriptions->update(
'YOUR_SUBSCRIPTION_ID',
new UpdateSubscriptionRequest([
'amount' => 2000,
'prorate' => true
])
);
?>
from Monei import UpdateSubscriptionRequest
subscription = monei.subscriptions.update(
"YOUR_SUBSCRIPTION_ID",
UpdateSubscriptionRequest(
amount=2000,
prorate=True
)
)
The response is the updated subscription. lastProration records what the change settled (credit, charge, net, and the paymentId of the charge, if any), and lastProrationAt records when. MONEI also sends a subscription.updated webhook.
How refunds work
When the difference is negative, MONEI refunds it from the payments that funded the current billing period, newest first: the charge from the latest prorated change in the period, then the renewal payment. If those payments together cannot cover the refund, MONEI rejects the change and moves no money. A change is settled in full or not at all.
A refund needs refunds to be enabled on your account.
Limits
- Status — Only
ACTIVEandTRIALINGsubscriptions. On aTRIALINGsubscription the fields change and no money moves, because there is no paid time to credit. - Repeat changes — You can prorate a billing period more than once. Wait at least one second between changes: MONEI rejects a change while the previous one is still settling.
- Resized periods — After a change moves the end of the current period (a
nextPaymentAtmove, or an interval change withoutprorate), you cannot prorate again until the next renewal. - Next charge date — A prorated
nextPaymentAtmove works onACTIVEsubscriptions only, cannot be combined with an interval change, and cannot charge for more than 24 billing periods. - Scheduled changes —
proratecannot be combined withtrialPeriodEnd,cancelAtPeriodEnd,pauseAtPeriodEnd,pauseIntervalCountorskipIntervalCount. A prorated interval change is rejected while a cancellation, pause or skip is scheduled. The one exception is anextPaymentAtmove, which accepts the clearing values listed in Move the next charge date. - Something to settle —
prorateneeds a change toamount,interval,intervalCountornextPaymentAt. - Bizum — Subscriptions that pay with Bizum cannot be prorated.
Prorate in the dashboard
- In the MONEI Dashboard, open the subscription and click Update.
- Change the Amount, the Billing period or the Next charge date.
- Turn on Apply the change now. The form shows what the customer will be charged or refunded.
- Click Update subscription.
The Apply the change now switch appears for active subscriptions that do not pay with Bizum. Each settlement then appears in the subscription's timeline as a Prorated charge or a Prorated refund.