Skip to content

Powered by Grav CMS + Helios Theme

Coupons

Discount codes a shopper types in at checkout.

Codes a shopper types in. See Coupons.

List coupons

GET /api/v1/kahunacart/coupons Permission kahunacart.settings

Discount codes with their type, percentage or amount, minimum and maximum cart totals, schedule, usage limits, how many times each has been redeemed, and the restriction matrix: what each is scoped to, whether it pays the postage, whether it skips items already on sale, how many units it covers, which addresses it is reserved for, and its conditions as a nested conditions document (an empty all when it has none). A coupon is what a shopper types in at the till; a site-wide automatic discount is a sale, listed by list_sales.

Parameters

Name Type Description
page optional integer At least 1.
Default: 1
per_page optional integer At least 1.
Default: 100
group_id optional string A campaign id to list only its codes, or "none" for codes in no campaign; applied before the sort and the page, and total counts the same set
id optional integer Only this code, for opening one from a link
sort optional string A column to sort every row by before it is paged; leave out for the usual order
One of: code, discount, expires, usage, status
dir optional string
One of: asc, desc
Default: asc
q optional string Words to search for in the code and the addresses a code is kept to; every word has to be there, in any order. Applied before the sort and the page, and total counts what it found

Create a coupon

POST /api/v1/kahunacart/coupons Permission kahunacart.settings

Create a discount code. The code is required and must be unique after normalising, so a duplicate answers 409. Use percent with type percent and amount with the two fixed types. Every optional numeric field is genuinely nullable: leaving the minimum total empty means there is no minimum, which a stored zero would not say.

Parameters

Name Type Description
code required string What the shopper types; lowercased and trimmed, and unique
type optional string percent takes a share off, fixed_cart takes an amount off the cart total, fixed_product takes an amount off each covered line
One of: percent, fixed_cart, fixed_product
percent optional string or null Percentage as a decimal string, for example "10"
amount optional string or null Decimal amount in the store currency for the two fixed types
min_total optional string or null Smallest cart total this code works on
max_total optional string or null Largest cart total this code works on
currency_amounts optional object The amounts in the store's other currencies, only on a store that sells in more than one: currency code to {amount, min_total, max_total} as decimal strings in that currency's own decimal places, for example {"EUR": {"amount": "4.50", "min_total": "20.00"}}. A code with no amount in the order's currency does not apply there: a fixed coupon needs an amount, and any coupon with a minimum or maximum total in the store currency needs one in the other currency too. An empty string removes an amount and a key left out is left alone. A currency the store does not sell in or an amount that is not an amount in its currency is refused with a 422 and nothing is written.
starts_at optional integer or null Unix timestamp; null for no start date
expires_at optional integer or null Unix timestamp; null for no expiry
usage_limit optional integer or null Total redemptions allowed; null for unlimited
usage_limit_per_user optional integer or null
enabled optional boolean
individual_use optional boolean This code cannot be combined with another
basis optional string Which price a percentage comes off. `current` is what the line is worth now, sale included, and is the default; `list` is the catalogue price, so the code stacks on top of a sale. Ignored by the two fixed types, which are not measured against a price. A line never gives back more than the customer is paying for it either way.
One of: current, list
product_ids optional array of integer Narrows the code to these products; an empty list is the whole catalog
scopes optional array of object What this code is limited to. An entry is a product, a variant, a category and everything under it, or a tag, and each one either includes or excludes. No entries is the whole catalog; entries that only exclude are the whole catalog minus what they name; an exclusion always beats an inclusion. Sending this replaces the whole set, empty list included. Keys: `kind`, `ref_id`, `exclude`
free_shipping optional boolean Zeroes the postage the order was quoted, as a negative shipping line so tax on shipping comes out right. Does not touch the tax on the goods.
exclude_sale_items optional boolean A line a sale has already discounted is not eligible for this code
limit_to_items optional integer or null The discount covers at most this many units, taken cheapest first. Null for no limit.
allowed_emails optional array of string Addresses this code is reserved for. An entry is an address or a `*@domain` pattern, matched case-insensitively against the checkout email. An empty list is a code anybody may use.
conditions optional object Who the code is for and what the cart has to hold, as the nested document a sale's conditions take: {"container": "all", "children": [{"attribute": "customer_group", "operator": "eq", "value": "trade"}]}. Containers are all, any or none and they nest; a bare list is read as an `all`, and null or an empty container removes every condition. Attributes come from list_rule_attributes, and an unknown attribute or operator is refused with a 422 and nothing is written. A code that fails a condition is refused with a sentence naming it. What is in the cart is judged on the cart page, and so is the customer for a signed-in shopper; `order_country`, and the customer for a guest, wait until checkout. A money condition is in the store currency unless it names another, as on create_sale.
grants_customer_group_id optional integer or null A customer group the buyer is put into when this code is redeemed. The grant happens as the order completes, so a code on a basket that never pays grants nothing; the group is added to any the customer is already in, and none is taken away; and refunding the order gives the code back but leaves the group. Null for a code that grants nothing, which is every code unless it says otherwise. Not `group_id` — that names the campaign a generated code was minted into.
utm_campaign optional string or null An ad campaign tag. A visitor who lands on any page with `?utm_campaign=` set to this value holds the code exactly as a `?coupon=` link would, so an ad already running gets the discount without editing its URL. Matched ignoring case, stored lowercased, at most 100 characters; null or empty clears it. A code the visitor already holds or has on the cart is left alone.

