Skip to main content
You can attach coupons at subscription creation time. For post-creation changes (add, remove, or schedule a future removal), use the subscription modification API.

Before you start

The coupon must be:
  • Status: active
  • Within its redeem_after / redeem_before window (if set)
  • Below its max_redemptions limit (if set)
Validation runs at association time. If any condition fails, you get a validation error before the association is created.

At subscription creation

Pass coupons in the subscription_coupons array. Each entry takes a coupon_code (the human-readable code from the coupon object), optional start_date/end_date, and an optional price_id to target a specific line item.

Subscription-level coupon

Discounts the full invoice subtotal. Omit price_id:
curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "<customer_id>",
    "plan_id": "<plan_id>",
    "start_date": "2025-01-01T00:00:00Z",
    "subscription_coupons": [
      {
        "coupon_code": "SUMMER15"
      }
    ]
  }'
start_date defaults to the subscription start date. end_date is optional: omit it to let the coupon run until its own cadence ends or the subscription cancels.

Line-item coupon

Discounts one specific price in the plan only. Set price_id to the target price:
curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "<customer_id>",
    "plan_id": "<plan_id>",
    "start_date": "2025-01-01T00:00:00Z",
    "subscription_coupons": [
      {
        "coupon_code": "USAGE10",
        "price_id": "<price_id>"
      }
    ]
  }'

Scheduled discounts via phases

Subscription phases are the recommended way to apply time-bounded coupons. Each phase has its own start_date and optional end_date. Coupons in a phase inherit those dates as their association window.

Example: introductory discount for Q1 only

curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "<customer_id>",
    "plan_id": "<plan_id>",
    "start_date": "2025-01-01T00:00:00Z",
    "phases": [
      {
        "start_date": "2025-01-01T00:00:00Z",
        "end_date": "2025-03-31T23:59:59Z",
        "subscription_coupons": [
          { "coupon_code": "Q1PROMO" }
        ]
      },
      {
        "start_date": "2025-04-01T00:00:00Z"
      }
    ]
  }'
The coupon is active during Phase 1 only. Phase 2 has no coupon, so invoices from April onwards are at full price.

Example: line-item discount scoped to a phase

curl -X POST https://api.flexprice.io/v1/subscriptions \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_id": "<customer_id>",
    "plan_id": "<plan_id>",
    "start_date": "2025-01-01T00:00:00Z",
    "phases": [
      {
        "start_date": "2025-01-01T00:00:00Z",
        "end_date": "2025-06-30T23:59:59Z",
        "subscription_coupons": [
          {
            "coupon_code": "USAGE10",
            "price_id": "<price_id>"
          }
        ]
      },
      {
        "start_date": "2025-07-01T00:00:00Z"
      }
    ]
  }'

Common scheduling patterns

GoalPhase configuration
Discount for first 3 monthsPhase 1: end_date = 3 months out, coupons: [id]. Phase 2: no coupon.
Discount starting 6 months inPhase 1: no coupon. Phase 2: start_date = 6 months in, coupons: [id].
Remove a discount on a known future datePhase 1: today to removal date with coupon. Phase 2: from removal date, no coupon.
Discount on one charge onlyIn subscription_coupons, set price_id to the target price ID.

Add or remove a coupon after subscription creation

Use the subscription modification API with type: "coupon".

Add a coupon

curl -X POST https://api.flexprice.io/v1/subscriptions/<subscription_id>/modify/execute \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "coupon",
    "coupon_params": {
      "action": "add",
      "coupon_code": "<coupon_code>",
      "start_date": "2025-06-01T00:00:00Z",
      "end_date": "2025-08-31T23:59:59Z"
    }
  }'
start_date defaults to now if omitted. end_date is optional: omit it to apply the coupon indefinitely. To target a specific line item instead of the full invoice, add subscription_line_item_id (mutually exclusive with subscription_id):
{
  "type": "coupon",
  "coupon_params": {
    "action": "add",
    "coupon_code": "<coupon_code>",
    "start_date": "2025-06-01T00:00:00Z",
    "subscription_line_item_id": "<line_item_id>"
  }
}

Remove a coupon

curl -X POST https://api.flexprice.io/v1/subscriptions/<subscription_id>/modify/execute \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "coupon",
    "coupon_params": {
      "action": "remove",
      "coupon_association_id": "<coupon_association_id>"
    }
  }'
Get the coupon_association_id from the subscription response with expand=coupon_associations. Removal affects only invoices generated after the request. Previously issued invoices are not changed.

Preview before executing

curl -X POST https://api.flexprice.io/v1/subscriptions/<subscription_id>/modify/preview \
  -H "x-api-key: <API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "coupon",
    "coupon_params": {
      "action": "add",
      "coupon_code": "<coupon_code>",
      "start_date": "2025-06-01T00:00:00Z"
    }
  }'

subscription_coupons fields (at creation)

FieldTypeRequiredDescription
coupon_codestringYesThe coupon’s code value (case-insensitive)
start_datetimestampNoWhen the association starts. Defaults to the subscription or phase start date.
end_datetimestampNoWhen the association ends. Omit for indefinite.
price_idstringNoTarget a specific line item. Omit for subscription-level.

coupon_params fields (post-creation modification)

FieldTypeRequiredDescription
actionstringYesadd or remove
coupon_codestringWhen action=addCode of the coupon to attach
coupon_association_idstringWhen action=removeID of the coupon association to detach
start_datetimestampNoWhen the association starts. Defaults to now.
end_datetimestampNoWhen the association ends. Omit for indefinite.
subscription_line_item_idstringNoTarget a specific line item. Mutually exclusive with subscription_id.

How discounts appear on invoices

Discount amounts are tracked at two levels on each line item:
FieldDescription
line_item_discountDiscount applied directly to this line item (from a line-item coupon targeting this price)
invoice_level_discountInvoice-wide coupon discount prorated to this line item
At the invoice level, total_discount is the sum of all coupon discounts across all line items. The discount terms are snapshotted when the coupon is applied, so they are preserved even if the coupon definition is later updated.

Check active coupons on a subscription

curl "https://api.flexprice.io/v1/subscriptions/<subscription_id>?expand=coupon_associations" \
  -H "x-api-key: <API_KEY>"

Validation errors

ErrorCause
coupon_not_activeCoupon is not in active status
coupon_expiredCurrent time is after redeem_before
coupon_not_yet_validCurrent time is before redeem_after
max_redemptions_reachedtotal_redemptions >= max_redemptions