Manage orders for prepaid subscriptions
When an order is created by Shopify, and delivery anchors exist, the order contains delayed fulfillment orders for prepaid items. This tutorial covers some common order management scenarios that relate to fulfillment orders and subscription contracts.
Keeping orders and subscription contracts in sync
Changes to prepaid subscription contracts aren't automatically reflected on the associated orders. For example, when a customer updates their address for a prepaid subscription in an app, their address isn't automatically updated in the order. To support this use case, you need to make calls to SubscriptionContractUpdate and subscriptionDraftUpdate to update the delivery method address on the contract. You also need to call OrderUpdate to update the shipping address on the order.
Updating the subscription contract
Before you can update the subscription draft, you need to get a draft ID.
Use the subscriptionContractUpdate
mutation and supply the subscription contract ID. The response includes a draft ID.
Example request:
POST /admin/api/2021-01/graphql.json
mutation {
subscriptionContractUpdate(
contractId: "gid://shopify/SubscriptionContract/22"
) {
draft {
id
}
userErrors {
field
message
}
}
}
JSON response:
{
"data": {
"subscriptionContractUpdate": {
"draft": {
"id": "gid://shopify/SubscriptionContract/22"
},
"userErrors": []
}
},
...
}
Updating the subscription draft
You can call the subscriptionDraftUpdate
mutation to make changes to a subscription draft. In the following example, the delivery method address is changed.
Example request
POST /admin/api/2021-01/graphql.json
mutation subscriptionDraftUpdate($draftId: ID!, $input: SubscriptionDraftInput!) {
subscriptionDraftUpdate(draftId: $draftId, input: $input) {
draft {
id
}
userErrors {
code
field
message
}
}
}
Input:
{
"draftId": "gid://shopify/SubscriptionDraft/2654264",
"input": {"deliveryMethod": {
"shippingAddress": {
"address1": "123 Fake Street",
"city": "Vancouver",
"countryCode": "CA",
"provinceCode": "BC",
"zip": "V6Z0A3",
"lastName": "Doe"
}
}
}
}
}
JSON response:
{
"data": {
"subscriptionDraftUpdate": {
"draft": {
"id": "gid://shopify/SubscriptionDraft/2654264"
},
"userErrors": []
}
},
...
}
Updating the order
You can call the OrderUpdate mutation to make changes to a order. The following example updates the order to include a shipping address.
Example request
POST /admin/api/2021-01/graphql.json
mutation orderUpdate($input: OrderInput!) {
orderUpdate(input: $input) {
order {
id
}
userErrors {
field
message
}
}
}
Input:
{
"input": {
"id": "gid://shopify/Order/2067697074232",
"shippingAddress": {
"address1": "123 Fake Street",
"city": "Vancouver",
"countryCode": "CA",
"provinceCode": "BC",
"zip": "V6Z0A3",
"lastName": "Doe"
}
}
}
JSON response:
{
"data": {
"orderUpdate": {
"order": {
"id": "gid://shopify/Order/2067697074232"
},
"userErrors": []
}
},
...
}
Managing cancellations
The cancellation of orders related to subscription contracts doesn't automatically cancel these subscription contracts. It's recommended that apps subscribe to the orders/cancel
webhook and communicate with merchants when subscription contract orders are cancelled, so that merchants know that the subscription contract hasn't also been cancelled.
Subscription cancellation through a customer portal
When a customer cancels a subscription order through the customer portal, apps must notify the merchant of this cancellation. If the cancellation is initiated through the app, then the app must handle the associated refunds. This applies to both prepaid and subscribe-and-save subscriptions.
Order tagging
Merchants often identify and filter subscription orders in the Shopify admin. To tag orders for subscriptions from your app, you can use the /orders
endpoint in REST or send a GraphQL Order mutation. The following example adds tags to a specific order using the order ID:
Automatic fulfillment
Scheduled fulfillment orders aren't eligible for automatic fulfillment. However, if a prepaid subscription order is created with its first fulfillment order set to the OPEN
state, then the fulfillment order is automatically fulfilled.
In the Set the cutoff date for a selling plan example, the customer checks out on January 8 with an item from a selling plan that has its pre-anchor behaviour set to ASAP
. The first fulfillment order (with the fulfillAt
date of Jan 8) is then fulfilled right away.
Order CSV export
Apps that use CSV exports to manage fulfillments can rely on the value of lineItem.fulfillableQuantity
to determine which orders are ready to fulfill. This is because SCHEDULED
fulfillment orders aren't included in the calculation of the order lineItem.fulfillableQuantity
.
For example, consider a fulfillment order scheduled to ship on January 15. Before January 15, lineItem.fulfillableQuantity
is set to 0. After January 15, lineItem.fulfillableQuantity
is set to 1. Then, after the item is fulfilled, lineItem.fulfillableQuantity
is set back to 0.
Order webhooks
The following webhooks are useful for apps that manage fulfillment orders for merchants:
orders/create
- Get notified when an order is created. Apps will need to check the line items and their selling plan application to determine whether this is a subscription order that they own.orders/updated
- Get notified when an order with a subscription contract is updated, or when the scheduled fulfillment order is transitioned toOPEN
state. For example, this could be important for address updates.orders/cancelled
- Get notified when an order is cancelled. This can be useful for apps to ensure contracts get cancelled as well (if that's the merchants intention).refunds/create
- Get notified when a refund is created. This can be useful for apps to ensure contracts get updated as well (if that's the merchants intention).
Next steps
- Create and manage fulfillments for prepaid subscriptions: Learn the calls you can make to manage fulfillments on subscriptions.
- Handling advanced scenarios for subscription-based fulfillment orders: Learn the calls you can make to manage advanced fulfillment scenarios for subscriptions.