Skip to content

Redeem points for a reward

POST /customers/{customer_id}/redemptions
Scoperedemptions:write
Customer session tokenAccepted with the write scope, for the token’s own customer
Rate limit classwrite_shopify (limits)
Idempotency keyRequired (idempotency)
MCP toolcharm_create_redemption

Spends points and mints a real Shopify discount code. Rate limits on this endpoint fail closed: if usage cannot be metered, the request is refused rather than allowed. reward_id and quantity may also be sent as query parameters, for no-code clients (a Gorgias action button, say) whose only way to collect a value from a human is the query string — without it a button can only ever grant the one reward hardcoded into its body. The body wins when both are present, and the query string is part of the idempotency hash.

NameInTypeDescription
customer_idpathstringShopify customer GID (percent-encoded, e.g. gid%3A%2F%2Fshopify%2FCustomer%2F123) or the numeric customer id.
reward_id (optional)querystringAlternative to the body field of the same name.
quantity (optional)queryintegerAlternative to the body field of the same name.
FieldTypeDescription
reward_idstringA redemption rule id from /v1/rewards. A reward’s name is accepted too when exactly one enabled reward has it, so a no-code client can show readable text where it must send this value.
quantityinteger(optional)
variant_idstringFor a product reward added to the cart by your storefront: the gift variant (GID or numeric id). The response then carries line_attribute; add the variant with that line property and apply discount_code. (optional)

Returns Redemption.

FieldTypeDescription
changedtrue
variant_idstring or nullThe gift variant, when variant_id was sent. (nullable)
line_attributeobject or null(nullable)
idstring or nullRedemption id; pass to /redemptions/{redemption_id}/reverse. (nullable)
reward_idstring
reward_namestring or null(nullable)
quantitynumber
points_spentnumber
balance_afternumber or null(nullable)
discount_codestring or null(nullable)
expires_atstring or null(nullable)
credit_amountnumber or null(nullable)
{
"changed": true,
"variant_id": "44123456789",
"line_attribute": {
"key": "key",
"value": "value"
},
"id": "id",
"reward_id": "rr_10off",
"reward_name": "10% off",
"quantity": 1,
"points_spent": 120,
"balance_after": 120,
"discount_code": "CHARM-7Q2X9",
"expires_at": "2026-10-01T09:30:00.000Z",
"credit_amount": 1
}
Terminal window
curl -X POST "https://charm.appfleece.app/api/v1/customers/7712345/redemptions" \
-H "Authorization: Bearer chrm_live_..." \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reward_id":"rr_10off"}'

unauthorized · invalid_token · token_expired · insufficient_scope · access_required · not_found · validation_error · rate_limited · idempotency_conflict · shopify_unavailable · insufficient_points

Every error body carries code, message, request_id and a doc_url pointing at the matching entry in the error catalog.