Create a paid membership
POST /program/memberships| 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_create_membership |
Creates a membership off sale, for the merchant to review and put on sale in the admin. It is bought as a Shopify product: link an existing one (product) or let Charm create an unpublished draft (create_product, priced in the shop currency). Call with dry_run: true first.
Request body
Section titled “Request body”| Field | Type | Description |
|---|---|---|
name | string | In the shop’s primary language. |
name_translations | object | Other published languages; null removes one. (optional) |
product | object | (optional) |
billing_type | string: term, subscription | subscription only when subscriptions_available. Fixed once the membership has members. (optional) |
term | object | How long one purchase lasts (term). Fixed once the membership has members. (optional) |
billing_interval | object | Renewal cadence (subscription). (optional) |
grace_days | integer | (optional) |
points_multiplier | number | (optional) |
activity_window_months | integer | The multiplier holds while the member buys at least once in this many months; after a longer gap their next order earns inactive_points_multiplier, and the full one returns from the order after. 0 = always (default). (optional) |
inactive_points_multiplier | number | What a member’s next order earns after a gap longer than activity_window_months. At most points_multiplier; 1 = no extra points. (optional) |
highlight | boolean | (optional) |
show_payoff | boolean | Show when the plan pays for itself (“Pays for itself from … in orders a month”) on the storefront. (optional) |
benefits | array of object | Replaces the membership’s benefits; same shape as a tier’s (GET /program/rule-types?kind=benefit). Send an existing benefit’s id to edit it in place. (optional) |
create_product | object | Charm creates a draft (unpublished, no shipping, no stock tracking) product at this price. (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 201
Section titled “Response 201”Returns MembershipWriteResult.
| Field | Type | Description |
|---|---|---|
dry_run | boolean | |
revision | integer | |
operation | string: create, update, delete, none | |
diff | array of FieldChange | |
summary | string or null | (nullable) |
membership | Membership | |
product_created | boolean | A new draft (unpublished) product was created in Shopify for this membership. (optional) |
would_create_product | object | Dry run: the draft product a real call would create. (optional) |
product_status | string | The product’s Shopify status when it is not ACTIVE (a DRAFT product cannot be bought until published). (optional) |
gating_republish_failed | boolean | Saved, but the members-only content rules did not republish; save again to retry. (optional) |
{ "dry_run": false, "revision": 1, "operation": "create", "diff": [ { "path": "path", "before": null, "after": null } ], "summary": "summary", "membership": { "id": "id", "name": "Gold", "name_translations": {}, "enabled": true, "billing_type": "term", "term": { "unit": "DAY", "count": 1 }, "billing_interval": { "unit": "DAY", "count": 1 }, "grace_days": 1, "points_multiplier": 120, "activity_window_months": 1, "inactive_points_multiplier": 120, "highlight": false, "show_payoff": false, "product": { "id": "id", "title": "title", "variant_id": "44123456789", "variant_title": "variant title", "price": "price", "currency": "EUR" }, "benefits": [ {} ] }, "product_created": false, "would_create_product": { "title": "title", "price": 1, "status": "active" }, "product_status": "product status", "gating_republish_failed": false}Example
Section titled “Example”curl -X POST "https://charm.appfleece.app/api/v1/program/memberships" \ -H "Authorization: Bearer chrm_live_..." \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"name":"Gold"}'Errors
Section titled “Errors”unauthorized · invalid_token · insufficient_scope · access_required · 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.