Coupons & Add-ons
Coupons
Section titled “Coupons”Coupons provide discounts that are applied to customer invoices during generation.
Coupon properties
Section titled “Coupon properties”| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier |
code | string | Unique coupon code |
name | string | Display name |
description | string | null | Optional description |
coupon_type | string | fixed_amount or percentage |
amount_cents | string | null | Discount amount (when fixed_amount) |
amount_currency | string | null | Currency code (when fixed_amount) |
percentage_rate | string | null | Percentage discount (when percentage) |
frequency | string | once, recurring, or forever |
frequency_duration | integer | null | Number of billing periods (when recurring) |
reusable | boolean | Whether coupon can be applied to multiple customers |
expiration | string | no_expiration or time_limit |
expiration_at | datetime | null | Expiry timestamp (when time_limit) |
status | string | active or terminated |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
Create a coupon
Section titled “Create a coupon”curl -X POST /v1/coupons \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "code": "WELCOME20", "name": "Welcome 20% Off", "coupon_type": "percentage", "percentage_rate": "20.00", "frequency": "recurring", "frequency_duration": 3, "reusable": true, "expiration": "time_limit", "expiration_at": "2026-12-31T23:59:59Z" }'Coupon types
Section titled “Coupon types”| Type | Description | Required field |
|---|---|---|
fixed_amount | Fixed monetary discount | amount_cents, amount_currency |
percentage | Percentage off subtotal | percentage_rate |
Frequency
Section titled “Frequency”| Frequency | Behavior |
|---|---|
once | Applied to one invoice, then terminated |
recurring | Applied for frequency_duration billing periods |
forever | Applied indefinitely |
Expiration
Section titled “Expiration”| Value | Behavior |
|---|---|
no_expiration | Coupon remains active until manually terminated |
time_limit | Coupon expires at expiration_at timestamp |
Update a coupon
Section titled “Update a coupon”Only name, description, expiration, expiration_at, and status can be modified after creation.
curl -X PUT /v1/coupons/WELCOME20 \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Welcome Discount 20%", "expiration": "time_limit", "expiration_at": "2027-06-30T23:59:59Z" }'Apply a coupon to a customer
Section titled “Apply a coupon to a customer”curl -X POST /v1/coupons/apply \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "coupon_code": "WELCOME20", "customer_id": "customer-uuid" }'- Non-reusable coupons can only be applied to one customer (409 if already used)
- Expired or terminated coupons cannot be applied (400)
amount_cents,amount_currency, andpercentage_ratecan be overridden per application
Applied coupon properties
Section titled “Applied coupon properties”| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier |
coupon_id | uuid | Reference to parent coupon |
customer_id | uuid | Reference to customer |
amount_cents | string | null | Override amount (if set) |
amount_currency | string | null | Override currency (if set) |
percentage_rate | number | null | Override percentage (if set) |
frequency | string | Inherited from coupon |
frequency_duration | integer | null | Total billing periods |
frequency_duration_remaining | integer | null | Remaining billing periods |
status | string | active or terminated |
terminated_at | datetime | null | When the application was terminated |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
Remove an applied coupon
Section titled “Remove an applied coupon”DELETE /v1/coupons/applied/{applied_coupon_id}Terminates a specific coupon application for a customer without affecting the coupon itself.
List customer applied coupons
Section titled “List customer applied coupons”GET /v1/customers/{customer_id}/applied_coupons?skip=0&limit=20Returns all applied coupons for a customer with pagination.
How discounts are calculated
Section titled “How discounts are calculated”During invoice generation:
- All active applied coupons for the customer are retrieved
- Percentage discounts:
discount = subtotal × rate / 100 - Fixed amount discounts:
min(amount_cents, remaining_subtotal) - Discounts are applied sequentially — if the subtotal reaches zero, remaining coupons are skipped
- The total discount is recorded as
coupons_amount_centson the invoice
Coupon analytics
Section titled “Coupon analytics”GET /v1/coupons/{code}/analyticsReturns usage statistics for a coupon:
| Field | Type | Description |
|---|---|---|
times_applied | integer | Total number of times applied |
active_applications | integer | Currently active applications |
terminated_applications | integer | Terminated applications |
total_discount_cents | string | Total discount amount given |
remaining_uses | integer | null | Remaining applications (non-reusable coupons) |
Duplicate a coupon
Section titled “Duplicate a coupon”POST /v1/coupons/{code}/duplicateCreates a copy of an existing coupon with a new code. Useful for creating variations of promotional campaigns.
Terminate a coupon
Section titled “Terminate a coupon”DELETE /v1/coupons/{code}Sets the coupon status to terminated. Existing applied coupons remain active until consumed.
Add-ons
Section titled “Add-ons”Add-ons are one-time charges applied to customers. When an add-on is applied, a one-off invoice is generated.
Add-on properties
Section titled “Add-on properties”| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier |
code | string | Unique add-on code |
name | string | Display name |
description | string | null | Optional description |
amount_cents | string | Default charge amount in cents |
amount_currency | string | Currency code (default: USD) |
invoice_display_name | string | null | Custom name shown on invoices |
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
Create an add-on
Section titled “Create an add-on”curl -X POST /v1/add_ons \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "code": "onboarding", "name": "Onboarding Fee", "amount_cents": 50000, "amount_currency": "USD", "invoice_display_name": "Professional Onboarding Service" }'Apply an add-on
Section titled “Apply an add-on”curl -X POST /v1/add_ons/apply \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "add_on_code": "onboarding", "customer_id": "customer-uuid", "amount_cents": 45000 }'When applied:
- An
AppliedAddOnrecord is created - A one-off invoice is generated with the add-on as a line item
- A fee with
fee_type: add_onis created
The amount_cents and amount_currency can be overridden from the default add-on price.
Applied add-on properties
Section titled “Applied add-on properties”| Field | Type | Description |
|---|---|---|
id | uuid | Unique identifier |
add_on_id | uuid | Reference to parent add-on |
customer_id | uuid | Reference to customer |
amount_cents | string | Charged amount in cents |
amount_currency | string | Currency code |
created_at | datetime | Creation timestamp |
Application history
Section titled “Application history”GET /v1/add_ons/{code}/applicationsReturns the list of customers who have been charged this add-on, including customer_name for display.
Application counts
Section titled “Application counts”GET /v1/add_ons/application_countsReturns a map of {add_on_id: count} showing how many times each add-on has been applied.
List customer applied add-ons
Section titled “List customer applied add-ons”GET /v1/customers/{customer_id}/applied_add_ons?skip=0&limit=20Returns all applied add-ons for a customer with pagination.
Customer portal
Section titled “Customer portal”Both coupons and add-ons are accessible through the customer portal API.
Portal coupon endpoints
Section titled “Portal coupon endpoints”| Method | Path | Description |
|---|---|---|
GET | /portal/coupons | List applied coupons for authenticated customer |
POST | /portal/coupons/redeem | Redeem a coupon code (body: {"coupon_code": "..."}) |
Portal add-on endpoints
Section titled “Portal add-on endpoints”| Method | Path | Description |
|---|---|---|
GET | /portal/add_ons | List available add-ons for purchase |
GET | /portal/add_ons/purchased | List purchased add-ons |
POST | /portal/add_ons/{add_on_id}/purchase | Purchase an add-on (creates invoice) |
The portal purchase response includes the applied_add_on_id, invoice_id, add_on_name, amount_cents, and amount_currency.
API endpoints
Section titled “API endpoints”Coupons
Section titled “Coupons”| Method | Path | Description |
|---|---|---|
POST | /v1/coupons | Create a coupon |
GET | /v1/coupons | List coupons (filterable by status) |
GET | /v1/coupons/{code} | Get coupon details |
PUT | /v1/coupons/{code} | Update a coupon |
DELETE | /v1/coupons/{code} | Terminate a coupon |
POST | /v1/coupons/{code}/duplicate | Duplicate a coupon |
GET | /v1/coupons/{code}/analytics | Get coupon analytics |
POST | /v1/coupons/apply | Apply coupon to customer |
DELETE | /v1/coupons/applied/{applied_coupon_id} | Remove applied coupon |
GET | /v1/customers/{customer_id}/applied_coupons | List customer applied coupons |
Add-ons
Section titled “Add-ons”| Method | Path | Description |
|---|---|---|
POST | /v1/add_ons | Create an add-on |
GET | /v1/add_ons | List add-ons |
GET | /v1/add_ons/{code} | Get add-on details |
PUT | /v1/add_ons/{code} | Update an add-on |
DELETE | /v1/add_ons/{code} | Delete an add-on |
POST | /v1/add_ons/apply | Apply add-on to customer |
GET | /v1/add_ons/{code}/applications | Get application history |
GET | /v1/add_ons/application_counts | Get application counts |
GET | /v1/customers/{customer_id}/applied_add_ons | List customer applied add-ons |