webhook_endpoint_url, signed with your app’s
client_secret. Delivery runs on the same signed, retrying pipeline as
Agent Gateway webhooks — the difference is that app webhooks are keyed
by your client secret, so you already hold everything needed to verify them.
Subscribing
You do not call a subscribe endpoint. Declare the topics you want on an app version’swebhook_topics, and set the delivery target as your app’s
webhook_endpoint_url. When a merchant installs an approved version, the platform
auto-registers those topics for that install and delivers to your endpoint.
Delivery format
Each event is aPOST to your endpoint with a signature header and a JSON envelope:
Verify the signature
The signature isHMAC-SHA256(client_secret, raw_body), hex-encoded and prefixed sha256=.
Compute it over the raw request bytes — not a re-serialized object — and compare in constant
time.
During the 72-hour secret-rotation grace,
signatures may be produced with either the new or the previous secret. If you have just rotated,
accept a body that verifies against either secret until you have fully cut over.
Retries
A delivery is considered successful on a2xx. Any network error or a >= 400 response is
retried — up to 5 attempts with exponential backoff. Make your handler idempotent:
de-duplicate on webhook_id, since a retry re-delivers the same event.
App lifecycle topics
Commerce topics
App versions may also subscribe to store-resource topics to react to merchant activity. Common ones:
See the webhook reference for the full topic catalog. Only topics your
app actually needs should appear on a version — unused subscriptions are noise the review team
will question.
Order payloads
orders/create is sent when checkout completes an order, on every payment method, to each app
installed on that store that subscribes to the topic. Each entry in line_items carries the
line’s line item properties as app_properties:
install_id is the install that received the delivery (the same id as app/uninstalled, the
compliance topics and the session token’s sid), so an order from a store your app has not seen
yet can still be attributed to the right install. app_properties is {} for a line without any. Entries arrive exactly as the cart API saved them,
private _ keys included. Read the entry under your own app handle.
Compliance payloads
The GDPR compliance topics (customers/data_request, customers/redact, shop/redact) use the
same envelope and signature as every other webhook. Public apps must
declare all three. Every compliance payload names the install it is
for:
shop/redact is sent 48 hours after an uninstall, and is not sent when the app was reinstalled in
that window. Delete everything you hold for the install:
customers/redact is sent when a merchant deletes a customer, to apps holding a customer or order
scope (customers:*, orders:*, draft orders, returns or checkout). Delete that customer’s data
and the listed orders’ personal data:
customers/data_request is sent when a merchant uses Request customer data on a customer’s
page (a customer asked what personal data the store holds), to the same apps. Send the data you
hold about that customer to the merchant (by email to the store’s contact address, or in your
app’s UI). It carries the same fields as customers/redact, with orders_requested in place of
orders_to_redact and data_request: { "id": "…" }:
Answering compliance webhooks
- Verify the signature first. Answer
401when it does not match (review sends a request signed with the wrong secret and expects401). - Answer
2xxas soon as you have accepted the request, then do the work. Finish it within 30 days. - A topic can go to its own URL: set
compliance_webhook_urlson the app (dtc app config). A topic without one goes to your webhook endpoint. - Failed deliveries are retried with backoff (1 minute, doubling, up to 6 hours between tries) for
about three days.
data_request.idandinstall_idstay the same on every retry, so use them to de-duplicate.