Understanding the Shopify Subscription API
Every Shopify subscription app is built on the same platform layer: the Shopify Subscription API. Understanding how that layer works gives you the ability to evaluate subscription apps accurately, troubleshoot billing issues at the source, and make architectural decisions about your subscription program that survive an app migration.
This article breaks down the four core objects in the Subscription API, traces the lifecycle of a subscription from product configuration to recurring order, and maps exactly where the platform ends and your subscription app begins.
What is the Shopify Subscription API
The Shopify Subscription API is a set of GraphQL Admin APIs that enable apps to create and manage recurring purchase experiences. It organizes into three API families: Selling Plans (how products can be purchased on a recurring basis), Subscription Contracts (the per-customer agreement that tracks each active subscription), and Customer Payment Methods (the vaulted card or payment method charged at each renewal). Shopify supports two subscription models through these APIs: pay-per-delivery, where the customer is charged at each billing cycle, and prepaid, where the customer pays upfront for multiple deliveries. Source: Shopify subscriptions overview (https://shopify.dev/docs/apps/build/purchase-options/subscriptions).
The API handles data storage, payment vaulting, and order creation. It does not handle billing initiation, retry logic, customer communication, or subscription analytics. Those responsibilities belong entirely to the subscription app installed on your store.
The four building blocks of Shopify subscriptions
Every subscription on Shopify involves four objects that form a sequential chain. Understanding each one tells you exactly where in the system a problem originates when something breaks.
1. Selling plans (SellingPlan and SellingPlanGroup)
A SellingPlan defines how a product can be sold on a recurring basis. It contains three policy types: a BillingPolicy (how often to charge the customer), a DeliveryPolicy (how often to ship), and a PricingPolicy (what discount or price adjustment to apply). Selling plans are grouped into a SellingPlanGroup, which represents a merchant-facing selling method such as "Subscribe and save" or "Prepaid 3-month plan." Each group can contain multiple selling plans with different frequencies or pricing tiers. Source: About selling plans (https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans).
When you create a subscription plan in subZwallet, it creates the SellingPlanGroup and associates it with your selected products and variants. The plan names, discount percentages, and frequencies you configure in the subZwallet dashboard map directly to these API objects. If you need to understand what plans exist on your store at the API level, they live here.
2. Subscription contracts (SubscriptionContract)
When a customer checks out with a product that has a selling plan attached, Shopify automatically creates a SubscriptionContract. The contract stores the customer identity, line items, billing and delivery policies, next billing date, and a reference to the customer's saved payment method. Contracts have five statuses: active, paused, cancelled, expired, and failed. Any modification to a contract follows a draft-then-commit pattern: the app creates a SubscriptionDraft, makes changes, and commits the draft. Each commit generates a revision_id for deduplication. Source: About subscription contracts (https://shopify.dev/docs/apps/build/purchase-options/subscriptions/contracts).
SubZwallet tracks every contract and surfaces the status, upcoming billing date, and full history in its subscription management dashboard. When a customer or merchant changes a subscription (swap product, change frequency, update address), subZwallet handles the draft-commit cycle behind the scenes. For details on managing contracts in subZwallet, see the managing subscriptions guide (/help/manage-subscriptions).
3. Billing attempts (SubscriptionBillingAttempt)
At each billing cycle, the subscription app must create a SubscriptionBillingAttempt against the contract. This is the moment the customer's payment method is charged. If the charge succeeds, Shopify creates the fulfillment order. If it fails, the API returns an error code indicating the reason: card declined, insufficient funds, expired card, or other processor-level failures. The app is responsible for deciding what to do next: retry immediately, wait and retry later, notify the customer, or cancel the subscription.
This is where dunning logic becomes critical. Shopify provides no built-in retry mechanism. SubZwallet's dunning system automates the full recovery flow: configurable retry schedules, pre-dunning email warnings, escalation emails, and final actions (pause, cancel, or skip). See the dunning configuration guide (/help/how-to-set-up-dunning) for setup instructions.
4. Customer payment methods (CustomerPaymentMethod)
Shopify vaults the customer's payment method at checkout and returns a CustomerPaymentMethod object tied to the subscription contract. The actual card details are never exposed to the subscription app. Shopify supports card vaulting through its own payments infrastructure, and the vaulted method can be used for all future billing attempts on that contract. Customers can update their payment method through the customer portal without merchant intervention.
Subscription lifecycle: from product to recurring order
The full lifecycle of a Shopify subscription follows a deterministic path through the four building blocks. Here is the exact sequence:
- Merchant creates a selling plan (via subZwallet) and attaches it to products. This creates a SellingPlanGroup with one or more SellingPlan objects in the Shopify API.
- Customer visits the product page, selects a subscription option (e.g., "Deliver every 30 days -- save 10%"), and completes checkout.
- Shopify creates a SubscriptionContract automatically. The contract references the selling plan policies, the customer's vaulted payment method, and the line items purchased.
- At the next billing date, subZwallet creates a SubscriptionBillingAttempt. Shopify charges the vaulted payment method.
- If the charge succeeds, Shopify creates a new order and fulfillment order. SubZwallet records the successful billing cycle and triggers loyalty point accrual.
- If the charge fails, subZwallet's dunning system activates: retry on the configured schedule, send customer notifications at each stage, and apply the final action if all retries are exhausted.
- The cycle repeats at each billing interval until the contract is paused, cancelled, or expires (for prepaid subscriptions).
Platform vs. app: what Shopify handles vs. what subZwallet adds
One of the most common points of confusion for merchants evaluating subscription apps is understanding where Shopify's responsibility ends and the app's begins. This table draws the exact boundary.
Glossary of Shopify Subscription API terms
These are the technical terms you will encounter in Shopify documentation, app settings, and API error messages. Each is defined in merchant-relevant language.
Annotated example: a subscription contract lifecycle
This walkthrough traces a real subscription from creation through three billing cycles, including a failed payment recovery. The store sells a daily supplement for $45/month with a 15% subscriber discount.
Day 0 -- Customer subscribes: The customer selects "Subscribe and save 15%" on the product page and checks out. Shopify creates a SubscriptionContract with status: active, next billing date: 30 days from now, line item: Daily Supplement x1 at $38.25 ($45 minus 15%), and a reference to the customer's vaulted Visa ending in 4242.
Day 30 -- First renewal: subZwallet creates a SubscriptionBillingAttempt. Shopify charges the Visa for $38.25. Charge succeeds. Shopify creates Order #1042. SubZwallet credits 38 loyalty points to the customer's wallet and advances the next billing date to Day 60.
Day 60 -- Second renewal (payment fails): subZwallet creates the billing attempt. The charge fails with error code CARD_DECLINED. SubZwallet marks the contract as needing recovery and starts the dunning sequence: sends a pre-dunning email immediately, retries the charge on Day 63 (fails again), sends a second notification, retries on Day 66 (succeeds). Shopify creates Order #1087. The contract returns to normal billing, with the next date set to Day 90.
Day 90 -- Third renewal: Billing attempt succeeds on first try. Order #1134 created. The customer has now accumulated 114 loyalty points across three orders. SubZwallet evaluates VIP tier eligibility and promotes the customer to Silver tier, unlocking an additional 2% cashback on future renewals.
At every stage, the SubscriptionContract remains the single source of truth. The contract's status, billing history, and revision log are all accessible through the Shopify Admin API and surfaced in the subZwallet dashboard.
Known limitations of the Shopify Subscription API
The Subscription API has platform-level constraints that affect every subscription app on Shopify, not just subZwallet. Knowing these upfront prevents wasted implementation time.
- No bundle subscriptions: The API does not support Shopify product bundles as subscription line items. Bundles must be handled through workarounds (e.g., dedicated bundle variants).
- No draft order subscriptions: Selling plans cannot be added to draft orders. Subscriptions must originate from the standard checkout flow.
- No local delivery for subscriptions: Subscription orders do not support the local delivery fulfillment method. Only shipping and pickup are available.
- Selling plans deleted on uninstall: Selling plan groups and records are automatically deleted 48 hours after the creating app is uninstalled. Contracts survive but become unbillable.
- No native retry logic: Shopify returns error codes on failed billing attempts but provides no built-in retry scheduling. The subscription app must implement all recovery logic.
- Contract edits require draft-commit: There is no way to directly mutate a live contract. Every change requires creating a SubscriptionDraft, modifying it, and committing. This adds latency to bulk operations.
- Single app ownership: Each selling plan group is owned by the app that created it. A store cannot have two subscription apps managing the same selling plan group.
Next steps
If you are evaluating how subZwallet implements the Subscription API for your store, see the subZwallet Shopify subscription app overview (/shopify-subscription-app) for a full feature breakdown.
To start configuring subscriptions, begin with creating subscription plans (/help/subscription-plans), which walks through selling plan creation in the subZwallet dashboard. For ongoing subscription management, including contract modifications and customer self-service, see the managing subscriptions guide (/help/manage-subscriptions).
If failed payment recovery is a priority, the dunning configuration guide (/help/how-to-set-up-dunning) covers subZwallet's retry schedules, notification templates, and final-action rules in detail.
Ready to put the Subscription API to work on your store? Install subZwallet (/shopify-subscription-app) and start your 14-day free trial.