App Events API reference
The App Events API lets developers send events that happen in their app to Shopify. All events are shown in the Dev Dashboard logs section. Events configured as part of Shopify App Pricing are also processed for billing.
Anchor to AuthenticationAuthentication
All App Events API requests require a valid bearer token.
API keys created in the Dev Dashboard provide a client ID and secret that can be used to generate a JWT token. Permissions to write to App Events are automatically included — no additional scope configuration is required.
The response will contain:
access_token: A JWT access token that can be used to interact with the App Events API.scope: The list of access scopes that were granted to your API key.expires_in: The number of seconds until the access token expires.
Include your token as a Authorization: Bearer {token} header on all API requests.
Access tokens expire after 60 minutes. You can use a JWT decoder tool like jwt.io to investigate more details related to how Shopify issues this token. Request a new token before the current one expires.
Anchor to Endpoints and requestsEndpoints and requests
The App Events API lets you send events happening in your app to Shopify. All events are visible in the Dev Dashboard. Events sent to this API as part of Shopify App Pricing are processed for billing to merchants. Each request sends one event at a time — batch requests aren't supported.
All App Events API endpoints follow this pattern: https://api.shopify.com/app/{version}/events.
The App Events API is versioned. To keep your app stable, make sure you specify a supported version in the URL. Learn more about API versioning.
The App Events API provides the following endpoint:
- Create an event: Send billing events for usage-based pricing meters or custom events for monitoring in the Dev Dashboard.
Learn more about App Events and building a billing event.
Anchor to Shopify Analytics eligibilityShopify Analytics eligibility
App Events in Analytics is in developer preview. The preview is available to approved apps and supports declared standard events. Sign up for early access.
App Events in Analytics is in developer preview. The preview is available to approved apps and supports declared standard events. Sign up for early access.
Events sent to the App Events API appear in the Dev Dashboard. Depending on your app configuration, Shopify can also process an event for usage-based billing or make it available in Shopify Analytics.
An event is eligible for Shopify Analytics only when all of the following are true:
- The app has access to App Events in Analytics.
- The app has an accepted
analytics_app_eventsdeclaration. - The emitted
event_handlematches a declared standard event. - The event attributes match the standard registry definition and the App Events API request constraints.
- The event passes analytics validation and processing.
For standard events, emit the full standard registry handle, including the shopify. prefix, as the event_handle. Use the same handle that you declare in shopify.extension.toml.
shopify.extension.toml declaration (name) | API event_handle |
|---|---|
shopify.marketing.email_sent | shopify.marketing.email_sent |
shopify.marketing.sms_sent | shopify.marketing.sms_sent |
shopify.loyalty.points_earned | shopify.loyalty.points_earned |
Standard registry membership alone doesn't make an event queryable in Shopify Analytics. Your app must declare the event in shopify.extension.toml.
The following example shows the request body for a standard analytics event:
Learn how to use App Events in Analytics.
Anchor to Request schemaRequest schema
All events use a single request schema. Every event is logged and visible in the Dev Dashboard. If the event_handle matches a handle configured in a pricing plan as part of Shopify App Pricing, the event is also processed as a usage charge.
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 Request bodyRequest body
shop_id•stringRequiredThe ID of the merchant's shop that the event is associated with. For example, gid://shopify/Shop/23423423 or 23423423. Both a Shopify GID and a numeric shop ID (as a string) are accepted.
event_handle•stringRequiredThe name of the event. If this matches a meter handle in your pricing configuration, the event is processed as a billing event. Otherwise, it's tracked as a custom event for monitoring. The prefix shopify. is reserved and can't be used.
If the event matches an accepted Analytics App Events declaration, then Shopify can also make the event available in Shopify Analytics. Standard events used in Shopify Analytics are an exception to the reserved shopify. prefix: emit the full standard registry handle, such as shopify.marketing.email_sent, as the event_handle. Use the same handle that you declare in shopify.extension.toml.
timestamp•stringRequiredThe ISO 8601 timestamp of when the event occurred (for example, 2026-01-27T14:30:00Z). The timestamp can't be more than 5 minutes in the future. Billing events outside the current cycle currently reject with RESULT_STATUS_FAILURE and a result_details message with details about the allowable window.
idempotency_key•stringRequiredAn app-generated unique key to prevent duplicate events. Maximum 64 characters. The API enforces a 24-hour idempotency window — requests with a previously seen key within that window return the original response. For billing events, idempotency is enforced permanently.
attributes•objectRequiredA JSON object containing the event data. For billing events, the value field is required and specifies the quantity to apply to the meter. For details, see Understand the request fields. The attributes object has the following restrictions:
- Maximum 15 keys in the attributes object
- Keys are limited to 64 characters and can only contain alphanumeric ASCII characters, underscores (
_), periods (.), and hyphens (-) - String values are limited to 128 characters (UTF-8)
- Only scalar values are allowed (strings, numbers, booleans). Arrays and nested objects aren't supported.
Anchor to Response schemaResponse schema
All successful requests return a 202 Accepted response with the following JSON body:
success•booleanWhether the event was received successfully.
error•stringPresent when success is false. A short explanation of what went wrong.
Anchor to Example: Report a billing eventExample: Report a billing event
This example shows the full flow of authenticating and sending a billing event.
Anchor to Status and error codesStatus and error codes
All API queries return HTTP status codes that can tell you more about the response.
202 Accepted
The event was received successfully. A 202 response means Shopify received the request — it doesn't confirm that billing validation passed. Billing errors are processed asynchronously and are only visible in the Dev Dashboard under Logs with the App Billing Event type filter. There are no synchronous billing error responses and no webhooks for billing validation failures. Replayed requests (same idempotency_key within the idempotency window) return the original response with an Idempotent-Replay: true header.
A 202 response also doesn't confirm that the event was accepted for Shopify Analytics. Analytics processing occurs asynchronously. An accepted request becomes queryable only if it matches an accepted Analytics App Events declaration and passes analytics validation. If an event appears in the Dev Dashboard but isn't available in Shopify Analytics, then check the app's analytics_app_events declaration and the standard event registry definition.
400 Bad Request
The request parameters are invalid. The response includes { "success": false, "error": "Invalid request" }.
401 Unauthorized
The bearer token is missing or invalid.
403 Forbidden
The app isn't installed on the shop specified by shop_id, or the shop_id value is invalid.
409 Conflict
A request with the same idempotency_key is still being processed. Retry after a short delay.
429 Too Many Requests
Rate limit exceeded. The App Events API has a rate limit of 500 requests per second per app. Wait before retrying.
5xx Errors
An internal error occurred in Shopify. Check out the Shopify status page for more information.
Anchor to TermsTerms
By using the App Events API, you agree to the App Events API Terms of Service. Don't submit personal information such as names, email addresses, or any data that identifies a natural person.
Events used for analytics must not include personal data or data that can identify a natural person. Don't send names, email addresses, phone numbers, customer IDs, addresses, or other directly identifiable values in event attributes. Use non-identifying campaign, workflow, app, or aggregate identifiers instead.