coupon.deactivated
A coupon was switched off and stops being offered at checkout.
When this fires
A creator switched a coupon off via
POST /v1/projects/{project}/coupons/{coupon}/deactivate. Switching a code off in the dashboard
or through the Telegram bot does not currently emit this event — those surfaces write through the
service layer directly.
This is the safe way to retire a code, and the one Subscriby points creators at when a delete is refused. Switching off stops the code being offered immediately without touching the redemptions already recorded against it.
A checkout already in flight still completes
Switching off blocks new redemptions. A subscriber who already applied the
code and is sitting on a payment page still gets their discount — the hold was
taken before the switch. Expect a coupon.redeemed to arrive
shortly after this event, and do not treat that as an error.
Required ability
project-coupon:view — token must carry this at mint time to subscribe an endpoint to this event.
Payload
{
"id": "evt_01HX...",
"type": "coupon.deactivated",
"created_at": "2026-12-01T08:02:19Z",
"api_version": "2026-05-01",
"project_id": "7f3d1c92-8b45-4e6a-9d21-5c8e0a4b6f13",
"data": {
"coupon": {
"id": "4b9d3e08-a1f6-4275-9c83-7e01d6a2f594",
"code": "BLACKFRIDAY",
"name": "Black Friday 2026",
"discount_type": "percentage",
"discount_value": "25.0000",
"currency_id": 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",
"active": false
}
}
}Field reference
| Field | Type | Notes |
|---|---|---|
data.coupon | object | The same snapshot every coupon.* lifecycle event carries — see coupon.created for each key. active is always false here. Read back from the database, so discount_value and minimum_amount carry four decimal places here. |
Caveats
- Expiry does not emit this. A coupon that runs past its
expires_atstops applying but itsactiveflag never changes, so no event fires. If you need the expiry moment, schedule againstexpires_at. - Exhaustion does not emit this either. A coupon that runs out of uses emits
coupon.exhaustedand staysactive: true. The two are distinct states: one is a decision, the other an outcome. - Nothing is refunded or revoked. Subscribers who already redeemed keep what they paid, and their subscriptions are untouched.
Related events
coupon.activated— the paired transition.coupon.exhausted— ran out of uses rather than being switched off.coupon.deleted— the destructive alternative, which stops the code resolving.- Coupon events overview — back to family overview.
How is this guide?