All Tutorials

Create and manage subscription shipping rates and delivery methods

All Tutorials

Create and manage subscription shipping rates and delivery methods

Create and manage subscription shipping rates and delivery methods

Each subscription contract has a delivery method that describes how the products in the contract will be delivered and at what price. You can update delivery methods when products are added or removed from a subscription contract.

This tutorial illustrates the calls you can make to manage shipping on subscriptions. It also provides information about the shipping rates that customers see during checkout when they buy one-time purchases or subscriptions.

Requirements

Scopes

To use the subscriptions GraphQL mutations, your app needs to request the following access scopes for a Shopify store:

  • read_own_subscription_contracts: Allow apps to read subscription contracts mutations for contracts they own.
  • write_own_subscription_contracts: Allow apps to write subscription contracts mutations for contracts they own.
  • read_shipping: Allows apps to read shipping rates.
  • write_shipping: Allows apps to write shipping rates.

Shipping rates displayed at checkout

Customers can buy one-time purchases and subscriptions when both are offered by the merchant.

Shipping for subscriptions is charged in addition to any shipping for one-time purchases. When multiple subscriptions are in the cart, shipping rates are consolidated if they share the same selling plan billing and delivery policies.

Customers can select a shipping rate for one-time purchase products in the cart if more than one rate is available. They can also view the total cost of shipping for their subscriptions and the total cost of shipping for one-time purchases:

One-time and subscriptions shipping screenshot

Limitations

  • By default, a product will have the same shipping rate whether it's bought as a one-time purchase or as part of a subscription.
  • Pickup and local delivery methods aren't supported for subscriptions. The delivery methods also don't support one-time purchases if the cart contains a subscription.
  • Only the cheapest shipping rate is available when a product is purchased as part of a subscription. Customers can't choose between multiple shipping rates.
  • Shipping rates that are specific to a selling plan group do not display in the Shipping and delivery settings in the Shopify admin. You must configure shipping rates for selling plan groups in your app.
  • When querying a new shipping rate for a subscription contract draft, the shipping rate returned depends on the following:
    • If the subscription contract doesn't have a selling plan ID, then the shipping rates from the delivery profile associated with the variant ID are displayed.
    • If the subscription contract doesn't have a selling plan or variant ID, then the shipping rates from the shop's general delivery profile are displayed.
  • If the rate is inherited from your delivery profile, then the rate name is "Shipping". If you define a subscription-specific rate using the API, then the specified name is used.

Specify free shipping for all subscriptions

If you don't want to charge shipping for all products in a selling plan group, then you can set a shipping rate amount of 0 for the selling plan.

In the following example, the deliveryProfileCreate mutation is used to include free shipping for all countries in the selling plan group. The sellingPlanGroupsToAssociate field represents the selling plan group IDs to be associated with the delivery profile.

Request

POST /admin/api/2021-01/graphql.json

