Early bird discounts live! Claim your offer

create_coupon

Create a coupon code any number of subscribers can redeem for money off. Returns the coupon immediately — no job to poll.

Purpose

Author a coupon code: one string many subscribers redeem for a discount at checkout. Distinct from an access code, which is one code for one person and grants access outright without a payment.

Synchronous — the coupon is returned in the response, and coupon.created emits once.

Discounts apply to the first payment only. Renewals charge list price, so an agent should not describe a coupon as changing a subscriber's ongoing rate.

Requires the Coupons Addon or a Growth plan. Without it the call fails with TEAM_TIER_REQUIRED rather than creating anything. Entitlement is checked again when a subscriber redeems, so a coupon created today stops applying if the addon later lapses.

Required ability

project-coupon:create

Input schema

{
  "type": "object",
  "required": ["project_id", "code", "discount_type", "discount_value"],
  "properties": {
    "project_id": {
      "type": "string",
      "description": "UUID of the project the code belongs to."
    },
    "code": {
      "type": "string",
      "description": "The code subscribers type at checkout. Letters, numbers and dashes only, 3 to 64 characters. Stored uppercase."
    },
    "name": {
      "type": "string",
      "description": "Internal label to tell your codes apart, e.g. \"Black Friday 2026\". Defaults to the code itself."
    },
    "discount_type": {
      "type": "string",
      "description": "Either \"percentage\" (works on plans in any currency) or \"fixed\" (requires currency_id, and only applies to plans priced in it)."
    },
    "discount_value": {
      "type": "number",
      "description": "For percentage, 1..99. For fixed, an amount greater than zero in the chosen currency."
    },
    "currency_id": {
      "type": "string",
      "description": "Currency UUID. Required when discount_type is \"fixed\", ignored otherwise."
    },
    "max_redemptions": {
      "type": "integer",
      "minimum": 1,
      "description": "Total uses allowed across everyone. Omit for unlimited."
    },
    "max_redemptions_per_user": {
      "type": "integer",
      "minimum": 1,
      "description": "How many times one subscriber may use the code. Defaults to 1."
    },
    "minimum_amount": {
      "type": "number",
      "description": "Only apply the code when the plan costs at least this much, in the plan's own currency."
    },
    "starts_at": {
      "type": "string",
      "description": "ISO 8601 instant the code becomes usable. Omit to start immediately."
    },
    "expires_at": {
      "type": "string",
      "description": "ISO 8601 instant the code stops working. Omit for no end date."
    },
    "plan_ids": {
      "type": "array",
      "items": { "type": "string" },
      "description": "Plan UUIDs to restrict the code to. Leave empty or omit to cover every plan in the project, including ones added later."
    },
    "active": {
      "type": "boolean",
      "description": "Whether the code is usable right away. Defaults to true."
    }
  }
}

Omitting `plan_ids` is not a safe default

An empty or absent plan_ids covers every plan in the project, now and in future. An agent asked to discount "the Premium plan" must pass that plan's UUID explicitly, or it will quietly discount the whole catalogue. Call list_plans first to resolve the id.

Output shape

{
  "data": {
    "id": "cpn_01HX...",
    "project_id": "prj_01HX...",
    "code": "BLACKFRIDAY",
    "name": "Black Friday 2026",
    "discount_type": "percentage",
    "discount_value": "25.0000",
    "currency": null,
    "duration": "once",
    "max_redemptions": 500,
    "max_redemptions_per_user": 1,
    "minimum_amount": null,
    "starts_at": "2026-11-27T00:00:00+00:00",
    "expires_at": "2026-12-01T00:00:00+00:00",
    "plan_ids": [],
    "active": true,
    "redeemable": true,
    "created_at": "2026-11-20T09:14:02+00:00"
  }
}

code comes back uppercase regardless of what was sent. discount_value is a decimal string — parse it as a decimal, not a float.

Example prompts

"Create a coupon BLACKFRIDAY in project prj_01HX... for 25% off, capped at 500 uses, running 27 November to 1 December."

"Make a $10-off code called WELCOME10 for the Starter plan only, one use per person, no expiry."

"Set up a launch code at 15% off with a $20 minimum purchase."

Failure modes

  • TEAM_TIER_REQUIRED — the creator has neither the Coupons Addon nor a Growth plan.
  • VALIDATION_FAILED — code already taken in this project (compared uppercase), code outside 3–64 characters or containing anything but letters, numbers and dashes, discount_value above 100 on a percentage, currency_id missing on a fixed coupon, expires_at not after starts_at, or a plan id that belongs to another project.
  • RESOURCE_NOT_FOUND — unknown project_id, or the project is outside the token's scope.
  • AUTHENTICATION_REQUIRED — no authenticated user on the request.
  • TOKEN_MISSING_ABILITY — token lacks project-coupon:create.
  • list_coupons — check for an existing code before creating a duplicate.
  • list_plans — resolve plan UUIDs for plan_ids.
  • Coupons API — the REST equivalent, plus update, delete and on/off.
  • Coupon Codes — the feature walkthrough.

How is this guide?

On this page

Subscriby is a product designed by you — for you.

No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request