---
title: Billing
description: >-
Contains function used to bill merchants for your app with the Billing API.
This object is returned on authenticated Admin requests.
> Note: [Managed App Pricing](/docs/apps/launch/billing/managed-pricing) is
now available. Define your app’s pricing plans directly in the Shopify Partner
Dashboard, without needing to use the Billing API.
api_version: v1 latest
api_name: shopify-app-react-router
source_url:
html: 'https://shopify.dev/docs/api/shopify-app-react-router/latest/apis/billing'
md: 'https://shopify.dev/docs/api/shopify-app-react-router/latest/apis/billing.md'
---
# Billing
Contains function used to bill merchants for your app with the Billing API.
This object is returned on authenticated Admin requests.
**Note:** \Managed App Pricing\ is now available. Define your app’s pricing plans directly in the Shopify Partner Dashboard, without needing to use the Billing API.
## billing
Provides utilities that apps can use to request billing for the app using the Admin API.
* **cancel**
**(options: CancelBillingOptions) => Promise\**
**required**
Cancels an ongoing subscription, given its ID.
* **check**
**\>(options?: Options) => Promise\**
**required**
Checks if the shop has an active payment for any plan defined in the `billing` config option.
* **createUsageRecord**
**(options: CreateUsageRecordOptions) => Promise\**
**required**
Creates a usage record for an app subscription.
* **request**
**(options: RequestBillingOptions\) => Promise\**
**required**
Requests payment for the plan.
* **require**
**(options: RequireBillingOptions\) => Promise\**
**required**
Checks if the shop has an active payment for any plan defined in the `billing` config option.
* **updateUsageCappedAmount**
**(options: UpdateUsageCappedAmountOptions) => Promise\**
**required**
Updates the capped amount for a usage billing plan.
### CancelBillingOptions
* isTest
Whether to use the test mode. This prevents the credit card from being charged.
```ts
boolean
```
* prorate
Whether to issue prorated credits for the unused portion of the app subscription. There will be a corresponding deduction (based on revenue share) to your Partner account. For example, if a $10.00 app subscription (with 0% revenue share) is cancelled and prorated half way through the billing cycle, then the merchant will be credited $5.00 and that amount will be deducted from your Partner account.
```ts
boolean
```
* subscriptionId
The ID of the subscription to cancel.
```ts
string
```
```ts
export interface CancelBillingOptions {
/**
* The ID of the subscription to cancel.
*/
subscriptionId: string;
/**
* Whether to issue prorated credits for the unused portion of the app subscription. There will be a corresponding
* deduction (based on revenue share) to your Partner account. For example, if a $10.00 app subscription
* (with 0% revenue share) is cancelled and prorated half way through the billing cycle, then the merchant will be
* credited $5.00 and that amount will be deducted from your Partner account.
*/
prorate?: boolean;
/**
* Whether to use the test mode. This prevents the credit card from being charged.
*/
isTest?: boolean;
}
```
### CheckBillingOptions
* isTest
Whether to include charges that were created on test mode. Test shops and demo shops cannot be charged.
```ts
boolean
```
* plans
The plans to check for. Must be one of the values defined in the \`billing\` config option.
```ts
(keyof Config["billing"])[]
```
```ts
export interface CheckBillingOptions
extends Omit {
/**
* The plans to check for. Must be one of the values defined in the `billing` config option.
*/
plans?: (keyof Config['billing'])[];
}
```
### CreateUsageRecordOptions
* description
The description of the app usage record.
```ts
string
```
* idempotencyKey
```ts
string
```
* isTest
Whether to use the test mode. This prevents the credit card from being charged.
```ts
boolean
```
* price
The price of the app usage record.
```ts
{ amount: number; currencyCode: string; }
```
* subscriptionLineItemId
```ts
string
```
```ts
export interface CreateUsageRecordOptions {
/**
* The description of the app usage record.
*/
description: string;
/**
* The price of the app usage record.
*/
price: {
/**
* The amount to charge for this usage record.
*/
amount: number;
/**
* The currency code for this usage record.
*/
currencyCode: string;
};
/**
* Whether to use the test mode. This prevents the credit card from being charged.
*/
isTest: boolean;
/*
* Defines the usage pricing plan the merchant is subscribed to.
*/
subscriptionLineItemId?: string;
/*
* A unique key generated to avoid duplicate charges.
*/
idempotencyKey?: string;
}
```
### RequestBillingOptions
* isTest
Whether to use the test mode. This prevents the credit card from being charged. Test shops and demo shops cannot be charged.
```ts
boolean
```
* plan
The plan to request. Must be one of the values defined in the \`billing\` config option.
```ts
keyof Config["billing"]
```
* returnUrl
The URL to return to after the merchant approves the payment.
```ts
string
```
```ts
export interface RequestBillingOptions
extends Omit {
/**
* The plan to request. Must be one of the values defined in the `billing` config option.
*/
plan: keyof Config['billing'];
/**
* Whether to use the test mode. This prevents the credit card from being charged. Test shops and demo shops cannot be charged.
*/
isTest?: boolean;
/**
* The URL to return to after the merchant approves the payment.
*/
returnUrl?: string;
}
```
### RequireBillingOptions
* isTest
Whether to include charges that were created on test mode. Test shops and demo shops cannot be charged.
```ts
boolean
```
* onFailure
How to handle the request if the shop doesn't have an active payment for any plan.
```ts
(error: any) => Promise
```
* plans
The plans to check for. Must be one of the values defined in the \`billing\` config option.
```ts
(keyof Config["billing"])[]
```
```ts
export interface RequireBillingOptions
extends Omit {
/**
* The plans to check for. Must be one of the values defined in the `billing` config option.
*/
plans: (keyof Config['billing'])[];
/**
* How to handle the request if the shop doesn't have an active payment for any plan.
*/
onFailure: (error: any) => Promise;
}
```
### UpdateUsageCappedAmountOptions
* cappedAmount
The maximum charge for the usage billing plan.
```ts
{ amount: number; currencyCode: string; }
```
* subscriptionLineItemId
The subscription line item ID to update.
```ts
string
```
```ts
export interface UpdateUsageCappedAmountOptions {
/**
* The subscription line item ID to update.
*/
subscriptionLineItemId: string;
/**
* The maximum charge for the usage billing plan.
*/
cappedAmount: {
/**
* The amount to update.
*/
amount: number;
/**
* The currency code to update.
*/
currencyCode: string;
};
}
```
Examples
### Examples
* #### Cancelling a subscription
##### Description
Use the \`billing.cancel\` function to cancel an active subscription with the id returned from \`billing.require\`.
##### /app/routes/cancel-subscription.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const billingCheck = await billing.require({
plans: [MONTHLY_PLAN],
onFailure: async () => billing.request({ plan: MONTHLY_PLAN }),
});
const subscription = billingCheck.appSubscriptions[0];
const cancelledSubscription = await billing.cancel({
subscriptionId: subscription.id,
isTest: true,
prorate: true,
});
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
[ANNUAL_PLAN]: {
lineItems: [
{
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Check what billing plans a merchant is subscribed to
##### Description
Use billing.check if you want to determine which plans are in use. Unlike \`require\`, \`check\` does notthrow an error if no active billing plans are present.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const { hasActivePayment, appSubscriptions } = await billing.check({
plans: [MONTHLY_PLAN],
isTest: false,
});
console.log(hasActivePayment);
console.log(appSubscriptions);
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
[ANNUAL_PLAN]: {
lineItems: [
{
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Check for payments without filtering
##### Description
Use billing.check to see if any payments exist for the store, regardless of whether it's a test ormatches one or more plans.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const { hasActivePayment, appSubscriptions } = await billing.check();
// This will be true if any payment is found
console.log(hasActivePayment);
console.log(appSubscriptions);
};
```
* #### Creating a usage record
##### Description
Create a usage record for the active usage billing plan
##### /app/routes/create-usage-record.ts
```typescript
import { ActionFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const action = async ({ request }: ActionFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const chargeBilling = await billing.createUsageRecord({
description: "Usage record for product creation",
price: {
amount: 1,
currencyCode: "USD",
},
isTest: true,
});
console.log(chargeBilling);
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const USAGE_PLAN = 'Usage subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[USAGE_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Usage,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Using a custom return URL
##### Description
Change where the merchant is returned to after approving the purchase using the \`returnUrl\` option.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
onFailure: async () => billing.request({
plan: MONTHLY_PLAN,
isTest: true,
returnUrl: 'https://admin.shopify.com/store/my-store/apps/my-app/billing-page',
}),
});
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
[ANNUAL_PLAN]: {
lineItems: [
{
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Overriding plan settings
##### Description
Customize the plan for a merchant when requesting billing. Any fields from the plan can be overridden, as long as the billing interval for line items matches the config.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
onFailure: async () => billing.request({
plan: MONTHLY_PLAN,
isTest: true,
trialDays: 14,
lineItems: [
{
interval: BillingInterval.Every30Days,
discount: { value: { percentage: 0.1 } },
},
],
}),
});
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
[ANNUAL_PLAN]: {
lineItems: [
{
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Requesting billing right away
##### Description
Call \`billing.request\` in the \`onFailure\` callback to immediately redirect to the Shopify page to request payment.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs } from "react-router";
import { authenticate, MONTHLY_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.require({
plans: [MONTHLY_PLAN],
isTest: true,
onFailure: async () => billing.request({ plan: MONTHLY_PLAN }),
});
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Redirect to a plan selection page
##### Description
When the app has multiple plans, create a page in your App that allows the merchant to select a plan. If a merchant does not have the required plan you can redirect them to page in your app to select one.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { LoaderFunctionArgs, redirect } from "react-router";
import { authenticate, MONTHLY_PLAN, ANNUAL_PLAN } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { billing } = await authenticate.admin(request);
const billingCheck = await billing.require({
plans: [MONTHLY_PLAN, ANNUAL_PLAN],
isTest: true,
onFailure: () => redirect('/select-plan'),
});
const subscription = billingCheck.appSubscriptions[0];
console.log(`Shop is on ${subscription.name} (id ${subscription.id})`);
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const MONTHLY_PLAN = 'Monthly subscription';
export const ANNUAL_PLAN = 'Annual subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[MONTHLY_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Every30Days,
}
],
},
[ANNUAL_PLAN]: {
lineItems: [
{
amount: 50,
currencyCode: 'USD',
interval: BillingInterval.Annual,
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
* #### Updating the capped amount for a usage billing plan
##### Description
Update the capped amount for the usage billing plan specified by \`subscriptionLineItemId\`.
##### /app/routes/\*\*\\/\*.ts
```typescript
import { ActionFunctionArgs } from "react-router";
import { authenticate } from "../shopify.server";
export const action = async ({ request }: ActionFunctionArgs) => {
const { billing } = await authenticate.admin(request);
await billing.updateUsageCappedAmount({
subscriptionLineItemId: "gid://shopify/AppSubscriptionLineItem/12345?v=1&index=1",
cappedAmount: {
amount: 10,
currencyCode: "USD"
},
});
// App logic
};
```
##### shopify.server.ts
```typescript
import { shopifyApp, BillingInterval } from "@shopify/shopify-app-react-router/server";
export const USAGE_PLAN = 'Usage subscription';
const shopify = shopifyApp({
// ...etc
billing: {
[USAGE_PLAN]: {
lineItems: [
{
amount: 5,
currencyCode: 'USD',
interval: BillingInterval.Usage,
terms: "Usage based"
}
],
},
}
});
export default shopify;
export const authenticate = shopify.authenticate;
```
## Related
[Authenticate requests from Shopify Admin. - Admin context](https://shopify.dev/docs/api/shopify-app-react-router/authenticate/admin)