Agent Skills: Shopify Billing Skill

Guide for implementing Shopify's Billing API, enabling app monetization through subscriptions and one-time charges. Use this skill when the user needs to create recurring application charges, one-time purchases, or check subscription status.

UncategorizedID: toilahuongg/google-antigravity-kit/shopify-billing

Install this agent skill to your local

pnpm dlx add-skill https://github.com/toilahuongg/Google-Antigravity-Kit/tree/HEAD/.agent/skills/shopify-billing

Skill Files

Browse the full folder contents for shopify-billing.

Download Skill

Loading file tree…

.agent/skills/shopify-billing/SKILL.md

Skill Metadata

Name
shopify-billing
Description
Guide for implementing Shopify's Billing API, enabling app monetization through subscriptions and one-time charges. Use this skill when the user needs to create recurring application charges, one-time purchases, or check subscription status.

Shopify Billing Skill

The Billing API allows you to charge merchants for your app using recurring subscriptions or one-time purchases.

[!IMPORTANT] GraphQL Only: The REST Billing API is deprecated. Always use the GraphQL Admin API for billing operations.

1. Recurring Subscriptions (appSubscriptionCreate)

Use this mutation to create a recurring charge (e.g., monthly plan).

Example (Remix / Shopify App Template)

/* app/routes/app.upgrade.tsx */
import { authenticate } from "../shopify.server";

export const action = async ({ request }) => {
  const { admin } = await authenticate.admin(request);
  const shop = await admin.graphql(`
    mutation AppSubscriptionCreate($name: String!, $lineItems: [AppSubscriptionLineItemInput!]!, $returnUrl: URL!) {
      appSubscriptionCreate(name: $name, returnUrl: $returnUrl, lineItems: $lineItems) {
        userErrors {
          field
          message
        }
        appSubscription {
          id
        }
        confirmationUrl
      }
    }
  `,
  {
    variables: {
      name: "Pro Plan",
      returnUrl: "https://myapp.com/app",
      lineItems: [{
        plan: {
          appRecurringPricingDetails: {
            price: { amount: 10.00, currencyCode: "USD" },
            interval: "EVERY_30_DAYS"
          }
        }
      }]
    }
  });

  const response = await shop.json();
  const confirmationUrl = response.data.appSubscriptionCreate.confirmationUrl;
  
  // Redirect merchant to approve charge
  return redirect(confirmationUrl);
};

2. One-Time Purchases (appPurchaseOneTimeCreate)

Use this mutation for non-recurring charges (e.g., specific service, lifetime access).

const response = await admin.graphql(`
  mutation AppPurchaseOneTimeCreate($name: String!, $price: MoneyInput!, $returnUrl: URL!) {
    appPurchaseOneTimeCreate(name: $name, returnUrl: $returnUrl, price: $price) {
      userErrors { field message }
      confirmationUrl
    }
  }
`, {
  variables: {
    name: "Concierge Setup",
    returnUrl: "https://myapp.com/app",
    price: { amount: 50.00, currencyCode: "USD" }
  }
});

3. Checking Active Subscriptions

To gate features, check the currentAppInstallation for active subscriptions.

/* app/shopify.server.ts (billing config) */
export const billing = {
  "Pro Plan": {
    amount: 10.00,
    currencyCode: "USD",
    interval: "EVERY_30_DAYS",
  },
};

/* Checking in loader */
const { billing } = await authenticate.admin(request);
const billingCheck = await billing.require({
  plans: ["Pro Plan"],
  isTest: true, // Use true for development stores
  onFailure: async () => billing.request({ plan: "Pro Plan", isTest: true }),
});
const subscription = billingCheck.appSubscriptions[0];

Manual Query (if not using billing helper)

query {
  currentAppInstallation {
    activeSubscriptions {
      id
      name
      status
      lineItems {
        plan {
          pricingDetails {
            ... on AppRecurringPricing {
              price { amount currencyCode }
            }
          }
        }
      }
    }
  }
}

4. Best Practices

  • Test Mode: Always set test: true (or isTest) when developing. Test charges do not bill the merchant.
  • Confirmation URL: You MUST redirect the user to the confirmationUrl returned by the mutation. The charge is not active until they approve it.
  • Webhooks: Listen for app_subscriptions/update to handle cancellations or status changes in real-time.