Creating subscriptions
Start a Shopify subscription for a customer with the Subscriptions REST API: find the product, list its priced plans, create, and wait until it's ready.
Last updated: 2026-11-09
Creating a subscription starts a Shopify subscription for a customer with a payment method they already have in Shopify. Nothing is charged when you create it; billing starts on the first billing date.
Find the product
GET /products?query= and pick a variant's product_selection.
List its plans
GET /subscription_plans with that product_selection. Each entry is a ready subscription_selection.
Create
POST /customers/{customer_id}/subscriptions with the selection, quantity and first billing date. Needs a key that can create subscriptions (subscriptions:create).
Wait until it's ready
Poll GET /subscription_creations/{id} until status is ready.
1. Find the product
Every word of the query must appear in the product's title, vendor, product type, product ID or a variant's name. Each match lists its selections, one per variant, each with a product_selection. When has_more is true, search with more specific words.
curl -G "https://api.chargezen.com/v1/products" \
--data-urlencode "query=morning coffee" \
-H "X-Chargezen-Key-Id: $CHARGEZEN_KEY_ID" \
-H "Authorization: Bearer $CHARGEZEN_SECRET"
# matches[0].selections[0].product_selection:
{ "product_record_id": "501", "provider": "shopify", "product_id": "gid://shopify/Product/8812",
"variant_id": "gid://shopify/ProductVariant/44100", "product_card_id": null }2. List its subscription plans
Send each field of the product_selection as a product_selection[…] query parameter. Leave product_card_id empty when it's null. The plans come from your Chargezen plans, priced for that variant: the first 10 plan groups with 10 plans each, with has_more when there are more. To pick one exact plan, add plan_ref[selling_plan_group_id] and plan_ref[selling_plan_id].
curl -G "https://api.chargezen.com/v1/subscription_plans" \
--data-urlencode "product_selection[product_record_id]=501" \
--data-urlencode "product_selection[provider]=shopify" \
--data-urlencode "product_selection[product_id]=gid://shopify/Product/8812" \
--data-urlencode "product_selection[variant_id]=gid://shopify/ProductVariant/44100" \
--data-urlencode "product_selection[product_card_id]=" \
-H "X-Chargezen-Key-Id: $CHARGEZEN_KEY_ID" \
-H "Authorization: Bearer $CHARGEZEN_SECRET"
{
"subscription_selections": [
{
"product_selection": { "product_record_id": "501", "provider": "shopify", "product_id": "gid://shopify/Product/8812", "variant_id": "gid://shopify/ProductVariant/44100", "product_card_id": null },
"plan_ref": { "selling_plan_group_id": "gid://shopify/SellingPlanGroup/51", "selling_plan_id": "gid://shopify/SellingPlan/71" },
"plan_name": "Monthly",
"kind": "subscription",
"group_name": "Subscribe & Save",
"billing_interval": "MONTH",
"billing_interval_count": 1,
"delivery_interval": "MONTH",
"delivery_interval_count": 1,
"price_adjustment": { "type": "percentage", "value": "10" },
"variant_price_amount": "20.00",
"currency": "USD"
}
],
"has_more": false
}3. Create the subscription
| Field | What to send |
|---|---|
subscription_selection | One entry from subscription_plans, unchanged. |
quantity | Whole number per delivery, 1 or more. |
first_billing_date | YYYY-MM-DD. Shopify may adjust the actual next billing date, which the answer returns. |
discount | Optional. { "value_type": "percentage", "value": 15 } (100 makes it free) or { "value_type": "fixed_amount", "value": 5 }, with an optional title. |
shipping_address | Optional. first_name, last_name, address1, address2, city, province_code, country_code, zip, phone; address1, city and country_code are required. Leave it out to use the customer's default address. |
curl -X POST "https://api.chargezen.com/v1/customers/8f14e45f-ceea-467f-a0e6-0e1c2f4b9d3a/subscriptions" \
-H "X-Chargezen-Key-Id: $CHARGEZEN_KEY_ID" \
-H "Authorization: Bearer $CHARGEZEN_SECRET" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"subscription_selection": { …one entry from subscription_plans, unchanged… },
"quantity": 1,
"first_billing_date": "2026-12-01"
}'
HTTP/1.1 201 Created
{
"id": "3d6f0b7e-2c41-4a8e-9b1f-5e7d2a90c4b8",
"status": "created",
"subscription_contract_id": "gid://shopify/SubscriptionContract/30971998877",
"requested_first_billing_date": "2026-12-01",
"next_billing_date": "2026-12-01T00:00:00Z",
"contract_status": "ACTIVE",
"billing_interval": "MONTH",
"billing_interval_count": 1,
"unit_price": "18.0",
"currency": "USD"
}The price is the variant's price with the plan's adjustment, then your discount. No delivery charge is added. Retry with the same Idempotency-Key and the same body to get the same answer; changing the body under that key is refused with SUBSCRIPTION_CREATION_CONFLICT.
4. Wait until it's ready
curl "https://api.chargezen.com/v1/subscription_creations/3d6f0b7e-2c41-4a8e-9b1f-5e7d2a90c4b8" \
-H "X-Chargezen-Key-Id: $CHARGEZEN_KEY_ID" \
-H "Authorization: Bearer $CHARGEZEN_SECRET"
{
"status": "ready",
"subscription_contract_id": "gid://shopify/SubscriptionContract/30971998877",
"subscription_ref": { "type": "customer_subscription_contract", "id": "48390" },
"observed_at": "2026-11-09T16:22:40.118204Z"
}status is pending until Chargezen has stored the new subscription, then ready with its subscription_ref. Use that id to read or change it.
When nothing is created
| Code | What happened |
|---|---|
SUBSCRIPTION_SELECTION_STALE | The plan or the price changed since you listed plans. List them again. |
SUBSCRIPTION_PAYMENT_METHOD_REQUIRED | The customer has no payment method in Shopify. They need to add one through Shopify. |
When Shopify refuses a creation, such as for a missing payment method, repeating it with the same Idempotency-Key returns the same answer. Once the cause is fixed, send a new request with a new key. Plans with a fixed price, a trial, a limited number of cycles, and bundle plans aren't listed; asking for one by plan_ref answers SUBSCRIPTION_PLAN_UNSUPPORTED.
The API creates Chargezen and Shopify subscriptions only.
Related Articles
Need more help? Contact support