Payment schedules
A payment schedule is a template that generates payment orders automatically, at a fixed interval, until an end date.
How it works
- Create a payment order with a nested
payment_scheduleobject. This payment order is the first occurrence, called the original payment order. - Mambu Payments creates a
payment_schedulelinked to it throughoriginal_payment_id, and setspayment_schedule_idon the original payment order, returned in the same response. - On each
next_payment_date, a daily job copies the original payment order into a new payment order, stamped with the samepayment_schedule_id. - Each generated payment order follows the normal payment order lifecycle. You can approve, cancel or reconcile it without affecting the schedule.
Key concepts
| Term | Definition |
|---|---|
| Original payment order | The payment order sent with the payment_schedule object. All generated payment orders copy its amount, currency, accounts, reference, type, direction and metadata. |
first_payment_date | The date the series counts from. It is the original payment order's requested_execution_date, or the connected account's current day when none is set. |
next_payment_date | The date the next payment order is generated, at 05:00 in the connected account's timezone (UTC when none is set). null when the schedule is disabled. |
end_date | No payment order is generated after this date. The schedule moves to disabled once it is reached. |
original_payment_details | A snapshot of the original payment order's amount, currency and accounts, stored on the schedule. |
Create a payment schedule
Add a payment_schedule object to POST /payment_orders.
POST /v1/payment_orders
{
"type": "sepa",
"direction": "credit",
"amount": 125000,
"currency": "EUR",
"connected_account_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"receiving_account": {
"holder_name": "SCI Les Tilleuls",
"account_number": "FR7630006000011234567890189",
"bank_code": "AGRIFRPPXXX"
},
"reference": "Rent apartment 4B",
"requested_execution_date": "2026-11-01",
"payment_schedule": {
"interval": "month",
"interval_count": 1,
"end_date": "2027-10-31"
}
}This pays €1,250.00 on the 1st of every month from November 2026 to October 2027. Amounts are in the smallest currency unit.
| Field | Type | Required | Rules |
|---|---|---|---|
interval | string | Yes | day, week, month, year or end_of_month. |
interval_count | integer | Yes | Number of intervals between two payment orders. Greater than 0, at most 1000. week + 2 = every two weeks. |
end_date | string (YYYY-MM-DD) | Yes | Must be strictly after first_payment_date, otherwise the request returns 400. |
Use end_of_month to pay on the last day of every month, whatever its length.
Every date is computed from first_payment_date, not from the previous payment order. When the anchor day does not exist in a month, the last day of that month is used. A schedule anchored on 31 January pays on 28 February, then on 31 March. A yearly schedule anchored on 29 February pays on 28 February in other years.
Retrieve a payment schedule
Find the schedule created by your payment order:
GET /v1/payment_schedules?original_payment_id=01a11760-2c4e-7b19-9a03-5d8e7f6a1b2c{
"id": "01a11760-2c51-73f6-9275-14066bb8d631",
"object": "payment_schedule",
"status": "active",
"status_details": null,
"original_payment_id": "01a11760-2c4e-7b19-9a03-5d8e7f6a1b2c",
"original_payment_details": {
"amount": 125000,
"currency": "EUR",
"connected_account_id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"originating_account": { "account_number": "FR7612739000704851925386421", "holder_name": "Claire Martin", "...": "..." },
"originating_account_id": null,
"receiving_account": { "account_number": "FR7630006000011234567890189", "holder_name": "SCI Les Tilleuls", "...": "..." },
"receiving_account_id": null,
"direct_debit_mandate_id": null
},
"interval": "month",
"interval_count": 1,
"first_payment_date": "2026-11-01T00:00:00Z",
"end_date": "2027-10-31T00:00:00Z",
"next_payment_date": "2026-12-01T05:00:00Z",
"metadata": {},
"created_at": "2026-10-13T09:12:44Z"
}List all schedules with GET /v1/payment_schedules. Filter by status, interval or original_payment_id. Standard pagination applies.
List the payment orders of a schedule
GET /v1/payment_orders?payment_schedule_id=01a11760-2c51-73f6-9275-14066bb8d631The response includes the original payment order and every payment order generated so far.
Pause, resume or stop a schedule
| Action | Endpoint | Allowed from | Result |
|---|---|---|---|
| Pause | POST /v1/payment_schedules/{id}/pause | active | paused. next_payment_date is kept. Any other status returns 409. |
| Resume | POST /v1/payment_schedules/{id}/activate | paused | active. next_payment_date moves to the next future date. Any other status returns 409. |
| Stop | POST /v1/payment_schedules/{id}/disable | active, paused, blocked | disabled. Terminal. next_payment_date becomes null. |
Resuming never replays missed dates. A schedule paused over three monthly dates resumes with the next future date, not three catch-up payment orders.
An active schedule behaves differently. If a due date is missed while the schedule is active, Mambu Payments creates one payment order per missed date. Each is executed on the day it is created.
Statuses
| Status | Meaning | Set by |
|---|---|---|
active | Generates a payment order on each next_payment_date. | Creation, or you (activate from paused) |
paused | Generates nothing until you resume it. | You (pause from active) |
blocked | A payment order could not be created because of a validation or conflict error. status_details gives the reason. | Mambu Payments |
disabled | Terminal. No more payment orders. | You, end_date reached, or creation when the second date falls after end_date |
Example status_details on a blocked schedule: receiving_account_id: SEPA payments can only be sent to IBANs belonging to SEPA countries.
Other errors, such as a temporary outage, do not block the schedule. Mambu Payments retries 5 times, then every hour.
You cannot pause or activate a blocked schedule: both return 409. Contact support to unblock it once the cause is fixed, or disable it.
Webhooks
Subscribe to the payment_schedule topic to track schedules without polling.
| Event type | Sent when |
|---|---|
active | The schedule is created, or resumed from paused. |
updated | A payment order was generated and next_payment_date moved. |
paused | You paused the schedule. |
blocked | A payment order could not be created. Read status_details. |
disabled | You disabled the schedule, end_date was reached, or the schedule was created disabled. |
Each generated payment order also sends the usual payment_order events.
Limits and constraints
- The
payment_schedulefeature flag must be enabled on your account. Otherwise the endpoints return403. - List and retrieve need
payments.view_payment_schedules. Pause, activate and disable needpayments.edit_payment_schedules. Both are in the Admin and Manager default roles. API keys need Read and Modify access respectively. end_dateis required. Open-ended schedules are not supported. Invalidpayment_schedulefields return400.- If the second occurrence would fall after
end_date, the schedule is created asdisabledand only the original payment order is sent. - Every generated payment order is identical to the original, including
reference. Reference templating is not supported. - Business days and bank holidays are not taken into account. A payment order can be generated on a weekend date.
- No approval workflow applies to the schedule itself. Generated payment orders follow your usual approval rules.
- Payment schedules cannot be created from an existing payment order, and do not support expected payments.
Updated 3 days ago
