Shopify Flow Trigger Lifecycle Callback Extensions: Relative URLs
No7 Engineering Team
Growth Architecture Unit

Shopify Flow trigger lifecycle callback extensions are app extensions that tell Shopify Flow where to send a lifecycle callback when a merchant tries to enable a workflow that uses your trigger. They now accept relative URL paths as well as absolute HTTPS URLs. That lets you test the callback against a local tunnel without hosting the endpoint first.
What changed for Shopify Flow trigger lifecycle callback extensions?
Shopify Flow now accepts relative URL paths for trigger lifecycle callback extensions. Running app dev resolves the path against your development tunnel URL, and app deploy resolves it against your app's application_url. Shopify's changelog says this works similarly to relative URLs with Flow action extensions.
Previously, the callback URL had to be an absolute HTTPS URL pointing to a web server. That required an already hosted system, which made testing locally before deployment awkward. With a dynamically tunnelled server, you also had to update the full URL with the app's application_url.
If you build Flow triggers, start with the endpoints your app already hosts: Shopify recommends a relative path for those, because your development tunnel URL can change each time you run app dev. For wider Flow design, see our guide to advanced Shopify Flow automation.
Who this update affects
The change affects app developers who build Flow triggers with lifecycle callbacks. When a merchant tries to enable a workflow that uses the trigger, Shopify Flow sends a lifecycle callback to the app's web server.
Your server has five seconds to answer, and the answer has to be a 2xx response. A slower reply, or any other status code, means the merchant can't enable that workflow. The merchant then sees a notification in the Shopify Flow app asking them to try again later.
Do existing callback extensions need action?
Extensions built with Shopify CLI need no change: relative URLs are supported in addition to absolute HTTPS URLs. The decision is per endpoint. Keep an absolute HTTPS URL, rather than a relative path, when the endpoint lives outside your app or must be the same in every environment. For an endpoint your app hosts, Shopify recommends a relative path. The exception is legacy trigger discovery webhook extensions created in the Partner Dashboard: they are deprecated and must be recreated with Shopify CLI before they can be edited.
Worked example: choosing the URL for one trigger callback
Take one trigger callback through each URL option:
- Endpoint on your app server: use a relative path that starts with a single slash, such as
/flow/lifecycle-callback. Shopify CLI resolves it against the tunnel inapp devand againstapplication_urlon deploy. - Endpoint on an external server: keep an absolute HTTPS URL, so Shopify Flow calls the same endpoint in every environment.
- Protocol-relative URL: replace forms such as
//example.com/flow/lifecycle-callback, because protocol-relative URLs aren't supported. - No HTTPS application_url yet: add an absolute HTTPS
application_urlto your app configuration before you deploy with a relative path. - Legacy extension from the Partner Dashboard: recreate it as a Shopify CLI extension before you change its endpoint, because the legacy extension can't be edited.
How to set up a trigger lifecycle callback endpoint
The steps below set the endpoint up, following Shopify's documentation.
- Configure the listener URL. Set up a route on your web server that listens for trigger lifecycle callbacks from Shopify Flow.
- Update the TOML. Change the
urlin the generated TOML to that endpoint. If your app hosts it, use a relative path such as/flow/lifecycle-callback. - Verify the HMAC header. Check it against your client secret. It arrives in
x-shopify-hmac-sha256, orhttp-x-shopify-hmac-sha256on a Ruby-based web framework. - Answer within five seconds. Return a 2xx response in time; a slower reply or another status code stops the merchant enabling the workflow. For handler design in general, see our guide to Shopify webhook retries and production failures.
- Track which stores use the trigger. Save them in a persistent datastore and send triggers only to those stores. Use the
timestampproperty so older information never overwrites a newer entry. - Test before production. Run
app dev, which applies changes automatically, or deploy to a test app first. - Deploy. The
app deploycommand resolves the relative path against your HTTPSapplication_urland also publishes the extension.
The full steps are in Shopify's trigger lifecycle events documentation. For what a trigger can drive once a merchant enables it, see Shopify Flow AI agent automation patterns.
What to do next
List every trigger your app ships and note where each callback endpoint lives. Switch the ones your app serves to a relative path when you next work on the extension, and leave externally hosted ones alone. Recreate any Partner Dashboard trigger with Shopify CLI before you next need to edit it.
Then time the callback handler: any reply slower than five seconds stops a merchant at the enable button. To have the triggers reviewed, talk to our Shopify development team.
Frequently Asked Questions
The questions buyers and engineers ask us most about this topic.
When should apps use relative URLs for Flow trigger lifecycle callbacks?
Use a relative path when your app hosts the callback endpoint: app dev resolves it against your development tunnel URL and app deploy against application_url. Use an absolute HTTPS URL when the endpoint is outside your app or you want Flow to call the same URL in every environment.
What happens if a trigger lifecycle callback server times out?
If the server does not answer within five seconds with a 2xx response, the merchant cannot enable the workflow and receives a notification in the Shopify Flow app to try again later.
What happens to legacy trigger discovery webhook extensions?
Legacy trigger discovery webhook extensions created in the Partner Dashboard are deprecated. They must be recreated with Shopify CLI before they can be edited, so recreate each one before you next need to edit it.