Skip to content

Change a VIP tier

PATCH /program/tiers/{tier_id}
Scopeprogram:write
Customer session tokenNot accepted: call from your server with an API key
Rate limit classwrite_shopify (limits)
Idempotency keyRequired (idempotency)
MCP toolcharm_update_tier

Changes a tier’s name, bar (criteria), points multiplier or benefits; keys you omit stay. While VIP tiers are live a new bar moves members: the dry run’s member_impact shows the moves and the real call then needs confirm_member_impact: true. The first tier is the entry tier and takes no bar. benefits replaces the tier’s list: send every benefit to keep, with its id to edit one in place, or without an id to add one (types and config per GET /program/rule-types?kind=benefit). To add or remove a tier use POST /program/tiers and DELETE /program/tiers/{tier_id}; switching tiers on stays in the admin. Call with dry_run: true first.

NameInTypeDescription
tier_idpathstringThe tier’s id as GET /program lists it.
FieldTypeDescription
namestringIn the shop’s primary language. (optional)
name_translationsobjectThe name in other published languages; null removes one, omitted ones stay. A value for the primary language sets name. (optional)
points_multipliernumber1 = base rate; 1.5 = 50% more points. (optional)
criteriaarray of objectThe bar to reach the tier: { type: "points" | "spend" | "orders" | "referrals", threshold } or { type: "tag", value }, each type at most once. (optional)
combinestring: any, allHow several criteria combine. Defaults to any. (optional)
benefitsarray of object(optional)
confirm_member_impactbooleanRequired, as true, when VIP tiers are live and a new bar moves members. Run a dry run first and show the merchant member_impact. (optional)
dry_runbooleanPreview 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_revisionintegerThe 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)

Returns ProgramWriteResult.

FieldTypeDescription
dry_runbooleanTrue when nothing was written: the diff shows what the same call without dry_run would do.
revisionintegerThe program revision after the write (unchanged on a dry run). Send it back as if_revision on the next write.
operationstring: create, update, delete, none
diffarray of FieldChange
summarystring or nullThe admin’s one-line summary of the rule after the change. (nullable)
earning_ruleEarningRule or null(optional, nullable)
rewardReward or null(optional, nullable)
tierTier or null(optional, nullable)
programProgram or null(optional, nullable)
positionintegerTier writes: the tier’s place in the ladder, 0 = the entry tier. (optional)
tiers_enabledbooleanTier writes: whether VIP tiers are live. While they are off, adding or removing a tier moves nobody. (optional)
member_impactTierMemberImpact or null(optional, nullable)
referencesarray of objectRemoving 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"
}
]
}
Terminal window
curl -X PATCH "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 '{}'

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.