---
title: Billing
description: Contains function used to bill merchants for your app with the Billing API.
api_version: v4
source_url:
  html: 'https://shopify.dev/docs/api/shopify-app-remix/latest/apis/billing'
  md: 'https://shopify.dev/docs/api/shopify-app-remix/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](https://shopify.dev/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.

#### billing

Provides utilities that apps can use to request billing for the app using the Admin API.

* **cancel**

  **(options: CancelBillingOptions) => Promise\<AppSubscription>**

  **required**

  Cancels an ongoing subscription, given its ID.

* **check**

  **\<Options extends CheckBillingOptions\<Config>>(options?: Options) => Promise\<BillingCheckResponseObject>**

  **required**

  Checks if the shop has an active payment for any plan defined in the `billing` config option.

* **createUsageRecord**

  **(options: CreateUsageRecordOptions) => Promise\<UsageRecord>**

  **required**

  Creates a usage record for an app subscription.

* **request**

  **(options: RequestBillingOptions\<Config>) => Promise\<never>**

  **required**

  Requests payment for the plan.

* **require**

  **(options: RequireBillingOptions\<Config>) => Promise\<BillingCheckResponseObject>**

  **required**

  Checks if the shop has an active payment for any plan defined in the `billing` config option.

* **updateUsageCappedAmount**

  **(options: UpdateUsageCappedAmountOptions) => Promise\<never>**

  **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
  ```

### AppSubscription

* createdAt

  The date and time when the subscription was created.

  ```ts
  string
  ```

* currentPeriodEnd

  The date and time when the current period ends.

  ```ts
  string
  ```

* id

  The ID of the app subscription.

  ```ts
  string
  ```

* lineItems

  ```ts
  ActiveSubscriptionLineItem[]
  ```

* name

  The name of the purchased plan.

  ```ts
  string
  ```

* returnUrl

  The return URL for this subscription.

  ```ts
  string
  ```

* status

  ```ts
  | 'ACTIVE'
      | 'CANCELLED'
      | 'PENDING'
      | 'DECLINED'
      | 'EXPIRED'
      | 'FROZEN'
      | 'ACCEPTED'
  ```

* test

  Whether this is a test subscription.

  ```ts
  boolean
  ```

* trialDays

  The number of trial days for this subscription.

  ```ts
  number
  ```

### ActiveSubscriptionLineItem

* id

  ```ts
  string
  ```

* plan

  ```ts
  AppPlan
  ```

### AppPlan

* pricingDetails

  ```ts
  RecurringAppPlan | UsageAppPlan
  ```

### RecurringAppPlan

* discount

  ```ts
  AppPlanDiscount
  ```

* interval

  ```ts
  BillingInterval.Every30Days | BillingInterval.Annual
  ```

* price

  ```ts
  Money
  ```

### AppPlanDiscount

* durationLimitInIntervals

  ```ts
  number
  ```

* priceAfterDiscount

  ```ts
  Money
  ```

* remainingDurationInIntervals

  ```ts
  number
  ```

* value

  ```ts
  AppPlanDiscountAmount
  ```

### Money

* amount

  ```ts
  number
  ```

* currencyCode

  ```ts
  string
  ```

### AppPlanDiscountAmount

```ts
BillingConfigSubscriptionPlanDiscountAmount | BillingConfigSubscriptionPlanDiscountPercentage
```

### BillingConfigSubscriptionPlanDiscountAmount

* amount

  The amount to discount. Cannot be set if \`percentage\` is set.

  ```ts
  number
  ```

* percentage

  The percentage to discount. Cannot be set if \`amount\` is set.

  ```ts
  never
  ```

### BillingConfigSubscriptionPlanDiscountPercentage

* amount

  The amount to discount. Cannot be set if \`percentage\` is set.

  ```ts
  never
  ```

* percentage

  The percentage to discount. Cannot be set if \`amount\` is set.

  ```ts
  number
  ```

### BillingInterval

* OneTime

  ```ts
  ONE_TIME
  ```

* Every30Days

  ```ts
  EVERY_30_DAYS
  ```

* Annual

  ```ts
  ANNUAL
  ```

* Usage

  ```ts
  USAGE
  ```

### UsageAppPlan

* balanceUsed

  ```ts
  Money
  ```

* cappedAmount

  ```ts
  Money
  ```

* terms

  ```ts
  string
  ```

### Options

* layout

  Whether to use the shop's theme layout around the Liquid content.

  ```ts
  boolean
  ```

### CheckBillingOptions

* plans

  The plans to check for. Must be one of the values defined in the \`billing\` config option.

  ```ts
  (keyof Config["billing"])[]
  ```

### BillingCheckResponseObject

* appSubscriptions

  The active subscriptions the shop has.

  ```ts
  AppSubscription[]
  ```

* hasActivePayment

  Whether the user has an active payment method.

  ```ts
  boolean
  ```

* oneTimePurchases

  The one-time purchases the shop has.

  ```ts
  OneTimePurchase[]
  ```

### OneTimePurchase

* id

  The ID of the one-time purchase.

  ```ts
  string
  ```

* name

  The name of the purchased plan.

  ```ts
  string
  ```

* status

  ```ts
  | 'ACTIVE'
      | 'CANCELLED'
      | 'PENDING'
      | 'DECLINED'
      | 'EXPIRED'
      | 'FROZEN'
      | 'ACCEPTED'
  ```

* test

  Whether this is a test purchase.

  ```ts
  boolean
  ```

### 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
  ```

### UsageRecord

* description

  The description of the usage record.

  ```ts
  string
  ```

* id

  The ID of the usage record.

  ```ts
  string
  ```

* idempotencyKey

  The idempotency key for this request.

  ```ts
  string
  ```

* plan

  The subscription line item associated with the usage record.

  ```ts
  ActiveSubscriptionLineItem
  ```

* price

  The price and currency of the usage record.

  ```ts
  { amount: number; currencyCode: string; }
  ```

* subscriptionLineItem

  The subscription line item associated with the usage record.

  ```ts
  AppSubscriptionLineItem
  ```

### AppSubscriptionLineItem

* id

  The ID of the subscription line item.

  ```ts
  string
  ```

* plan

  The plan associated with the subscription line item.

  ```ts
  AppPlan
  ```

### 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
  ```

### RequireBillingOptions

* onFailure

  How to handle the request if the shop doesn't have an active payment for any plan.

  ```ts
  (error: any) => Promise<Response>
  ```

* plans

  The plans to check for. Must be one of the values defined in the \`billing\` config option.

  ```ts
  (keyof Config["billing"])[]
  ```

### 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
  ```

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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  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]: {
        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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  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]: {
        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;
  ```

* ####

  ##### 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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  import { ActionFunctionArgs } from "@remix-run/node";
  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

  ```ts
  import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  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]: {
        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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  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]: {
        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

  ```ts
  import { LoaderFunctionArgs } from "@remix-run/node";
  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

  ```ts
  import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/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

  ```ts
  import { LoaderFunctionArgs, redirect } from "@remix-run/node";
  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

  ```ts
  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]: {
        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

  ```ts
  import { ActionFunctionArgs } from "@remix-run/node";
  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

  ```ts
  import { shopifyApp, BillingInterval } from "@shopify/shopify-app-remix/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-remix/v4/authenticate/admin)

***
