We are experiencing an issue with subscription webhooks, specifically subscription_contracts/create, and would appreciate clarification on the expected behavior.
Environment
Summary of the issue
-
Subscription contracts are being successfully created and are visible in Admin → Subscriptions → Contracts
-
Orders are created normally and we receive:
orders/create
order_transactions/create
-
However, subscription_contracts/create webhook is not delivered when the subscription is created via checkout
What we have verified
- Webhook is correctly registered (confirmed via
GET /admin/api/2025-07/webhooks.json)
- Topic is listed as
subscription_contracts/create
- Endpoint is reachable and HTTPS
- Other orders webhooks are delivered successfully:
- App has the required scopes (
write_own_subscription_contracts, read_own_subscription_contracts)
- The issue occurs while using Shopify Payments in test mode
Example behavior
- Customer completes checkout for a subscription product
- Order is created and order-related webhooks fire as expected
- Subscription contract appears in Admin
- No
subscription_contracts/create webhook is received
Questions
-
Is the absence of the subscription_contracts/create webhook for checkout-created subscriptions expected behavior, particularly when using Shopify Payments in test mode?
-
If this is expected:
- What is Shopify’s recommended approach to reliably detect newly created subscription contracts?
- Should apps rely on
orders/create combined with a GraphQL lookup of subscription contracts?
-
If this is not expected:
- re there known limitations, delays, or conditions under which this webhook is intentionally not fired?
1 Like
Hey @Gaurav_Dhandre, thanks for the details of the troubleshooting you have already completed.
I would expect the webhooks to be delivered here.
Can you share how you subscribed to the webhook? Did you do so through the API or the app configuration file?
Can you also try a query from the app that is subscribed to the webhook and query the subscription contract directly? This is to ensure that your app is able to receive the subscription contract data.
We subscribed to the subscription_contracts/create webhook via the Admin REST API (not through the app configuration file). We’ve verified the subscription using GET /admin/api/2025-07/webhooks.json, and the topic is correctly registered and active.
Additionally, we queried the subscription contract directly using the GraphQL Admin API from the same app that is subscribed to the webhook, but it returns empty records, even though the subscription is clearly visible in the Order, Customer, and Shopify Subscriptions sections in the Admin.
Please find the attached screenshots for reference.
Following up on the subscription contracts issue we discussed earlier.
This behavior is consistent when the subscription is created via checkout using Shopify Payments in test mode.
Looking forward to your guidance on the recommended way to reliably detect newly created subscription contracts.
Thanks
Gaurav
Hey @Gaurav_Dhandre,
Based on the Subscriptions section visible in your admin sidebar, it looks like you might be using the Shopify Subscriptions app (or another third-party subscription app) to handle the actual subscription creation at checkout. Can you confirm?
The reason I ask is the _own_ in your scopes (read_own_subscription_contracts, write_own_subscription_contracts) means your app can only access contracts that your app created and manages. This applies to both API queries and webhook delivery. If a different app is creating the contracts at checkout, your app won’t receive the subscription_contracts/create webhook for those, and they won’t appear in your GraphQL queries. This is by design where each subscription app owns and manages only its own contracts, and there isn’t a scope that grants access to contracts created by other apps.
If you can confirm which app is handling the subscription creation that will help clarify whether this is the expected behavior you’re seeing.
Thanks for the clarification — that makes sense.
Yes, the subscriptions are being created at checkout using the Shopify Subscriptions app (not by our app). Our app is currently only consuming order and subscription-related data post-checkout and does not create or manage the subscription contracts itself.
Given this, we understand now that because our app only has the read_own_subscription_contracts / write_own_subscription_contracts scopes, it can only access subscription contracts that were created and managed by our app. Since the contracts are owned by the Shopify Subscriptions app, it’s expected that:
Thanks for pointing this out — this explains the behavior we’re seeing.
To confirm next steps: for apps that do not own the subscription contracts, is the recommended approach to rely on orders/create (and related order webhooks) to detect subscription purchases, without direct access to the underlying subscription contract?
Appreciate your help in clarifying this.
Hey @Gaurav_Dhandre, orders/create is the right approach. One way to identify these orders is to Check the source_name field in the order payload. Subscription orders may have something like "subscription_contract". Best to test on your own store to confirm how it looks with your current set up.
If you need to query for additional details, the sellingPlan field on line items has additional info.
Thanks for the clarification — that makes sense.
We’ll proceed with using the orders/create webhook and identify subscription-related orders by inspecting the source_name field in the order payload. We’ll also review the sellingPlan field on line items to extract any additional subscription details as needed.
We’ll validate this behavior in our own test store to confirm how it appears with our current setup.
Appreciate your guidance on this.
Thanks for the guidance. We’ve done some additional testing, but we’re still seeing inconsistent behavior and wanted to share our findings.
Here’s what we’re observing:
-
Fetching subscription contracts
-
We attempted to fetch all subscription contracts using the GraphQL Admin API from the same app.
-
The response returns empty nodes, even though the subscription contracts are clearly visible in:
-
Order webhook inspection
-
We checked the orders/create webhook payload for subscription orders.
-
The source_name field shows web (not subscription_contract or similar).
-
Order tags do indicate a subscription, but:
-
Summary
We’ve attached screenshots of:
Based on this, could you please advise:
-
Is this expected behavior when subscriptions are created by the Shopify Subscriptions app (or another subscription app)?
-
If so, what is the recommended and reliable way for a third-party app to detect and associate checkout-created subscription orders with subscription contracts?
Hey @Gaurav_Dhandre,
The orders/create and orders/update webhooks include an app_id field in the payload that identifies which app created the order. For subscription orders created by the Shopify Subscriptions app, this field contains the Shopify Subscriptions app ID, which is one way to identify them in the webhook since the other fields aren’t returning identifiers.
One thing to note: the initial subscription order is placed through the online store, so the app_id field won’t help identify that first order. However, all recurring orders are created by the Shopify Subscriptions app and will have the app_id field populated with the Shopify Subscriptions app ID.
Additionally, as you can see in your screenshots, subscription orders do add order tags. You can query orders based on these tags to confirm whether an order is a subscription order (these won’t be in the webhooks as they can take a few minutes to populate) Combining the app_id check with the tag filter gives you a reliable way to identify and process subscription orders even without direct access to the underlying contracts.
You can also create some Flow automations if you want to do more with these orders.
Checking in to see if the above helped, @Gaurav_Dhandre .
Thanks for your email,
I wanted to summarize our subscription sync requirement, the approach we planned to take, and the blocker we’re currently facing, so we can confirm the best path forward.
Requirement
Our goal is to ensure that all Shopify subscription lifecycle changes are accurately reflected in our system, including:
-
Subscription creation
-
Pause
-
Expiration
-
Cancellation
Planned Approach1. Subscription Creation
-
Subscription Status Updates
-
For changes such as pause, expiration, or cancellation, we planned to periodically query the Shopify Subscriptions API.
-
This job would run daily to fetch subscription contracts and sync their latest status to our system.
Current Blocker
While implementing this, we’ve encountered a critical issue:
-
We are unable to fetch subscription contracts at all via the GraphQL Admin API.
-
Queries to fetch all subscription contracts consistently return empty nodes.
-
This happens even though the subscriptions are clearly visible in:
Because of this:
-
We cannot detect subscription status changes programmatically.
-
The daily polling approach for syncing paused, expired, or cancelled subscriptions is not currently viable.
Questions
Could you please help clarify:
-
Is this expected behavior when subscriptions are created and managed by the Shopify Subscriptions app (or another subscription app)?
-
If so, what is the recommended way for a third-party app to:
-
Are there any required scopes, limitations, or alternative APIs we should be using to access subscription contract data?
(We already have subscription scope access)
Thanks for the follow up @Gaurav_Dhandre.
To help clarify, currently we don’t have API’s available for the Shopify Subscription app. Since the subscription API’s are scoped to the app that creates and manages them, they won’t be available to your app or other apps to query. Currently those additional details are only accessible through the Shopify Subscription app in the admin.
Hi,
We observed an inconsistency while testing subscription contract retrieval and wanted to highlight the behavior we’re seeing.
-
When an order is placed with a one-time purchase, the subscription contracts are returned correctly via the API.
-
However, when an order is placed with a recurring frequency (for example, every 1 month or 2 months), the subscription contracts query returns empty nodes, even though the subscription is successfully created and visible in the Admin → Subscriptions section.
This makes it difficult for us to reliably track and sync recurring subscriptions in our system, even though the contracts clearly exist in the Shopify admin.
Additionally, we noticed that recurring subscription orders are created by the Shopify Subscriptions app and include an app_id in the orders/create and orders/update webhooks.
Could you please confirm:
-
Whether this behavior is expected for recurring-frequency subscriptions
-
Whether it’s supported or recommended to identify recurring subscription contracts using the app_id from order webhooks
-
And if so, what the correct or supported approach would be to associate those orders with their underlying subscription contracts oR how to fetch the subscription contracts using the app_id?
Hey @Gaurav_Dhandre,
The difference you’re seeing isn’t between prepaid vs recurring subscriptions. It’s about which app created the subscription contract.
With read_own_subscription_contracts, you can only query contracts owned by your app.
To verify: check the app field on the contracts you can see. That’ll confirm which app owns them.
For your questions:
-
Expected behavior? Yes. The visibility is based on contract ownership, not subscription type.
-
Using app_id from webhooks? Yes, this is a valid way to identify which app created an order. Subscription orders from Shopify Subscriptions will have that app’s app_id.
-
Associating orders with contracts via app_id? You can’t. There’s no reverse lookup from Order → SubscriptionContract in the API. You can only identify that an order is subscription-related. For the actual contract data, you’d need access from the app that owns it.
Since the Shopify Subscriptions app doesn’t expose an API for third-party apps, if you need full programmatic access to subscription data, there are other subscription apps with more developer-friendly features. Recharge is one example.