All Tutorials

Bill for your app with the GraphQL Admin API

All Tutorials

Bill for your app with the GraphQL Admin API

Bill for your app with the GraphQL Admin API

The GraphQL Admin API enables app developers to process charges through Shopify's merchant invoicing system. Using this functionality delivers the best merchant experience while greatly simplifying and streamlining billing for apps.

As an app developer, you select the API resource for your billing model and include the amount to charge. Shopify handles collecting the funds and making sure you get paid.

There are three types of transactions between app developers and merchants:

  • AppPurchaseOneTime is used for items or services that are billed for only once. Each purchase needs to be approved by the merchant.
  • AppSubscription is used for items or services that are billed on a recurring basis. The subscription needs to be approved only once by the merchant, and any recurring charges are billed automatically. Usage records are billed with app subscriptions.
  • AppCredit is used to handle purchase adjustments. App credits are redeemed on future app purchases. Shopify deducts the purchase adjustment from your Partner account’s future payouts.

There are several advantages to using Shopify's Billing API:

  • The charges appear directly on the merchant’s Shopify invoice – merchants don't have to enter their credit card information to pay for apps.
  • Apps that use Shopify’s Billing API see higher free-to-paid conversion rates because charges originate directly from Shopify.
  • You automatically receive a revenue share from Shopify. Your share of the revenue is defined in the Shopify Partner revenue share agreement.
  • Shopify handles all chargebacks.

Free testing for Shopify Partner development stores

Shopify Partners are more likely to recommend apps they’ve used before. Consider allowing free app testing in Shopify Partner development stores to help increase your app sales.

You can identify a development store by querying the Shop resource. Development stores return ( { "plan_name" : "affiliate" }). Once you've identified development stores, you can add logic to your app to avoid charging them. If you make your app free to affiliate stores, then contact us to get your app listed on our Partner-friendly app list.

How billing works with the GraphQL Admin API

Creating and issuing charges to users is a multiple-step process:

  1. A merchant initiates an action that includes a charge, such as app installation, service plan upgrade, or individual purchase.

  2. The app creates a charge for the merchant, which might be an app subscription or a one-time purchase.

  3. Shopify verifies the charge and returns a confirmationUrl where the merchant is redirected to accept or decline the charge.

  4. When the merchant accepts the charge, they are redirected to the returnUrl specified by your app when it issued the charge.

  5. If the charge is declined, then Shopify redirects the merchant to Shopify admin, and provides a notification message that the app charge was declined.

Webhooks for billing

You can use the webhookSubscriptionCreate mutation to register webhooks for specific shop events. For billing, the following webhook topics are available:

Example queries

You can use the following examples to familiarize yourself with the Billing API data.

Query for an AppPurchase

Using the Billing API you can query for an individual purchase or query for multiple purchases.

Query for multiple purchases

To query for multiple purchases, you can use the currentAppInstallation type. You can use the first or last argument to specify how many purchases you want to return.

