deactivate_coupon

Switch a coupon code off so no new subscriber can redeem it. A checkout that already applied it keeps its discount. Emits coupon.deactivated.

Purpose

Stop a code right now. Switching off is the safe way to retire a coupon: no new subscriber can redeem it, while the redemptions already recorded stay exactly as they are and a buyer who applied the code before you called keeps the discount they were quoted. Nothing is deleted, so activate_coupon brings it back.

Why this, and not delete_coupon

delete_coupon refuses while a checkout holding the code is still in progress, because the discount has already reached a gateway. Deactivating never refuses for that reason — it is the call to make when a code has leaked or a campaign has to end this minute. Delete later if you want the row gone.

Announces coupon.deactivated rather than a generic coupon.updated, so an automation that reacts to codes being withdrawn does not have to diff payloads to notice. Re-calling on a code that is already off leaves it unchanged; the event emits on every successful call, so key a consumer on the coupon's state rather than on counting events.

Required ability

project-coupon:update

Input schema

{
  "type": "object",
  "required": ["coupon_id"],
  "properties": {
    "coupon_id": {
      "type": "string",
      "description": "UUID of the coupon to switch off."
    }
  }
}

Output shape

{
  "data": {
    "id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
    "project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
    "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,
    "redemptions": {
      "count": 137,
      "remaining": 363,
      "exhausted": false
    },
    "starts_at": "2026-11-27T00:00:00+00:00",
    "expires_at": "2026-12-01T00:00:00+00:00",
    "plan_ids": [],
    "active": false,
    "redeemable": false,
    "created_at": "2026-11-20T09:14:02+00:00"
  }
}

The full get_coupon row, with active: false. redeemable is always false on a deactivated code; redemptions is untouched.

Example prompts

"Turn off coupon 4b9d3e08-a1f6-4275-9c83-7e01d6a2f594 immediately — it's been posted publicly."

"Pause the BLACKFRIDAY code; we'll switch it back on for the weekend."

"Stop the STAFF50 code from being used, but keep the record of who already used it."

Failure modes

  • VALIDATION_FAILED — the caller is a team member whose role lacks the team's coupon-update permission, or the project owner's tier no longer includes coupons — every coupon write passes the entitlement gate, and on this tool the refusal surfaces under error.context.coupon rather than as TEAM_TIER_REQUIRED.
  • RESOURCE_NOT_FOUND — unknown coupon_id, a coupon on another team's project, one outside the token's scope:project: allow-list, or a coupon that has been deleted.
  • AUTHENTICATION_REQUIRED — no authenticated user on the request.
  • TOKEN_MISSING_ABILITY — token lacks project-coupon:update.

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