Check if a coupon code is valid for a specific user and purchase amount before applying it. The response shows whether the coupon is eligible, the calculated discount, and the final price—or the reasons why the coupon cannot be used.
POST/v2/projects/{project_id}/coupons/validate
Authorization
Bearer API KeyRequired
API key scope:coupons:read (required for restricted keys).
Path Parameters
project_idstringrequired
The unique identifier of the project.
Request Body
coupon_idstring
Coupon UUID. Either coupon_id or code is required.
codestring
Coupon code (case-insensitive). Either code or coupon_id is required.
amountstring|numberrequired
Current checkout amount to evaluate. Prefer an exact decimal string; JSON numbers must satisfy the numeric precision limits. Used for inclusive minimum/maximum spend checks.
currencystringrequired
The currency of the amount (e.g., USD).
user_idstringrequired
Customer platform user ID. Required for project API-key requests; used to evaluate per-user limits and audience scope.
plan_idstring
Plan being purchased, used for plan_scope checks. Omit for top-up previews.
is_renewalboolean
Whether the purchase is a renewal, used for renewal_constraint.
is_churnedboolean
Whether the user is churned, used for renewal_constraint.
Spend limits compare this request's amount and currency with the coupon's configured bounds. An amount equal to either bound qualifies. A mismatched currency does not trigger conversion. Failed checks can return eligible: false with MIN_SPEND_NOT_MET, MAX_SPEND_EXCEEDED, MIN_SPEND_CURRENCY_MISMATCH or MAX_SPEND_CURRENCY_MISMATCH in reasons.
The amount follows the decimal input rules. Discounts are calculated with decimal arithmetic and rounded to the currency's precision. A discount covering the entire checkout leaves exactly "0". A positive remainder below the smallest currency unit makes the coupon ineligible with REMAINDER_BELOW_MINOR_UNIT and applied_amount: "0"; for example, "10.006" USD minus a "10" discount cannot leave a payable "0.006" USD balance.
An unsupported currency returns eligible: false with CURRENCY_UNSUPPORTED and applied_amount: "0". If the lifetime-revenue calculation exceeds the backend's aggregation limit, a revenue-dependent rule returns LIFETIME_REVENUE_NOT_MATCHED rather than treating unknown revenue as zero. These are eligibility results under HTTP 200, not successful coupon applications. The schema permits nullable applied_amount, but these two currency-related refusals return "0"; final_amount remains the original amount, not the rejected remainder.