Build a Billing Event
Usage-based billing for Shopify apps relies on two systems working together:
- Shopify App Pricing: Defines your pricing plans, billing meters, and pricing structures in the Partner Dashboard. Shopify App Pricing handles plan selection, merchant approval, and automatic charge calculation.
- App Events API: Reports billing events from your app to Shopify. When an event's handle matches a billing meter defined in Shopify App Pricing, Shopify automatically counts it toward the merchant's usage charges.
In this tutorial, you'll build an SMS messaging app that charges merchants per message sent. You'll use Shopify App Pricing to configure a plan with a usage meter, then use the App Events API to report each SMS as a billing event. Shopify handles everything in between — plan selection, charge approval, usage tracking, and invoicing.
Anchor to What you'll learnWhat you'll learn
In this tutorial, you'll learn how to do the following tasks:
- Use Shopify App Pricing to create a plan with usage-based billing meters
- Configure a welcome link and redirect merchants to the plan selection page
- Authenticate with the App Events API
- Send billing events that match your Shopify App Pricing meters
- Verify that Shopify App Pricing correctly processes your billing events in the Dev Dashboard
Anchor to RequirementsRequirements
- A Partner account
- A development store
- An app with Shopify App Pricing enabled
- An API key with the
write_global_api_app_eventsscope
Anchor to Step 1: Configure usage-based pricing with Shopify App PricingStep 1: Configure usage-based pricing with Shopify App Pricing
Before you can send billing events through the App Events API, you need to use Shopify App Pricing to create a pricing plan and define a billing meter. The meter's handle is what connects your API requests to the pricing configuration — when an event's event_handle matches a meter handle, Shopify knows to bill for it.
Anchor to Create a plan with usage-based pricingCreate a plan with usage-based pricing
- From the Partner Dashboard, click Apps > All Apps and click your app's name.
- Click Distribution.
- Beside Shopify App Store listing, click Manage listing.
- Under Published languages, click Edit for the locale you want to update.
- Under Pricing content, click Manage to open the Pricing index page.
- Under Public plans, click Add to open the plan editor.
- Under Billing, select Monthly as the billing period.
- Under Monthly charge, enter 9.99 as the base subscription fee.
The base fee gives merchants access to your app. Usage-based charges for SMS messages are added on top of this fee.
Anchor to Add a usage meter for SMSAdd a usage meter for SMS
Usage meters track specific types of usage in your app. Each meter has a handle that you'll reference when sending billing events through the API.
-
In your plan editor, click Add usage meter.
-
Configure the meter with the following values:
Field Value Name SMS messages sent Handle sms_sentPricing structure Fixed Unit price $0.01 Included units 100
In this configuration, each merchant gets 100 free SMS messages per month. After that, each additional message costs $0.01. Shopify App Pricing automatically handles the calculation and adds the charges to the merchant's monthly bill.
The event_handle you send through the App Events API must exactly match the meter handle you define in Shopify App Pricing. Handles are case-sensitive. A mismatched handle causes the event to be marked as non-billable in the Dev Dashboard.
The event_handle you send through the App Events API must exactly match the meter handle you define in Shopify App Pricing. Handles are case-sensitive. A mismatched handle causes the event to be marked as non-billable in the Dev Dashboard.
Anchor to Configure the welcome linkConfigure the welcome link
The welcome link is where merchants are redirected after they approve your plan charge. Use it to guide merchants into your app's onboarding experience.
-
In the plan editor, find the Welcome link field.
-
Enter a redirect path or URL:
- Apps with a landing page in App Home: Specify a relative path to your app root, such as
/welcome. Yourplan_handleURL parameter is appended to all redirect URLs which is a plan that merchant is subscribed to. - Apps without a landing page in App Home: Redirect to a valid URL (including the
httporhttpsprotocol). URL parameters for theplan_handleand the merchant shop domain are appended to redirect URLs.
- Apps with a landing page in App Home: Specify a relative path to your app root, such as
-
Click Save to save the plan.
After a merchant is redirected to your welcome link, query the Active Subscription API on the Partner API to verify the subscription status before granting access to paid features.
After a merchant is redirected to your welcome link, query the Active Subscription API on the Partner API to verify the subscription status before granting access to paid features.
Anchor to Add plan descriptionsAdd plan descriptions
Plans need a display name and feature list for each language your app listing supports. A plan only displays to merchants if it has a description for their language.
- From the Partner Dashboard, navigate back to your app's Pricing content.
- Find the plan you created.
- Under Display name, enter a name like SMS Pro.
- Under Top features, list the features included in the plan. For example:
- Send SMS messages to customers
- 100 free messages per month
- $0.01 per additional message
- Click Save.
- Repeat for each published language in your app listing.
Anchor to Step 2: Redirect merchants to the Shopify App Pricing plan selection pageStep 2: Redirect merchants to the Shopify App Pricing plan selection page
Shopify App Pricing hosts the plan selection page for your app. When merchants install your app or need to select a plan, redirect them to this page. It displays the plans you configured in Step 1 and handles the approval flow.
Anchor to Build the redirect in your appBuild the redirect in your app
Your app's plan selection page URL follows this pattern:
In your app's root route loader, check whether the merchant has an active subscription using the Active Subscription API on the Partner API. If not, redirect them to the plan selection page:
app/routes/app.jsx
Replace YOUR_APP_HANDLE with the app_handle value from your shopify.app.toml file. The target: "_top" option is required for apps with a landing page in App Home because the plan selection page is outside the app's iframe.
Anchor to Test the plan approval flowTest the plan approval flow
- Install your app on your development store.
- Confirm that your app redirects to the plan selection page.
- Select the SMS Pro plan and approve the charge.
- Verify that you're redirected to your welcome link with the
plan_handleparameter.
On development stores, merchants aren't actually charged. You can test the full billing flow without any real payments. If you don't want to publish a public plan yet, Shopify App Pricing includes a $0 private test plan that you can use to configure and test your meters during development.
On development stores, merchants aren't actually charged. You can test the full billing flow without any real payments. If you don't want to publish a public plan yet, Shopify App Pricing includes a $0 private test plan that you can use to configure and test your meters during development.
Anchor to Step 3: Authenticate with the App Events APIStep 3: Authenticate with the App Events API
The App Events API uses JWT tokens for authentication. Generate a token using your app's client credentials from the Dev Dashboard.
When you create an API key in the Dev Dashboard, you automatically receive permissions to write to App Events. No additional configuration is required.
Use your app's client ID and client secret to request an access token:
/auth/access_token
The response includes an access_token, the granted scope, and an expires_in value in seconds:
{} Response
Store this token securely in your app. You'll include it as an Authorization: Bearer header on every App Events API request. Tokens expire after 60 minutes — refresh them before they expire.
Anchor to Step 4: Send a billing event through the App Events APIStep 4: Send a billing event through the App Events API
After your app sends an SMS message for a merchant, use the App Events API to report the usage to Shopify. The event_handle must match the sms_sent meter handle you configured in Shopify App Pricing in Step 1. This is how the two systems connect — the App Events API reports the event, and Shopify App Pricing uses the matching meter to calculate the charge. To learn more about using App Events, see About App Events.
Anchor to Send a single SMS eventSend a single SMS event
Report usage promptly to ensure accurate billing data. You can queue events in your app and send them sequentially to stay within rate limits.
Don't include any data that, alone or in combination with other data, could identify an individual. This includes any merchant or buyer information, such as name, email address, phone number, and other identifiable data points. Use anonymized identifiers and aggregated metrics instead.
Don't include any data that, alone or in combination with other data, could identify an individual. This includes any merchant or buyer information, such as name, email address, phone number, and other identifiable data points. Use anonymized identifiers and aggregated metrics instead.
Anchor to Understand the request fieldsUnderstand the request fields
| Field | Value | Description |
|---|---|---|
shop_id | "gid://shopify/Shop/23423423" | The Shopify shop ID of the merchant the SMS was sent for. Accepts a GID (shown) or a numeric shop ID as a string. |
event_handle | sms_sent | Must exactly match the billing meter handle from your Shopify App Pricing configuration. |
timestamp | 2026-01-27T14:30:00Z | The ISO 8601 time when the SMS was actually sent, not when you reported it. Must fall within the merchant's current billing cycle and can't be more than 5 minutes in the future. |
idempotency_key | sms_23423423_1706365800 | A unique key that prevents duplicate charges if you retry the request. Maximum 64 characters. Billing idempotency keys are enforced permanently. |
attributes.value | 1 | The number of units to add to the meter. Must be greater than 0. Use 1 for a single SMS. |
Anchor to Report batch usageReport batch usage
If your app sends multiple messages in a campaign, you can report the total in a single event:
Setting value: 5 adds five units to the merchant's sms_sent meter for the billing period.
The App Events API always returns a 202 response when it receives your request, even if the event fails billing validation. There is no synchronous billing error response and no webhooks for billing validation failures. Always verify your events in the Dev Dashboard under Logs with the App Billing Event type filter.
The App Events API always returns a 202 response when it receives your request, even if the event fails billing validation. There is no synchronous billing error response and no webhooks for billing validation failures. Always verify your events in the Dev Dashboard under Logs with the App Billing Event type filter.
Anchor to Step 5: Verify billing events in the Dev DashboardStep 5: Verify billing events in the Dev Dashboard
After sending billing events through the App Events API, use the Dev Dashboard to confirm that Shopify App Pricing is processing them correctly.
Anchor to View your billing eventsView your billing events
- Go to the Dev Dashboard and select your app.
- Click Logs in the sidebar.
- Set the Type filter to App Event to show only app events.
- Look for your
sms_sentevents in the list.
Each event displays:
- Status: Whether the event was successfully processed (
200) or failed (4xx,5xx). - Event handle: The meter handle from your request (
sms_sent). - Shop: The merchant's shop domain.
- Timestamp: When the event was sent.
Anchor to Confirm the event is billableConfirm the event is billable
In the logs, billing events are labeled to distinguish them from custom events:
- Billable: The App Events API matched the event to the
sms_sentbilling meter in Shopify App Pricing. The usage counts toward the merchant's charges. - Non-billable: The event was received by the App Events API but didn't match any billing meter in Shopify App Pricing.
If an event shows as non-billable, verify that the event_handle in your App Events API request exactly matches the meter handle in your Shopify App Pricing configuration. Handles are case-sensitive.
Anchor to Troubleshoot billing errorsTroubleshoot billing errors
The following errors can appear in the Dev Dashboard for billing events:
| Error | Cause | Solution |
|---|---|---|
NO_SUBSCRIPTION | The merchant doesn't have an active Shopify App Pricing subscription | Confirm the merchant installed your app and approved the pricing plan |
ACCOUNT_FROZEN | The partner account is frozen and can't process billable events | Contact Shopify Partner Support to resolve your account status |
SUBSCRIPTION_NOT_METERED | The Shopify App Pricing subscription doesn't include usage-based pricing | Verify the merchant is on a plan that includes usage meters |
INVALID_TIMESTAMP | The timestamp is missing, malformed, more than 5 minutes in the future, or falls outside the merchant's current billing cycle | Use an ISO 8601 timestamp within the merchant's current billing cycle that isn't more than 5 minutes in the future |
IDEMPOTENCY_KEY_ERROR | The key is missing, already used, or invalid | Use a unique idempotency key for each distinct billable action |
INVALID_VALUE | The value is zero, negative, or non-numeric | Send a value greater than 0 for the value field |
MISSING_VALUE_KEY | The value key is missing from the attributes | Include "value" in the attributes object |
PERIOD_CLOSED | The billing period for this timestamp has already closed. This also occurs more than 24 hours after a merchant uninstalls your app | Send events within the current billing cycle. After a merchant uninstalls, you have 24 hours to submit remaining usage |
INVALID_ACCOUNT | The app or partner account isn't authorized | Verify your app credentials and partner account status |
Anchor to Monitor billing healthMonitor billing health
Use the event graph in the Logs view to monitor billing event volume over time:
- Consistent volume: Billing events should correlate with your app's SMS sending patterns.
- Error spikes: Sudden increases in failed events might indicate a configuration issue or expired credentials.
- Missing events: Gaps in expected billing events could mean your app isn't reporting usage correctly.
Check the Dev Dashboard regularly, especially after deploying changes to your billing integration.
Anchor to Next stepsNext steps
- Explore Shopify App Pricing for an overview of all pricing options available to your app.
- Learn about graduated and volume pricing structures in Shopify App Pricing for more advanced billing models.
- Combine subscriptions with usage for hybrid pricing plans.
- Set up custom events to track non-billable merchant behavior through the App Events API.
- Review the App Events API reference for the complete API specification.
- Monitor your events in the Dev Dashboard.