Coupons
A coupon takes a percentage or a fixed amount off a payment. Customers type its code on the hosted checkout, you add it to a payment link's URL so it is already applied, or you pass it when you create a charge. Each coupon belongs to the mode its key works in.
The coupon object
| Field | Type | Description |
|---|---|---|
id, code
string
|
string | The code customers type, in capitals: 3 to 32 letters, digits, dashes or underscores. Unique in each mode, and matched in any case. |
object
"coupon"
|
"coupon" | The kind of object. |
percent_off
string|null
|
string|null | The share taken off, from 0.01 to 99.99, or null for an amount off. |
amount_off
string|null
|
string|null | The amount taken off, or null for a percentage. Never more than the price: a coupon worth the whole price is refused. |
currency
string|null
|
string|null | Required with amount_off or min_amount, and the coupon then only works on payments in this currency. null for a percentage that works in every currency. |
min_amount
string|null
|
string|null | The least the price before the discount must be. |
max_redemptions
integer|null
|
integer|null | How many payments may use the coupon, 1 to 1,000,000. A charge that is still open holds a use until it is paid or expires. |
times_redeemed
integer
|
integer | How many paid charges used the coupon. |
once_per_customer
boolean
|
boolean | Each customer email can use the coupon once, so the email becomes required when it is used. |
payment_links
array
|
array | The ids of the payment links the coupon is limited to. Empty means every link, and charges made without one. |
active
boolean
|
boolean | Whether customers can use it. Switch it off to pause the coupon. |
expires_at
string|null
|
string|null | ISO 8601. The coupon stops working after it; a bare date such as 2026-12-31 means 23:59:59 UTC that day. |
created_at, updated_at
string
|
string | ISO 8601 timestamps in UTC. |
Endpoints
-
GET
/v1/couponsList coupons, newest first. Paginated with ?page= and ?per_page= (max 100). -
POST
/v1/couponsCreate a coupon. Body: code, percent_off or amount_off, currency, min_amount, max_redemptions, once_per_customer, payment_links, active, expires_at. -
GET
/v1/coupons/{id}Retrieve a coupon. -
PATCH
/v1/coupons/{id}Change any subset of max_redemptions, once_per_customer, payment_links, active and expires_at. The code, the discount, the currency and min_amount cannot change: create a new coupon instead. payment_links replaces the whole list. -
DELETE
/v1/coupons/{id}Delete a coupon. Charges that used it keep its code and their discount. Answers 204.
Example: create a coupon
curl -X POST https://api.velirapay.com/v1/coupons \
-H "Authorization: Bearer vp_live_…" \
-H "Content-Type: application/json" \
-d '{
"code": "SPRING10",
"percent_off": "10",
"max_redemptions": 100,
"expires_at": "2026-12-31"
}'
HTTP/1.1 201 Created
{
"data": {
"id": "SPRING10",
"object": "coupon",
"code": "SPRING10",
"percent_off": "10.00",
"amount_off": null,
"currency": null,
"max_redemptions": 100,
"times_redeemed": 0,
"payment_links": [],
"active": true,
"expires_at": "2026-12-31T23:59:59.000000Z",
…
}
}
Applying a coupon
On the hosted checkout, customers type the code under "Have a coupon code?", which appears while at least one of your coupons could apply to that link (active, not expired or used up, in its currency, and open to it). To apply it for them, add it to the payment link's URL; they see the lower price straight away and can still remove it.
https://velirapay.com/pay/6dprcllogj1a?coupon=SPRING10
Through the API, pass coupon when you create a charge, with or without a payment link. A coupon that cannot be used answers 422 with the reason under errors.coupon: it does not exist in this mode, is paused or expired, is limited to other links, is in another currency, needs a higher price, is used up, or the customer already used it.
The charge then records what the coupon took off: fiat_amount is the price the customer pays, coupon holds the code and discount_amount the difference. Webhooks, the receipt and the receipt email show them too.