Remove a VIP tier
DELETE /program/tiers/{tier_id}| Scope | program:write |
| Customer session token | Not accepted: call from your server with an API key |
| Rate limit class | write_shopify (limits) |
| Idempotency key | Required (idempotency) |
| MCP tool | charm_delete_tier |
Removes a tier above the entry tier (the entry tier cannot be removed). While VIP tiers are live its members re-qualify for the tiers that remain: the dry run’s member_impact shows the moves and references lists rules and campaigns that name the tier; the real call needs confirm_member_impact: true when the tier has members or anyone moves. A removal cannot be undone, and a tier added again later is a new tier: members who reach it get its e-mail and gifts again. Call with dry_run: true first.
Parameters
Section titled “Parameters”| Name | In | Type | Description |
|---|---|---|---|
tier_id | path | string | The tier’s id as GET /program lists it. |
Request body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
confirm_member_impact | boolean | Required, as true, when VIP tiers are live and the tier has members or the removal moves anyone. (optional) |
dry_run | boolean | Preview only: validate, resolve references and return the diff and summary, but write nothing. Costs no idempotency key and is limited as a read. Call with this first, show the merchant, then repeat without it. (optional) |
if_revision | integer | The program revision you last read (from GET /program or a previous write). When the program changed since, the write is refused with 409 revision_conflict instead of overwriting a concurrent admin edit. (optional) |
Response 200
Section titled “Response 200”Returns ProgramWriteResult.
| Field | Type | Description |
|---|---|---|
dry_run | boolean | True when nothing was written: the diff shows what the same call without dry_run would do. |
revision | integer | The program revision after the write (unchanged on a dry run). Send it back as if_revision on the next write. |
operation | string: create, update, delete, none | |
diff | array of FieldChange | |
summary | string or null | The admin’s one-line summary of the rule after the change. (nullable) |
earning_rule | EarningRule or null | (optional, nullable) |
reward | Reward or null | (optional, nullable) |
tier | Tier or null | (optional, nullable) |
program | Program or null | (optional, nullable) |
position | integer | Tier writes: the tier’s place in the ladder, 0 = the entry tier. (optional) |
tiers_enabled | boolean | Tier writes: whether VIP tiers are live. While they are off, adding or removing a tier moves nobody. (optional) |
member_impact | TierMemberImpact or null | (optional, nullable) |
references | array of object | Removing a tier: rules and live campaigns that name it. They keep working, but their per-tier part no longer applies to anyone. (optional) |
{ "dry_run": false, "revision": 1, "operation": "create", "diff": [ { "path": "path", "before": null, "after": null } ], "summary": "summary", "earning_rule": { "id": "id", "type": "earn", "enabled": true, "label": "Points per order", "points": 120, "points_per_currency": 120, "limit": 1, "title": "title", "title_translations": {}, "fields": {}, "summary": "summary" }, "reward": { "id": "id", "type": "earn", "enabled": true, "name": "Gold", "points_cost": 120, "discount_type": "percentage", "discount_value": 1, "code_valid_days": 1, "title": "title", "title_translations": {}, "fields": {}, "summary": "summary" }, "tier": { "id": "id", "name": "Gold", "handle": "handle", "name_translations": {}, "threshold": 1, "points_multiplier": 120, "combine": "any", "criteria": [ null ], "benefits": [ null ] }, "program": { "enabled": true, "program_name": "Rewards Club", "points_name": "points", "points_expiry": { "enabled": null, "months": null }, "reward_expiry": { "enabled": null, "code_valid_days": null }, "eligibility": { "customer_audience": null, "excluded_customer_tags": null, "excluded_product_tags": null }, "referral": { "enabled": true, "code_prefix": "REF", "discount_type": "percentage", "discount_value": 1, "minimum_purchase": 1 }, "memberships_enabled": false, "tiers_enabled": false, "earning_rules": [ null ], "redemption_rules": [ null ], "revision": 1, "updated_at": "2026-10-01T09:30:00.000Z" }, "position": 1, "tiers_enabled": false, "member_impact": { "members_evaluated": 1, "promoted": 1, "demoted": 1, "replaced": 1, "gift_codes": 1, "gifts": [ { "tier_id": null, "tier_name": null, "label": null, "codes": null } ], "per_tier": [ { "tier_id": null, "name": null, "members": null } ], "members_in_removed_tier": 1, "truncated": false }, "references": [ { "kind": "earning_rule", "id": "id", "label": "Points per order" } ]}Example
Section titled “Example”curl -X DELETE "https://charm.appfleece.app/api/v1/program/tiers/<tier_id>" \ -H "Authorization: Bearer chrm_live_..." \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{}'Errors
Section titled “Errors”unauthorized · invalid_token · insufficient_scope · access_required · not_found · validation_error · rate_limited · idempotency_conflict · shopify_unavailable
Every error body carries code, message, request_id and a doc_url pointing at the matching entry in the error catalog.