Skip to content

Discount codes

Discount codes are yours — you define them for your own end customers. They never change what you pay Linra: your commission, VAT, and settlement are computed exactly as if the order had no discount at all. A code is purely a display/reporting overlay on top of the price Linra computes.

Terminal window
POST /api/v1/scent/discount-codes
{
"code": "SAVE10",
"discountType": "Percent",
"value": 10,
"productScope": "All"
}
{
"state": "CREATED",
"payload": {
"id": "5b2e...",
"code": "SAVE10",
"discountType": "Percent",
"value": 10,
"isActive": true,
"productScope": "All",
"usageCount": 0
}
}

The code string is immutable once created — there is no rename operation. To retire a typo’d or campaign-ended code, deactivate it and create a new one:

Terminal window
PATCH /api/v1/scent/discount-codes/{id}
{ "discountType": "Percent", "value": 10, "isActive": false, "productScope": "All" }

Every field on the update call is a full replace (state your complete desired settings each time) — except code, which the update body has no field for at all.

Guardrails you can set at create/update time

Section titled “Guardrails you can set at create/update time”
Field Meaning
validFrom / validTo Optional validity window. Both null = open-ended.
totalUsageCap Optional cap on total redemptions across all customers.
perCustomerCap null (no limit) or exactly 1 (at most one redemption per customerRef, ever). No other value is accepted in v1.
productScope + scopedVariantIds All (your whole catalog) or VariantList (an explicit set of variant IDs).
minOrderValue Optional minimum cart total (VAT-inclusive) for the code to apply.

A code is scoped to you — two partners may both register SAVE10 independently.

Before checkout, check whether a code currently applies — this never consumes a use:

Terminal window
POST /api/v1/scent/cart/discount-code/validate
{ "code": "SAVE10" }
{
"state": "SUCCESS",
"payload": {
"valid": true,
"reason": null,
"originalTotal": 200.00,
"discountAmount": 20.00,
"discountedTotal": 180.00
}
}

(Worked from a cart holding 2 units at 100 SAR each — a 10% code computes a 20 SAR discount, Math.Round-ed to 4 decimal places and never exceeding the cart total.)

If you’ve requested a supported non-SAR display currency via X-Partner-Currency, the response additionally carries originalTotalDisplay/ discountAmountDisplay/discountedTotalDisplay — the same additive display-currency pattern used everywhere else in the API, alongside the canonical SAR figures above (never replacing them). The code’s own configured value (e.g. a fixed-amount discount) is always SAR-denominated regardless of your display currency — only the computed result shown back here converts for display.

If the code doesn’t apply, valid is false and reason is one of:

Reason Meaning
EMPTY_CART Your cart has no lines.
NOT_FOUND No such code for your account.
INACTIVE The code exists but is deactivated.
NOT_YET_VALID / EXPIRED Outside the code’s validity window.
BELOW_MIN_ORDER_VALUE Cart total is below the code’s minOrderValue.
PRODUCT_SCOPE_MISMATCH None of your cart lines are in the code’s VariantList scope.
CAP_REACHED The total-usage cap has been reached (advisory here — see below).
ALREADY_USED_BY_CUSTOMER This customerRef has already redeemed a per-customer-capped code.

originalTotal/discountAmount/discountedTotal are display figures only — they never change what you are actually charged.

Pass the SAME code on the order-create call:

Terminal window
POST /api/v1/orders/scent
{
"partnerId": "...",
"externalReference": "order-42",
"discountCode": "SAVE10",
"shippingAddress": { "...": "..." }
}
{
"state": "CREATED",
"payload": {
"id": "...",
"appliedDiscountCode": "SAVE10",
"discountAmount": 20.00,
"...": "..."
}
}

The code is re-validated at this point (state may have changed since you last validated it — the usage cap in particular is only advisory at validate time and authoritative here). If it no longer applies, order creation is rejected with VALIDATION_DISCOUNT_CODE_INVALID, VALIDATION_DISCOUNT_CODE_EXPIRED, VALIDATION_DISCOUNT_CODE_CAP_REACHED, or BUSINESS_DISCOUNT_CODE_ALREADY_USED_BY_CUSTOMER — never a silent downgrade to “no discount applied.” A use is only ever counted when the order itself is actually created: a failed or cancelled checkout never burns a redemption.

How charging works (the part that never changes)

Section titled “How charging works (the part that never changes)”

However a code is defined, it has zero effect on:

  • what you pay Linra (wholesale amount, or your commission in commission mode),
  • VAT computation and settlement,
  • the margin-floor guard.

Those are all computed on the undiscounted price, exactly as if no code were applied. If you want to fund a promotion, it comes out of your own margin — Linra has no stake in it either way.

GET /api/v1/scent/discount-codes and GET /api/v1/scent/discount-codes/{id} include a running usageCount so you can track redemption progress without a separate report. A code that has never been redeemed (usageCount == 0) can be deleted outright (DELETE /api/v1/scent/discount-codes/{id}); once it has at least one redemption, delete is rejected with BUSINESS_DISCOUNT_CODE_IN_USE — deactivate it instead, so the historical order data referencing it stays meaningful.