← All articles

Shopify abandoned checkout API and webhooks: what's available and how it fits together

5 October 2026 · 5 min read

We built Cartback on these APIs, and this is the map we wish we'd had on day one. It sticks to what Shopify documents, links the documentation for each piece, and flags the few places where our own testing adds something.

There is no "abandoned" event

The thing most people look for first doesn't exist: Shopify has no webhook that fires when a checkout becomes abandoned. The definition in the Abandoned Checkouts documentation is "a checkout is considered abandoned after the customer has added contact information, but before the customer has completed their purchase" — a state, not an event. In practice you subscribe to checkout events, watch for completion, and apply your own delay before treating a checkout as abandoned. (When the record first appears is covered in when does Shopify create an abandoned checkout.)

The webhooks

From the webhook topic list, these are the relevant topics:

TopicWhat it tells you
checkouts/createA checkout started. In our testing it fired within seconds of the shopper entering an email address.
checkouts/updateThe checkout changed — address, shipping, payment step. Also carries completed_at once the order is placed.
checkouts/deleteThe checkout was removed.
orders/createThe reliable completion signal: match it to the checkout and stop any pending reminder.
carts/create, carts/updateThe pre-checkout cart. No contact information — useful for analytics, not for reaching anyone.

The checkout payload carries what a recovery flow needs: an identifier and token, the cart_token that links it to the earlier cart, the shopper's email (once entered), total_price and currency, the line_items, completed_at, and abandoned_checkout_url — the link that returns the shopper to their checkout with everything still in it. It also carries buyer_accepts_marketing and a customer object with email_marketing_consent; treat those with care, because Shopify only records the checkout marketing checkbox at Pay now (details in this article).

Subscriptions are declared in the app configuration. This is the shape Cartback uses:

[[webhooks.subscriptions]]
uri = "/webhooks/checkouts/update"
topics = [ "checkouts/create", "checkouts/update" ]

[[webhooks.subscriptions]]
uri = "/webhooks/orders/create"
topics = [ "orders/create" ]

Two things we learned the hard way: webhooks can arrive more than once and out of order, so the handler has to be idempotent and should prefer completed_at over arrival order; and a handler must answer quickly with a 2xx, or Shopify retries and eventually drops the subscription — do the work after you've acknowledged.

The GraphQL Admin API

The abandonedCheckouts query lists abandoned checkouts, with fields such as the recovery URL and line items; the documentation states it requires the read_orders access scope. It's the right tool for backfilling when an app is installed and for reconciling your own records — not for timeliness. In our testing the listing lagged the webhook stream by hours, while the webhooks were immediate.

The REST resource (legacy)

GET /admin/api/{version}/checkouts.json — the Abandoned checkouts resource — still works, but Shopify marks the REST Admin API as legacy as of October 1, 2024 and requires new public apps to use GraphQL exclusively from April 1, 2025. New work should start on GraphQL.

Protected customer data

Abandoned checkouts are full of personal data, and Shopify treats it as protected customer data. Beyond the base approval, the shopper's name, address, phone and email are protected fields that have to be requested individually and come with data-protection requirements (encryption, retention limits, and a review before the App Store listing is approved). The practical consequence: if a feature only needs counts, totals or line items, don't request the fields — the approval is lighter and there's less to protect. An app that actually contacts the shopper can't avoid it; Cartback stores email addresses encrypted at rest for exactly this reason.

Retention and the compliance webhooks

Shopify deletes abandoned checkouts older than three months from the admin, so your own copy needs a retention rule rather than growing forever. Every app that touches customer data also has to answer the three mandatory compliance topics — customers/data_request, customers/redact and shop/redact — and the App Store checks for them.

Putting it together

  1. Subscribe to checkouts/create, checkouts/update and orders/create.
  2. Upsert the checkout by token on each event; mark it complete on completed_at or a matching order.
  3. After your chosen delay, if it's still open, send the reminder with abandoned_checkout_url.
  4. Backfill and reconcile with the abandonedCheckouts query; expire your records on your own schedule.

The delay in step 3 is the interesting design decision — it's the one thing Shopify leaves entirely to you. We've written about it in when is the best time to send an abandoned cart email.

Recover abandoned carts with coordinated, AI-timed email and web push — shopper email addresses encrypted at rest, no revenue-share pricing. Install Cartback free on the Shopify App Store →

More from the blog