B2B Can’t Do Subscriptions: the Purchase-Option Wall (and the API Door Around It)
Shopify’s own B2B documentation says it in one sentence: B2B doesn’t support purchase options — subscriptions, pre-orders, try before you buy. And the community’s standard advice, “just use draft orders,” collapses the moment you open the Admin GraphQL reference: there is no selling-plan field on DraftOrder or DraftOrderLineItem. This is the map of the wall, and the three doors that actually get you recurring B2B revenue.
TL;DR: B2B does not support purchase options — subscriptions included. That’s a documented platform limitation, not a bug and not a missing app. The usual workaround, “sell the subscription through a draft order,” is impossible at the API level: neither DraftOrder nor DraftOrderLineItem has any selling-plan field in the Admin GraphQL API (latest stable 2026-07). What actually works: Door 1 — route the subscription through the company contact’s associated retail customer record on the D2C checkout; Door 2 — create the contract without any checkout via subscriptionContractCreate → subscriptionDraftCommit → subscriptionBillingAttemptCreate; Door 3 — emulate recurrence with native B2B primitives (draft orders + paymentTerms + invoice collection) driven by your own automation.
This is part 1 of our Shopify B2B in production series — the series opener. The demand evidence is a live community thread: a pure-B2B merchant (~200k SKUs, no D2C checkout at all) wants to sell maintenance bundles as quarterly subscriptions, and the only answer the thread produced was “make a draft order every month by hand.”
The problem
On a normal Shopify store, subscriptions are a solved problem: install a subscriptions app, attach a selling plan group to the product, done. On B2B, the feature simply doesn’t exist — subscription apps never appear in the B2B buying flow. The merchant in Shopify Community topic 657803 ends the thread with the manual draft-order workaround and a well-founded fear of stacking a B2B app and a subscription app that were never designed to meet each other.
This is not a merchant skill issue. It’s a documented platform boundary.
Root cause: a one-sentence wall
Shopify’s B2B developer documentation states it in the Limitations section:
“B2B doesn’t support purchase options, such as subscriptions, pre-orders, and try before you buy.”
“Purchase options” is the umbrella term, and subscriptions are implemented through selling plans: a SellingPlan defines how a product can be sold and purchased through recurring billing — when to bill, when to fulfill, what pricing adjustments to apply — and a SellingPlanGroup attaches those plans to products and variants. No purchase options in B2B means no selling plans in the B2B checkout, which means no SubscriptionContract — the object that defines recurring purchases for a customer and tracks billing attempts, payment status, and generated orders — is ever born there.
Why “use a draft order” fails at the API level
Draft orders are the standard B2B instrument: the API lets you create draft orders for company contacts to review and approve, attach paymentTerms, send an invoiceUrl. So the community reflex is “sell the subscription through a draft order.”
Open the Admin GraphQL reference for DraftOrder and DraftOrderLineItem (latest stable, 2026-07) and read the full field list: there is no selling-plan field anywhere — not on the draft order, not on its line items. You cannot smuggle a selling plan through a draft order, so a draft order cannot create a subscription contract either. The wall has no cracks on this side.
Minimal reproduction
You don’t need a Plus sandbox to confirm the wall; you need the schema. Run an introspection query against any store’s Admin GraphQL API:
{
draftLineItem: __type(name: "DraftOrderLineItem") {
fields { name }
}
draftOrder: __type(name: "DraftOrder") {
fields { name }
}
}Grep the result for sellingPlan: zero hits on either type, matching the published object reference. What you will find on DraftOrder are the B2B-native fields: paymentTerms, purchasingEntity, invoiceUrl, and the deposit-aware totals (amountDueNowSet / amountDueLaterSet — when payment terms exist, “due now” is the deposit and “due later” is the remainder).
Two checks, five minutes, wall confirmed from primary sources.
Door 1 — the D2C lane (no app required)
The B2B object model has a built-in escape hatch: a company contact is associated with a retail customer record. That customer record can buy through the normal online-store checkout, where purchase options are supported. So the subscription is sold on the D2C lane to the contact’s customer account, while the rest of the relationship stays B2B.
The trade-offs are real: that subscription order won’t carry B2B catalog pricing, won’t inherit payment terms, and won’t roll up into company-level reporting. For a pure-B2B merchant it’s a compromise lane, not a native feature — which is exactly what was told to the merchant in the thread, and what they confirmed matched their expectations.
Door 2 — the API door: build the contract without checkout
Here’s the part almost nobody mentions: a subscription contract does not have to be born at checkout. The Admin GraphQL API exposes subscriptionContractCreate, which — per the reference — “creates a subscription contract draft, which is an intention to create a new subscription.” You supply the customer, a customer payment method, and billing/delivery policies; you then finalize with subscriptionDraftCommit. No storefront involved:
# Adapted from the official mutation example (API version 2026-07)
mutation createSubscriptionContract($input: SubscriptionContractCreateInput!) {
subscriptionContractCreate(input: $input) {
draft { id }
userErrors { field message }
}
}{
"input": {
"customerId": "gid://shopify/Customer/544365967",
"currencyCode": "USD",
"nextBillingDate": "2026-09-01T09:00:00Z",
"contract": {
"status": "ACTIVE",
"paymentMethodId": "gid://shopify/CustomerPaymentMethod/b7cc6e3267aace169e516ed48be72dff",
"billingPolicy": { "minCycles": 3, "maxCycles": 12, "intervalCount": 1, "interval": "MONTH" },
"deliveryPolicy": { "intervalCount": 1, "interval": "MONTH" }
}
}
}Once the draft commits, the contract exists. Billing then runs through subscriptionBillingAttemptCreate, which charges the contract for the current (or a selected) billing cycle and creates an Order on success; failed attempts expose a processingError, and the idempotencyKey argument exists specifically to prevent duplicate charges on retries.
The fine print, all verifiable in the reference:
- Both mutations require the
write_own_subscription_contractsaccess scope, and the acting user needs themanage_orders_informationpermission. - The contract’s
customerPaymentMethodmust already exist — vaulting a card is a separate problem the API doesn’t solve for you. - The contract belongs to the customer, not the company. B2B pricing, terms, and reporting still don’t apply.
- Selling plans and their associated records are automatically deleted 48 hours after the merchant uninstalls the app that created them — if you build on this, back those records up.
Door 3 — emulate recurrence with native B2B primitives
If “real subscriptions” are impossible but “recurring charges on a schedule” is the actual business need, the native building blocks are draft orders with paymentTerms: deposit semantics via amountDueNowSet/amountDueLaterSet, an invoiceUrl to collect payment, and company association via purchasingEntity. You generate the recurring draft orders on a schedule (your own automation) instead of a billing policy doing it.
A community contributor on the same thread described one concrete assembly of this — vaulting a B2B customer’s card and using Shopify Flow’s payment-schedule trigger with a “charge vaulted payment” action to automate the collection. We flag that specific assembly as a field report: it’s practitioner testimony from the thread, not something re-verified line-by-line in the merchant documentation, so treat the exact trigger/action names as “confirm in your own admin” rather than gospel.
Checklist
- Accept the wall: B2B doesn’t support purchase options (subscriptions, pre-orders, try before you buy) — it’s documented, not a bug.
- Stop trying to attach selling plans to draft orders: neither
DraftOrdernorDraftOrderLineItemhas a selling-plan field in the Admin GraphQL API. - Decide what the business actually needs: contract semantics (Door 2), or just recurring collection (Door 3 / Door 1).
- Door 1: route the subscription through the contact’s retail customer record on the D2C checkout; document that B2B pricing/terms/reporting don’t apply.
- Door 2: use
subscriptionContractCreate→subscriptionDraftCommit→subscriptionBillingAttemptCreate; confirmwrite_own_subscription_contractsscope +manage_orders_informationpermission; solve card vaulting first; back up selling-plan data against the 48-hour uninstall deletion rule. - Door 3: model recurrence with draft orders +
paymentTerms+ invoice collection; treat community Flow recipes as field reports to verify in your own admin. - Whatever you build: a subscription order created outside B2B will not appear in company-level B2B reporting — set stakeholder expectations in writing.
Where an agent fits
Picking a door is a one-time architecture decision. The ongoing work is the recurrence itself: generating the scheduled draft orders for Door 3, watching billing attempts for processingError on Door 2, and keeping an audit trail of which customers are on which arrangement. That’s a scheduled operations loop — exactly the kind of thing a store operations agent can own: generate, verify, flag the exception to a human with the evidence attached.
Verified against Shopify’s official documentation (the B2B build guide, the SellingPlan / SubscriptionContract / SubscriptionDraft object references, and the subscriptionContractCreate / subscriptionDraftCommit / subscriptionBillingAttemptCreate mutation references, Admin GraphQL latest stable 2026-07) as of August 2026. The Flow-based vaulted-card assembly is a community field report (Shopify Community topic 657803) and is labeled as such wherever it appears above.