Update a coupon

PATCH /api/v1/kahunacart/coupons/{id} Permission kahunacart.settings

Change a coupon's fields. Only what is sent is written, and changing the code to one another coupon already holds answers 409.

Parameters

Name Type Description
id required integer Coupon id
code optional string
type optional string
One of: percent, fixed_cart, fixed_product
percent optional string or null
amount optional string or null
min_total optional string or null
max_total optional string or null
currency_amounts optional object The amounts in the store's other currencies; see create_coupon
starts_at optional integer or null
expires_at optional integer or null
usage_limit optional integer or null
usage_limit_per_user optional integer or null
enabled optional boolean
individual_use optional boolean
basis optional string Which price a percentage comes off; see create_coupon
One of: current, list
product_ids optional array of integer
scopes optional array of object What this code is limited to. An entry is a product, a variant, a category and everything under it, or a tag, and each one either includes or excludes. No entries is the whole catalog; entries that only exclude are the whole catalog minus what they name; an exclusion always beats an inclusion. Sending this replaces the whole set, empty list included. Keys: `kind`, `ref_id`, `exclude`
free_shipping optional boolean Zeroes the postage the order was quoted, as a negative shipping line so tax on shipping comes out right. Does not touch the tax on the goods.
exclude_sale_items optional boolean A line a sale has already discounted is not eligible for this code
limit_to_items optional integer or null The discount covers at most this many units, taken cheapest first. Null for no limit.
allowed_emails optional array of string Addresses this code is reserved for. An entry is an address or a `*@domain` pattern, matched case-insensitively against the checkout email. An empty list is a code anybody may use.
conditions optional object The code's conditions as a nested document; see create_coupon. Left out leaves them as they are, null or an empty container removes them, and anything else replaces them.
grants_customer_group_id optional integer or null A customer group the buyer is put into when this code is redeemed. The grant happens as the order completes, so a code on a basket that never pays grants nothing; the group is added to any the customer is already in, and none is taken away; and refunding the order gives the code back but leaves the group. Null for a code that grants nothing, which is every code unless it says otherwise. Not `group_id` — that names the campaign a generated code was minted into.
utm_campaign optional string or null An ad campaign tag. A visitor who lands on any page with `?utm_campaign=` set to this value holds the code exactly as a `?coupon=` link would, so an ad already running gets the discount without editing its URL. Matched ignoring case, stored lowercased, at most 100 characters; null or empty clears it. A code the visitor already holds or has on the cart is left alone.

Delete a coupon

DELETE /api/v1/kahunacart/coupons/{id} Permission kahunacart.settings

Delete a discount code. The redemption log is left alone, because it is the audit trail behind orders that have already been placed and those orders outlive the coupon.

Parameters

Name Type Description
id required integer Coupon id

Fields are code, type (percent, fixed_cart or fixed_product), percent, amount, basis (current or list, read on percent only), min_total, max_total, starts_at, expires_at, usage_limit, usage_limit_per_user, enabled, individual_use and product_ids. Every optional numeric field is nullable, so an empty value clears the column rather than writing a zero.