Check whether a coupon code is valid for the authenticated user, record a coupon application, or instantly redeem a self-contained bonus coupon (free traffic / free subscription days) with no payment. These endpoints return flat, bespoke JSON — they are not wrapped in the standard {success, payload, meta, errors, description} envelope. Every response carries a top-level success boolean; failures add a machine-readable reason and a human message.
Validate does not price the order.POST /v1/coupon/validate only confirms the code is redeemable and echoes back the raw coupon record — it does not return a discount amount or a final total. Cash discounts (percent / fixed) are computed and applied server-side at checkout by POST /v1/payments when you pass coupon_code; there is no separate "quote" field here.
Restriction guard + rate limit. All three endpoints sit behind the coupons account-restriction guard and a throttle:coupon limiter of 10 requests per minute (keyed by user). Accounts flagged with COUPONS_DISABLED (e.g. multi-account risk) receive { "success": false, "reason": "coupons_disabled", "message": "Coupons are not available for your account." } from validate/apply, and exceeding the rate limit returns 429.
Validate Coupon
POST/v1/coupon/validateRequires Auth
Validate Coupon
Validate Coupon
Run all validity checks against a coupon code for the authenticated user (active, within its validity window, has remaining uses, not already used by this user, plan/currency/min-total/stackability constraints). On success returns the raw coupon record. This is a read-only check — it does NOT consume a use or record any usage.
Example request:codeplan_idorder_sumcurrency
Request Body
Name
Type
Required
Description
code
string
Required
The coupon code to validate.
plan_id
string
Optional
Plan the coupon would be applied to. When present, plan-restriction and product-scope (traffic vs ISP) checks are enforced.
order_sum
numeric
Optional
Order total, used only to enforce the coupon's min_total requirement when set.
currency
string
Optional
Order currency (e.g. "USD"). Checked against the coupon's currency when the coupon pins one.
already_applied_types
array
Optional
List of coupon type strings already applied to the order. A non-stackable coupon whose type is already present fails with reason "not_stackable".
Failure shape. When the coupon is not redeemable the response is { "success": false, "reason": "<slug>", "message": "<human text>" }. The only 404 case is reason: "not_found"; every other failure returns 400. Possible reason values: coupons_disabled, not_found, inactive, expired, usage_limit, already_used, plan_incompatible, product_incompatible, type_incompatible, min_total, currency, not_stackable.
Apply Coupon
POST/v1/coupon/applyRequires Auth
Apply Coupon
Apply Coupon
Re-run the same validity checks as validate and, on success, atomically consume one use of the coupon and record a CouponUsage row for the authenticated user. This endpoint only records the usage — it does NOT mutate any payment or balance, and it returns no coupon object, discount, or final total. Use it to mark a coupon as claimed; use POST /v1/payments with coupon_code to actually discount a purchase.
Example request:codeplan_idorder_sumcurrency
Request Body
Name
Type
Required
Description
code
string
Required
The coupon code to apply.
plan_id
string
Optional
Plan context for validation (same semantics as validate).
order_sum
numeric
Optional
Order total, for the min_total check (same as validate).
currency
string
Optional
Order currency, for the currency check (same as validate).
already_applied_types
array
Optional
Coupon type strings already applied, for the stackability check (same as validate).
activated_service
mixed
Optional
Optional free-form value stored verbatim on the CouponUsage record (for your own attribution/bookkeeping).
Failure shape. Same failure envelope as validate: { "success": false, "reason": "<slug>", "message": "<human text>" } — 404 only for not_found, otherwise 400. If two requests race past the usage limit, the loser gets reason: "usage_limit".
Redeem Coupon (Instant)
Instant redemption, no payment.POST /v1/coupon/redeem is only for coupons flagged is_instant whose type grants a self-contained bonus — free_traffic (credits GB straight to your balance) or free_subscription_period (extends an active subscription by N days). It applies the bonus in a single transaction, consumes one use, records the usage, and returns your refreshed traffic balance. Non-instant coupon types are rejected with reason: "not_instant".
POST/v1/coupon/redeemRequires Auth
Redeem Coupon (Instant)
Redeem Coupon (Instant)
Instantly redeem an is_instant coupon for the authenticated user and apply its bonus directly (free traffic credited to balance, or free subscription days added). Only the code field is read; any other body fields are ignored. free_traffic requires a positive traffic amount in the coupon; free_subscription_period requires an active subscription. Value-issuing instant coupons are additionally gated by disposable-email and multi-account risk checks.
Example request:code
Request Body
Name
Type
Required
Description
code
string
Required
The instant coupon code to redeem. This is the only field this endpoint reads.
Bonus shape by type. For a free_traffic coupon bonus is { "type": "free_traffic", "bytes": <int>, "human": "5.00 GB" }. For a free_subscription_period coupon it is { "type": "free_subscription_period", "days": <int> }, and the traffic.subscription_expires_at field reflects the extended expiry.
Failure reasons. Failures return { "success": false, "reason": "<slug>", "message": "<human text>" }. 404 for not_found; 500 for server_error; all others 400. Possible reason values: not_found, not_instant, inactive, expired, usage_limit, already_used, ineligible_account (disposable email or multi-account risk), not_first_payment, invalid_coupon_data, no_active_subscription, unsupported_type, server_error.