End a discount
The discounts.delete operation: DELETE /api/v1/discounts/{id} in the REST API and the discounts_delete tool in the MCP server.
/api/v1/discounts/{id}Ends a discount now: it no longer applies to invoices from this moment on, and a discount scheduled to start
later never starts. Invoices already issued keep their discount, and a redemption already counted stays
counted. The discount stays readable with end set; ending an ended discount changes nothing.
Works for subscription and customer-level discounts. reason is recorded in the audit log.
At a glance
- REST:
DELETE /api/v1/discounts/{id} - MCP tool:
discounts_delete - Operation ID:
discounts.delete - Scope: Brand
- Permission:
subscriptions:write - Risk tier:
financial - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyoptional - Modes: Test and live
- Authentication: API key with the
subscriptions:writescope - Since: M5
Request
Path parameters
| Field | Type | Description |
|---|---|---|
id | disc_… ID |
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
reason | string | No |
Response
200 OK with a JSON object:
| Field | Type | Description |
|---|---|---|
id | disc_… ID | |
object | "discount" | |
brandId | brd_… ID | |
livemode | boolean | |
couponId | cpn_… ID | |
promotionCodeId | string or null | |
customerId | cus_… ID | |
subscriptionId | string or null | The subscription it belongs to, or null for a customer-level discount. |
start | date-time | |
end | date-time or null | When it stops applying (exclusive), or null for forever. |
redeemedAt | date-time or null | When its redemption was counted. |
status | one of scheduled, active, ended | scheduled before start, active, or ended from end on. |
createdAt | date-time | |
updatedAt | date-time |
Examples
End a discount early
DELETE /api/v1/discounts/disc_01m4tx5nj8emwbyf7y9vcf47z3
Authorization: Bearer or_test_…
Content-Type: application/json
{
"reason": "Offer withdrawn after a dispute"
}
Response (200):
{
"id": "disc_01m4tx5nj8emwbyf7y9vcf47z3",
"object": "discount",
"brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
"livemode": false,
"couponId": "cpn_01m4tx5nj8emwbyf7y9vcf47z0",
"promotionCodeId": "promo_01m4tx5nj8emwbyf7y9vcf47z2",
"customerId": "cus_01m4tx5nj8emwbyf7y9vcf47z4",
"subscriptionId": "sub_01m4tx5nj8emwbyf7y9vcf47z5",
"start": "2026-10-13T12:00:00.000Z",
"end": "2026-10-14T09:30:00.000Z",
"redeemedAt": "2026-10-13T12:00:00.000Z",
"status": "ended",
"createdAt": "2026-10-13T12:00:00.000Z",
"updatedAt": "2026-10-14T09:30:00.000Z"
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
resource_not_found | 404 | No discount with this ID is visible to the request. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
version_conflict | 409 | The discount changed at the same time; retry. | Fetch the object again and retry the change. |
permission_denied | 403 | You can't change this brand's subscriptions. | Ask an organization owner or admin for a role or scope that allows this action. |
It can also return these common errors: validation_failed, api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, scope_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.