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:
A merchant initiates an action that includes a charge, such as app installation, service plan upgrade, or individual purchase.
The app creates a charge for the merchant, which might be an app subscription or a one-time purchase.
Shopify verifies the charge and returns a
confirmationUrl
where the merchant is redirected to accept or decline the charge.When the merchant accepts the charge, they are redirected to the
returnUrl
specified by your app when it issued the charge.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:
- APP_PURCHASE_ONE_TIME_UPDATE - A webhook is triggered when the
status
of anAppPurchaseOneTime
is changed. - APP_SUBSCRIPTIONS_UPDATE - A webhook is triggered when the
status
of anAppSubscription
is changed.
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
}
}
}
}
}
}
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
}
}
}
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 {
allSubscriptions(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
}
}
}
}
}
JSON response:
{
"data": {
"currentAppInstallation": {
"allSubscriptions": {
"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
}
}
}
}
}
}
}
}
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 allSubscriptions
. You can use the first
or last
argument to specify how many to return.
query {
currentAppInstallation {
allSubscriptions(first: 2) {
edges {
node {
id
status
lineItems {
id
usageRecords(first: 5) {
edges {
node {
id
description
createdAt
price {
amount
currencyCode
}
}
}
}
}
}
}
}
}
}
JSON response:
{
"data": {
"currentAppInstallation": {
"allSubscriptions": {
"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
}
}
}
}
}
}
}
}
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
}
}
}
}
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
- Learn how to best identify your billing model and implement the Billing API.