billing
POST /v1/subscriptions/{subscriptionId}/prepay
Create the order to pay for several billing periods at once.
Authentication
Send an API key as a bearer token. The key must carry the billing.payment.manage permission; a key without it is refused with 403, not 404.
This endpoint takes no organisation id. Your key already identifies the organisation it belongs to, and the response is scoped to it.
Try it
Replace anything in angle brackets with your own values, and the key placeholder with a key from your dashboard.
curl -X POST https://api.zinndigital.com/v1/subscriptions/{subscriptionId}/prepay \
-H "Authorization: Bearer zdk_live_…" \
-H "Content-Type: application/json" \
-d '{ "periods": <integer> }'Signed in? The API console in your dashboard fills in your real organisation id and your own key, and runs the request against the live API so you can see the actual response. Open this endpoint in the API console
Details
Mints an unpaid order for N whole billing periods. ⛔⛔ No money is taken here. The client then settles that order through POST /v1/orders/{orderId}/pay, which already knows how to pay from account balance, from a gateway, or from both. That separation is the point rather than an implementation detail: it is what lets a customer with no chargeable mandate use this at all — somebody paying in crypto, or in a market whose regulator forbids an off-session charge. They top up once and pay six months from their balance, with no card anywhere in the flow. Replaying the same request returns the same order rather than a second one, so a double-clicked button cannot bill twice. Asking for a different number of periods supersedes the earlier unpaid prepay order and mints a fresh one — a customer changing their mind is not a collision. An unpaid order against this subscription that is not a prepayment (a plan change, say) is refused with ORDER_IN_FLIGHT instead, and is never cancelled on the customer's behalf. Requires billing.payment.manage. 422 carries a code in its details: TOO_FEW / TOO_MANY (outside the allowed range), NOT_PREPAYABLE (ended, comped or free), RAIL_NOT_SUPPORTED (billed by PayPal on its own schedule), ORDER_IN_FLIGHT, or ARREARS_OUTSTANDING — the subscription owes missed periods (Subscription.periods_owed > 0) and fewer periods than that were asked for: a payment that leaves the service paused is not sold here (W43-107; s1014 R40). Asking for periods >= periods_owed is the pay everything owed order: it extends from the date the subscription is paid through, so it covers every missed period first, brings the service back, and cancels the unpaid renewal order(s) it paid for so the same month is never chased twice.
Parameters
| Name | Type | Required | What it is |
|---|---|---|---|
subscriptionId (path) | Uuid | Yes | The subscription to pay ahead on. |
Request body
| Name | Type | Required | What it is |
|---|---|---|---|
periods | integer | Yes | How many whole billing periods to pay for now. |
Response
| Name | Type | Required | What it is |
|---|---|---|---|
order_id | Uuid | Yes | UUIDv7 identifier — sortable by creation time (docs/02 §8). |
order_number | string | Yes | — |
periods | integer | Yes | — |
total_amount_minor | integer | Yes | Including tax. |
currency | string | Yes | — |
status | string | Yes | — |
Errors this endpoint can return
401 · 403 · 404 · 422 · 429