mutation {
  deliveryProfileCreate(
    profile: {
      sellingPlanGroupsToAssociate: ["gid://shopify/SellingPlanGroup/2"]
      name: "Subscriptions Free Shipping"
      locationGroupsToCreate: {
        locations: "gid://shopify/Location/1"
        zonesToCreate: {
          name: "All Countries"
          countries: { restOfWorld: true }
          methodDefinitionsToCreate: {
            rateDefinition: { price: { amount: 0, currencyCode: CAD } }
            name: "Free Shipping"
          }
        }
      }
    }
  ) {
    profile {
      id
      profileLocationGroups {
        locationGroupZones(first: 1) {
          edges {
            node {
              zone {
                id
                name
                countries {
                  code {
                    restOfWorld
                  }
                }
              }
              methodDefinitions(first: 1) {
                edges {
                  node {
                    id
                    name
                    rateProvider {
                      __typename
                      ... on DeliveryRateDefinition {
                        price {
                          amount
                          currencyCode
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "deliveryProfileCreate": {
      "profile": {
        "id": "gid://shopify/DeliveryProfile/2",
        "profileLocationGroups": [
          {
            "locationGroupZones": {
              "edges": [
                {
                  "node": {
                    "zone": {
                      "id": "gid://shopify/DeliveryZone/2",
                      "name": "All Countries",
                      "countries": [
                        {
                          "code": {
                            "restOfWorld": true
                          }
                        }
                      ]
                    },
                    "methodDefinitions": {
                      "edges": [
                        {
                          "node": {
                            "id": "gid://shopify/DeliveryMethodDefinition/2",
                            "name": "Free Shipping",
                            "rateProvider": {
                              "__typename": "DeliveryRateDefinition",
                              "price": {
                                "amount": "0.0",
                                "currencyCode": "CAD"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Restrict shipping subscriptions to specific countries

You can restrict shipping subscriptions to specific countries regardless of which shipping zones you have configured in the Shopify admin. In the following example, the selling plan group includes free shipping to the North America shipping zone.

Request

POST /admin/api/2021-01/graphql.json

mutation {
  deliveryProfileCreate(
    profile: {
      sellingPlanGroupsToAssociate: ["gid://shopify/SellingPlanGroup/1"]
      name: "Subscriptions To NA"
      locationGroupsToCreate: {
        locations: "gid://shopify/Location/1"
        zonesToCreate: {
          name: "North America Shipping"
          countries: [
            { code: CA, includeAllProvinces: true }
            { code: US, includeAllProvinces: true }
            { code: MX, includeAllProvinces: true }
          ]
          methodDefinitionsToCreate: {
            name: "Free Shipping"
            rateDefinition: { price: { amount: 0, currencyCode: CAD } }
          }
        }
      }
    }
  ) {
    profile {
      id
      profileLocationGroups {
        locationGroupZones(first: 1) {
          edges {
            node {
              zone {
                id
                name
                countries {
                  name
                }
              }
              methodDefinitions(first: 1) {
                edges {
                  node {
                    id
                    name
                    rateProvider {
                      __typename
                      ... on DeliveryRateDefinition {
                        price {
                          amount
                          currencyCode
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "deliveryProfileCreate": {
      "profile": {
        "id": "gid://shopify/DeliveryProfile/3",
        "profileLocationGroups": [
          {
            "locationGroupZones": {
              "edges": [
                {
                  "node": {
                    "zone": {
                      "id": "gid://shopify/DeliveryZone/3",
                      "name": "North America Shipping",
                      "countries": [
                        {
                          "name": "Canada"
                        },
                        {
                          "name": "United States"
                        },
                        {
                          "name": "Mexico"
                        }
                      ]
                    },
                    "methodDefinitions": {
                      "edges": [
                        {
                          "node": {
                            "id": "gid://shopify/DeliveryMethodDefinition/3",
                            "name": "Free Shipping",
                            "rateProvider": {
                              "__typename": "DeliveryRateDefinition",
                              "price": {
                                "amount": "0.0",
                                "currencyCode": "CAD"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Define a flat shipping rate by country for all subscriptions

You can define a flat shipping rate per shipping zone for all subscriptions. In the following example, the selling plan group includes free shipping to Canada and specifies a $15.00 flat shipping rate for the rest of the world.

Request

POST /admin/api/2021-01/graphql.json

mutation {
  deliveryProfileCreate(
    profile: {
      sellingPlanGroupsToAssociate: ["gid://shopify/SellingPlanGroup/1"]
      name: "Subscriptions To Canada and International"
      locationGroupsToCreate: {
        locations: "gid://shopify/Location/1"
        zonesToCreate: [
          {
            name: "Canada Shipping"
            countries: [{ code: CA, includeAllProvinces: true }]
            methodDefinitionsToCreate: {
              name: "Free Shipping"
              rateDefinition: { price: { amount: 0, currencyCode: CAD } }
            }
          }
          {
            name: "Rest of World"
            countries: { restOfWorld: true }
            methodDefinitionsToCreate: {
              name: "International Shipping"
              rateDefinition: { price: { amount: 15, currencyCode: CAD } }
            }
          }
        ]
      }
    }
  ) {
    profile {
      id
      profileLocationGroups {
        locationGroupZones(first: 2) {
          edges {
            node {
              zone {
                id
                name
                countries {
                  name
                }
              }
              methodDefinitions(first: 1) {
                edges {
                  node {
                    id
                    name
                    rateProvider {
                      __typename
                      ... on DeliveryRateDefinition {
                        price {
                          amount
                          currencyCode
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "deliveryProfileCreate": {
      "profile": {
        "id": "gid://shopify/DeliveryProfile/4",
        "profileLocationGroups": [
          {
            "locationGroupZones": {
              "edges": [
                {
                  "node": {
                    "zone": {
                      "id": "gid://shopify/DeliveryZone/4",
                      "name": "Canada Shipping",
                      "countries": [
                        {
                          "name": "Canada"
                        }
                      ]
                    },
                    "methodDefinitions": {
                      "edges": [
                        {
                          "node": {
                            "id": "gid://shopify/DeliveryMethodDefinition/4",
                            "name": "Free Shipping",
                            "rateProvider": {
                              "__typename": "DeliveryRateDefinition",
                              "price": {
                                "amount": "0.0",
                                "currencyCode": "CAD"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                {
                  "node": {
                    "zone": {
                      "id": "gid://shopify/DeliveryZone/5",
                      "name": "Rest of World",
                      "countries": [
                        {
                          "name": "Rest of World"
                        }
                      ]
                    },
                    "methodDefinitions": {
                      "edges": [
                        {
                          "node": {
                            "id": "gid://shopify/DeliveryMethodDefinition/5",
                            "name": "International Shipping",
                            "rateProvider": {
                              "__typename": "DeliveryRateDefinition",
                              "price": {
                                "amount": "15.0",
                                "currencyCode": "CAD"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Update a delivery profile with a new shipping zone

You can use to the deliveryProfileUpdate mutation to add a new shipping zone. In the following example, the "United States" shipping zone is added to the delivery profile.

Request

POST /admin/api/2021-01/graphql.json

mutation {
  deliveryProfileUpdate(
    id: "gid://shopify/DeliveryProfile/4"
    profile: {
      locationGroupsToCreate: {
        locations: "gid://shopify/Location/1"
        zonesToCreate: [
          {
            name: "United States"
            countries: { code: US, includeAllProvinces: true }
            methodDefinitionsToCreate: {
              rateDefinition: { price: { amount: 0, currencyCode: CAD } }
              name: "Free Shipping"
            }
          }
        ]
      }
    }
  ) {
    profile {
      id
      profileLocationGroups {
        locationGroupZones(first: 5) {
          edges {
            node {
              zone {
                id
                name
                countries {
                  id
                  name
                  provinces {
                    id
                    name
                    code
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "deliveryProfileUpdate": {
      "profile": {
        "id": "gid://shopify/DeliveryProfile/4",
        "profileLocationGroups": [
          {
            "locationGroupZones": {
              "edges": [
                {
                  "node": {
                    "zone": {
                      "id": "gid://shopify/DeliveryZone/6",
                      "name": "United States",
                      "countries": [
                        {
                          "id": "gid://shopify/DeliveryCountry/3",
                          "name": "United States",
                          "provinces": [
                            {
                              "id": "gid://shopify/DeliveryProvince/14",
                              "name": "Alabama",
                              "code": "AL"
                            },
                            { ... },
                            {
                              "id": "gid://shopify/DeliveryProvince/71",
                              "name": "Wyoming",
                              "code": "WY"
                            }
                          ]
                        }
                      ]
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 33,
      "actualQueryCost": 17
    }
  }
}

Request a new shipping rate for a subscription contract draft

At any time, you can query a new shipping rate for a subscription contract draft. The shippingOptions field recalculates and returns the shipping options for the subscription draft using the shop’s current shipping rates.

Fetching shipping options takes some time to execute on the backend, so you must continuously poll on your app. The query returns one of the following statuses: success, failure or null. Sending the first request will return null. Subsequent requests will keep returning null until the job worker has succeeded or failed.

Request

POST /admin/api/2021-01/graphql.json

{
  subscriptionDraft(id: "gid://shopify/SubscriptionDraft/1") {
    shippingOptions(
      deliveryAddress: {
        address1: "150 Elgin St"
        city: "Ottawa"
        country: "Canada"
        countryCode: CA
        province: "Ontario"
        zip: "K2P1L4"
        firstName: "James"
        lastName: "Bond"
      }
    ) {
      __typename
      ... on SubscriptionShippingOptionResultSuccess {
        shippingOptions {
          title
          price {
            amount
            currencyCode
          }
        }
      }
      ... on SubscriptionShippingOptionResultFailure {
        message
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "subscriptionDraft": {
      "shippingOptions": {
        "__typename": "SubscriptionShippingOptionResultSuccess",
        "shippingOptions": [
          {
            "title": "International rates",
            "price": {
              "amount": "10.0",
              "currencyCode": "CAD"
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 3,
      "actualQueryCost": 3,
      "throttleStatus": {
        "maximumAvailable": 5000.0,
        "currentlyAvailable": 4997,
        "restoreRate": 250.0
      }
    }
  }
}

Update a subscription contract with a new shipping rate

When a customer updates their subscription, any changes to shipping must be updated in the subscription contract. You can make updates to the deliveryPrice and deliveryMethod fields in the subscriptionDraftUpdate mutation, and then commit the subscription draft to activate the changes.

Request

POST /admin/api/2021-01/graphql.json

mutation {
  subscriptionDraftUpdate(
    draftId: "gid://shopify/SubscriptionDraft/1"
    input: {
      deliveryPrice: 21.90
      deliveryMethod: {
        shipping: {
          address: {
            address1: "150 Elgin St"
            city: "Ottawa"
            country: "Canada"
            province: "Ontario"
            zip: "K2P1L4"
            firstName: "James"
            lastName: "Bond"
          }
          shippingOption: {
            title: "Standard"
            presentmentTitle: "Standard"
            code: "Standard"
            description: null
          }
        }
      }
    }
  ) {
    draft {
      deliveryPrice {
        amount
        currencyCode
      }
      deliveryMethod {
        __typename

        ... on SubscriptionDeliveryMethodShipping {
          address {
            address1
            city
            provinceCode
            countryCode
          }
          shippingOption {
            title
            presentmentTitle
            code
            description
          }
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}

View response

JSON response:

{
  "data": {
    "subscriptionDraftUpdate": {
      "draft": {
        "deliveryPrice": {
          "amount": "21.9",
          "currencyCode": "CAD"
       },
       "deliveryMethod": {
           "__typename": "SubscriptionDeliveryMethodShipping",
           "address": {
            "address1": "150 Elgin St",
            "city": "Ottawa",
            "provinceCode": "ON",
            "countryCode": "CA"
          },
          "shippingOption": {
            "title": "Standard",
            "presentmentTitle": "Standard",
            "code": "Standard",
            "description": null
          }
        }
      },
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 13,
      "actualQueryCost": 13
    }
  }
}

Webhooks

There are no webhooks specifically available for your app to receive information about shipping on subscriptions. However, the following webhooks are available if your app needs to react to a shop's delivery profile changes:

Webhook topic Description Payload
profiles/create Emitted when a delivery profile is first created. { id, }
profiles/update Emitted when a delivery profile is updated. { id, }
profiles/delete Emitted when a delivery profile is deleted. { id, }

Next steps