A valid request URL is required to generate request examples{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"kind": "percent",
"percent_off": 123,
"amount_minor": 123,
"currency": "BRL",
"currency_exponent": 123,
"duration": "once",
"duration_months": 123,
"max_redemptions": 123,
"expires_at": "2023-11-07T05:31:56Z",
"archived": true,
"providers": [
{
"provider": "stripe",
"provider_account_id": "<string>",
"provider_coupon_id": "<string>"
}
],
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Create a coupon
Requires billing:write. Adds a discount to one environment’s catalogue. Build it in test and the live catalogue is untouched.
The kind decides which fields carry the discount, in both directions — the other kind’s fields are refused rather than ignored, because a request naming both is naming two discounts:
percent—percent_offis required, 1 to 100, a whole number.amount_minorandcurrencyare refused.amount—amount_minorandcurrencyare required and travel together, the catalogue’s money rule: an amount without a currency is not money.percent_offis refused. An amount coupon can only discount a price in its own currency — R50offaUS29 price is not an exchange-rate question, and the checkout refuses the pair.
duration is how long the discount keeps applying to a recurring subscription: once is the first invoice, forever is every invoice, and repeating is duration_months of them — required for that duration and refused for the other two.
A coupon’s terms are immutable. They are what somebody was promised, a subscription bought under them keeps producing invoices that only make sense against the terms as they were, and the database refuses any edit. There is no update endpoint; a different discount is a new coupon, and POST /v1/organization/catalogue/coupons/{id}/archive withdraws this one.
Nothing is created at any payment provider here. The gateway’s own coupon object is minted lazily, by the first checkout that applies this coupon on each gateway account.
A valid request URL is required to generate request examples{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"kind": "percent",
"percent_off": 123,
"amount_minor": 123,
"currency": "BRL",
"currency_exponent": 123,
"duration": "once",
"duration_months": 123,
"max_redemptions": 123,
"expires_at": "2023-11-07T05:31:56Z",
"archived": true,
"providers": [
{
"provider": "stripe",
"provider_account_id": "<string>",
"provider_coupon_id": "<string>"
}
],
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Authorizations
A staff session token, uk_st_…. Minted by sign-up, sign-in or the two-factor exchange. Only a 401 means it is spent; not_a_member (403) is about the organization named in X-Organization-Id and leaves the token good for the others.
Headers
The organization the caller is acting on — the org_… code that appears in the panel URL. It identifies; the membership JOIN is what authorizes, so a forged code reads nothing: the answer is not_a_member (403), which does not mean the session is over. Absent, the session's default organization answers, or — if that membership was revoked while the session was open — any other one the caller still holds.
Query Parameters
Which environment to act in. A view parameter, valid only on the staff surface — a machine credential never chooses its environment, it is resolved from the key.
live, test Body
A coupon on the way in. Every field is stated — there is no PATCH on a coupon, so no request carrying this is editing one. The kind decides which fields carry the discount, and the other kind's fields are refused rather than ignored: a request naming both is naming two discounts.
What the payer sees beside the discount.
percent, amount once, repeating, forever Required on percent, refused on amount. A whole number — the weakest gateway takes whole percents, and a catalogue storing 12.5 would promise what some checkout cannot honour.
1 <= x <= 100Required on amount with currency, refused on percent. An integer in the currency's minor unit; a discount of 0 discounts nothing and is refused.
x >= 1ISO 4217, uppercase. Travels with amount_minor always — an amount without a currency is not money. At checkout, an amount coupon may only discount a price in this currency.
"BRL"
Required on repeating, refused on the other durations — a stored number of months on a forever coupon is a second answer to a question the duration already answered.
x >= 1Omit for no cap. 0 is refused: a coupon nobody can redeem wearing a limit.
x >= 1When the offer stops being redeemable. Omit for never.
Response
The coupon. providers is empty — the gateway's own coupon is minted by the first checkout that applies it.
A discount you promise on your own catalogue. Its terms are immutable — a subscription bought under a coupon keeps producing invoices that only make sense against the terms as they were — so there is no update: a different discount is a new coupon, and this one is withdrawn by archiving.
The fields of the other kind and the other durations are null, never 0: 0% off and an amount of nothing are numbers a screen would render.
What the payer sees beside the discount at the gateway's checkout.
percent, amount A whole percentage, 1–100. null on an amount coupon.
The amount off, an integer in the currency's minor unit. null on a percent coupon.
ISO 4217, uppercase — the amount never travels without it. null on a percent coupon.
"BRL"
How many decimal places the currency has, so amount_minor can be rendered without hard-coding a divisor. null on a percent coupon.
How long the discount keeps applying to a recurring subscription: the first invoice, duration_months of them, or every one.
once, repeating, forever How many invoices repeating covers. null on the other durations.
How many redemptions the offer is good for, across all customers. null is no cap.
When the offer stops being redeemable. null is never. Subscriptions already discounted keep their discount either way.
Withdrawn: no new checkout may apply it. Existing discounts survive.
How this coupon is known at each payment provider. Empty is the ordinary state — the gateway's coupon is minted by the first checkout that applies this one on each account.
Show child attributes
Show child attributes