query {
  currentAppInstallation {
    oneTimePurchases(first: 2) {
      edges {
        node {
          ...on AppPurchaseOneTime {
          price {
            amount
            currencyCode
          }
          createdAt
          id
          name
          status
          test
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "currentAppInstallation": {
      "oneTimePurchases": {
        "edges": [
          {
            "node": {
              "price": {
                "amount": "100.0",
                "currencyCode": "USD"
              },
              "createdAt": "2017-11-01T19:17:09Z",
              "id": "gid://shopify/AppPurchaseOneTime/5308422",
              "name": "Super Duper Expensive action",
              "status": "ACTIVE",
              "test": true
            }
          },
          {
            "node": {
              "price": {
                "amount": "100.0",
                "currencyCode": "USD"
              },
              "createdAt": "2017-11-02T18:22:00Z",
              "id": "gid://shopify/AppPurchaseOneTime/5701638",
              "name": "Another Super Duper Expensive action",
              "status": "EXPIRED",
              "test": true
            }
          }
        ]
      }
    }
  },
  ...
}

Query for a single purchase

To query for a single purchase, you can query the node on AppPurchaseOneTime by passing the app purchase's ID as an argument.

query {
  node(id: "gid://shopify/AppPurchaseOneTime/5308422"){
    ... on AppPurchaseOneTime {
      price {
        amount
        currencyCode
      }
      createdAt
      id
      name
      status
      test
    }
  }
}

View response

JSON response:

{
  "data": {
    "node": {
      "price": {
        "amount": "100.0",
        "currencyCode": "USD"
      },
      "createdAt": "2017-11-01T19:17:09Z",
      "id": "gid://shopify/AppPurchaseOneTime/5308422",
      "name": "Super Duper Expensive action",
      "status": "ACTIVE",
      "test": true
    }
  },
  ...
}

Query for an AppSubscription

Using the Billing API you can query for an individual subscription or query for multiple subscriptions.

Query for multiple subscriptions

To query for multiple subscriptions, you can use the currentAppInstallation type. You can use the first or last argument to specify how many to return.

query {
  currentAppInstallation {
    rawSubscriptions(first: 2) {
      edges {
        node {
          lineItems {
            plan {
              pricingDetails {
                __typename
                ... on AppRecurringPricing {
                  price {
                    amount
                    currencyCode
                  }
                }
                ... on AppUsagePricing {
                  balanceUsed {
                    amount
                    currencyCode
                  }
                  cappedAmount {
                    amount
                    currencyCode
                  }
                }
              }
            }
          }
          createdAt
          id
          name
          status
          test
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "currentAppInstallation": {
      "rawSubscriptions": {
        "edges": [
          {
            "node": {
              "lineItems": [
                {
                  "plan": {
                    "pricingDetails": {
                      "__typename": "AppRecurringPricing",
                      "price": {
                        "amount": "4.99",
                        "currencyCode": "USD"
                      }
                    }
                  }
                },
                {
                  "plan": {
                    "pricingDetails": {
                      "__typename": "AppUsagePricing",
                      "balanceUsed": {
                        "amount": "0.0",
                        "currencyCode": "USD"
                      },
                      "cappedAmount": {
                        "amount": "100.0",
                        "currencyCode": "USD"
                      }
                    }
                  }
                }
              ],
              "createdAt": "2016-08-30T17:00:16Z",
              "id": "gid://shopify/AppSubscription/2816132",
              "name": "Gift Basket Plan",
              "status": "EXPIRED",
              "test": true
            }
          },
          {
            "node": {
              "lineItems": [
                {
                  "plan": {
                    "pricingDetails": {
                      "__typename": "AppRecurringPricing",
                      "price": {
                        "amount": "4.99",
                        "currencyCode": "USD"
                      }
                    }
                  }
                },
                {
                  "plan": {
                    "pricingDetails": {
                      "__typename": "AppUsagePricing",
                      "balanceUsed": {
                        "amount": "0.0",
                        "currencyCode": "USD"
                      },
                      "cappedAmount": {
                        "amount": "100.0",
                        "currencyCode": "USD"
                      }
                    }
                  }
                }
              ],
              "createdAt": "2016-09-21T19:42:43Z",
              "id": "gid://shopify/AppSubscription/2962896",
              "name": "Gift Basket Plan",
              "status": "EXPIRED",
              "test": true
            }
          }
        ]
      }
    }
  },
  ...
}

Query for a single subscription

To query for a single subscription, you can query the node on AppSubscription by passing the app purchase's ID as an argument.

query {
  node(id: "gid://shopify/AppSubscription/4019585080") {
    ...on AppSubscription {
      billingInterval
      createdAt
      currentPeriodEnd
      id
      name
      status
      test
      lineItems {
        plan {
          pricingDetails {
            ...on AppRecurringPricing {
              interval
              price {
                amount
                currencyCode
              }

            }
            ...on AppUsagePricing {
              terms
              cappedAmount {
                amount
                currencyCode

              }
              balanceUsed {
                amount
                currencyCode
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "node": {
      "billingInterval": "EVERY_30_DAYS",
      "createdAt": "2019-05-30T15:50:50Z",
      "currentPeriodEnd": null,
      "id": "gid://shopify/AppSubscription/4019585080",
      "name": "Super Duper Capped Pricing Plan",
      "status": "CANCELLED",
      "test": true,
      "lineItems": [
        {
          "plan": {
            "pricingDetails": {
              "terms": "$1 for 100 emails",
              "cappedAmount": {
                "amount": "20.0",
                "currencyCode": "USD"
              },
              "balanceUsed": {
                "amount": "0.0",
                "currencyCode": "USD"
              }
            }
          }
        }
      ]
    }
  },
  ...
}

Query for AppUsageRecords

To query for AppUsageRecords, you can use the currentAppInstallation type. You can obtain the usageRecords from the lineItems field of rawSubscriptions. You can use the first or last argument to specify how many to return.

query {
  currentAppInstallation {
    rawSubscriptions(first: 2) {
      edges {
        node {
          id
          status
          lineItems {
            id
            usageRecords(first: 5) {
              edges {
                node {
                  id
                  description
                  createdAt
                  price {
                    amount
                    currencyCode
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "currentAppInstallation": {
      "rawSubscriptions": {
        "edges": [
          {
            "node": {
              "id": "gid://shopify/AppSubscription/2816132",
              "status": "EXPIRED",
              "lineItems": [
                {
                  "id": "gid://shopify/AppSubscriptionLineItem/2816132?v=1&index=0",
                  "usageRecords": {
                    "edges": []
                  }
                },
                {
                  "id": "gid://shopify/AppSubscriptionLineItem/2816132?v=1&index=1",
                  "usageRecords": {
                    "edges": []
                  }
                }
              ]
            }
          },
          {
            "node": {
              "id": "gid://shopify/AppSubscription/2962896",
              "status": "EXPIRED",
              "lineItems": [
                {
                  "id": "gid://shopify/AppSubscriptionLineItem/2962896?v=1&index=0",
                  "usageRecords": {
                    "edges": []
                  }
                },
                {
                  "id": "gid://shopify/AppSubscriptionLineItem/2962896?v=1&index=1",
                  "usageRecords": {
                    "edges": []
                  }
                }
              ]
            }
          }
        ]
      }
    }
  },
  ...
}

Query for AppUsageRecords for a specific subscription

To query for an AppUsageRecord on a specific subscription, you can query the node on AppSubscription by passing the app subscription ID as an argument.

query {
  node(id: "gid://shopify/AppSubscription/4019585080"){
    ...on AppSubscription {
      lineItems {
        usageRecords(first: 5) {
          edges {
            node {
              id
              description
              createdAt
              price {
                amount
                currencyCode
              }
            }
          }
        }
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "node": {
      "lineItems": [
        {
          "usageRecords": {
            "edges": [
              {
                "node": {
                  "id": "gid://shopify/AppUsageRecord/14518231",
                  "description": "Super Mega Plan 1000 emails",
                  "createdAt": "2019-05-30T16:03:31Z",
                  "price": {
                    "amount": "1.0",
                    "currencyCode": "USD"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  },
  ...
}

Query for a specific AppUsageRecord by ID

To query for a specific app usage record, you can query the node on AppUsageRecord by passing the app usage record ID as an argument.

query {
  node(id: "gid://shopify/AppUsageRecord/14518231"){
    ...on AppUsageRecord {
      createdAt
      description
      id
      price {
        amount
        currencyCode
      }
    }
  }
}

View response

JSON response:

{
  "data": {
    "node": {
      "createdAt": "2019-05-30T16:03:31Z",
      "description": "Super Mega Plan 1000 emails",
      "id": "gid://shopify/AppUsageRecord/14518231",
      "price": {
        "amount": "1.0",
        "currencyCode": "USD"
      }
    }
  },
  ...
}

Next Steps