--- title: Billing description: |- Contains function used to bill merchants for your app. This object is returned on authenticated Admin requests. api_version: v1 api_name: shopify-app-remix source_url: html: https://shopify.dev/docs/api/shopify-app-remix/v1/latest/apis/billing md: https://shopify.dev/docs/api/shopify-app-remix/v1/latest/apis/billing.md --- # Billingobject Contains function used to bill merchants for your app. This object is returned on authenticated Admin requests. ## billing Provides utilities that apps can use to request billing for the app using the Admin API. * require (options: RequireBillingOptions\) => Promise\ required Checks if the shop has an active payment for any plan defined in the `billing` config option. * request (options: RequestBillingOptions\) => Promise\ required Requests payment for the plan. * cancel (options: CancelBillingOptions) => Promise\ required Cancels an ongoing subscription, given its ID. ### RequireBillingOptions * plans The plans to check for. Must be one of the values defined in the \`billing\` config option. ```ts (keyof Config["billing"])[] ``` * onFailure How to handle the request if the shop doesn't have an active payment for any plan. ```ts (error: any) => Promise ``` * isTest ```ts boolean ``` ```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; } ``` ### RequestBillingOptions * plan The plan to request. Must be one of the values defined in the \`billing\` config option. ```ts keyof Config["billing"] ``` ```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']; } ``` ### CancelBillingOptions * subscriptionId The ID of the subscription to cancel. ```ts string ``` * prorate Whether to prorate the cancellation. ```ts boolean ``` * isTest ```ts boolean ``` ```ts export interface CancelBillingOptions { /** * The ID of the subscription to cancel. */ subscriptionId: string; /** * Whether to prorate the cancellation. * * {@link https://shopify.dev/docs/apps/billing/subscriptions/cancel-recurring-charges} */ prorate?: boolean; isTest?: boolean; } ``` ## Examples ### require Requesting billing right away Call `billing.request` in the `onFailure` callback to immediately request payment. Using a plan selection page Redirect to a different page in the `onFailure` callback, where the merchant can select a billing plan. ### Examples * #### Requesting billing right away ##### Description Call \`billing.request\` in the \`onFailure\` callback to immediately request payment. ##### /app/routes/\*\*\\/\*.ts ```typescript import { LoaderArgs } from "@remix-run/node"; import { authenticate, MONTHLY_PLAN } from "../shopify.server"; export const loader = async ({ request }: LoaderArgs) => { 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-remix/server"; export const MONTHLY_PLAN = 'Monthly subscription'; export const ANNUAL_PLAN = 'Annual subscription'; const shopify = shopifyApp({ // ...etc billing: { [MONTHLY_PLAN]: { amount: 5, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, [ANNUAL_PLAN]: { amount: 50, currencyCode: 'USD', interval: BillingInterval.Annual, }, } }); export default shopify; export const authenticate = shopify.authenticate; ``` * #### Using a plan selection page ##### Description Redirect to a different page in the \`onFailure\` callback, where the merchant can select a billing plan. ##### /app/routes/\*\*\\/\*.ts ```typescript import { LoaderArgs, redirect } from "@remix-run/node"; import { authenticate, MONTHLY_PLAN, ANNUAL_PLAN } from "../shopify.server"; export const loader = async ({ request }: LoaderArgs) => { 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-remix/server"; export const MONTHLY_PLAN = 'Monthly subscription'; export const ANNUAL_PLAN = 'Annual subscription'; const shopify = shopifyApp({ // ...etc billing: { [MONTHLY_PLAN]: { amount: 5, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, [ANNUAL_PLAN]: { amount: 50, currencyCode: 'USD', interval: BillingInterval.Annual, }, } }); export default shopify; export const authenticate = shopify.authenticate; ``` ### request Using a custom return URL Change where the merchant is returned to after approving the purchase using the `returnUrl` option. ### Examples * #### 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 { LoaderArgs } from "@remix-run/node"; import { authenticate, MONTHLY_PLAN } from "../shopify.server"; export const loader = async ({ request }: LoaderArgs) => { const { billing } = await authenticate.admin(request); await billing.require({ plans: [MONTHLY_PLAN], onFailure: async () => billing.request({ plan: MONTHLY_PLAN, isTest: true, returnUrl: '/billing-complete', }), }); // App logic }; ``` ##### shopify.server.ts ```typescript import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/server"; export const MONTHLY_PLAN = 'Monthly subscription'; export const ANNUAL_PLAN = 'Annual subscription'; const shopify = shopifyApp({ // ...etc billing: { [MONTHLY_PLAN]: { amount: 5, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, [ANNUAL_PLAN]: { amount: 50, currencyCode: 'USD', interval: BillingInterval.Annual, }, } }); export default shopify; export const authenticate = shopify.authenticate; ``` ### cancel Cancelling a subscription Use the `billing.cancel` function to cancel an active subscription with the id returned from `billing.require`. ### 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 { LoaderArgs } from "@remix-run/node"; import { authenticate, MONTHLY_PLAN } from "../shopify.server"; export const loader = async ({ request }: LoaderArgs) => { 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-remix/server"; export const MONTHLY_PLAN = 'Monthly subscription'; export const ANNUAL_PLAN = 'Annual subscription'; const shopify = shopifyApp({ // ...etc billing: { [MONTHLY_PLAN]: { amount: 5, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, [ANNUAL_PLAN]: { amount: 50, currencyCode: 'USD', interval: BillingInterval.Annual, }, } }); export default shopify; export const authenticate = shopify.authenticate; ``` ## Related [![](https://shopify.dev/images/icons/32/pickaxe-1.png)![](https://shopify.dev/images/icons/32/pickaxe-1-dark.png)](https://shopify.dev/docs/api/shopify-app-remix/authenticate/admin) [Authenticate requests from Shopify Admin.Admin context](https://shopify.dev/docs/api/shopify-app-remix/authenticate/admin)