Webhooks
Apps/Connections/Webhooks

Webhooks

A signed JSON event posted to your URL when an action runs, a record changes, a deploy goes live or a store installs the app.

Endpoints

Add endpoints on the app's Settings → Webhooks. Each takes one environment or both, and every event or only the types you choose (All events includes types added later). Send test queues a webhook.test event (from development, for an endpoint that takes both); Recent deliveries shows how each delivery went.

An app's endpoints are separate from the team's webhooks: the team's events never reach them, and an app's events never reach the team's. The team's endpoints get their own events about apps instead.

Events

TypeWhendata
action.succeededAn action finished: its run and any write it made are done (also when only onSuccess failed).model, action, action_type, record_id, duration_ms, error (null)
action.failedAn action threw, its write was refused, it timed out or the app didn't answer. Nothing it asked for was saved.The same, with error set
record.created, record.updated, record.deletedA record was written: by an action, the API, the MCP server, the dashboard or the Shopify sync. A backfill writes quietly and sends none.model, record_id, fields (names only), by_action
deploy.succeededProduction's new build is live, or a rollback finished.version, url (or rollback: true)
deploy.failedProduction's build failed, timed out or was canceled. The version that was live stays live.version, state, note
build.failedDevelopment's dev server didn't start.name, version, note
shopify.release_failedThe Shopify app's configuration or storefront blocks weren't accepted.shopify_app, reason, storefront_blocks_only, note
shop.installedA store installed the app.shop, scopes
shop.uninstalledA store uninstalled it.shop
webhook.testSent by Send test.

Payloads never carry record values, action params or logs, which can hold what the app keeps secret. A record event names the changed fields; read the values through the API with a linked key.

Payload

Every event has the same shape. id is the event's id in the app's Logs; the same event is never sent twice to an endpoint, but treat a repeated id as already handled.

{
  "id": "evt_01k…",
  "type": "record.updated",
  "occurred_at": "2026-10-17T14:03:22.418Z",
  "app": { "id": "app_…", "slug": "reviews" },
  "environment": "production",
  "data": {
    "model": "review",
    "record_id": "rec_…",
    "fields": ["status", "moderatedAt", "moderatedBy"],
    "by_action": "evt_01k…"
  }
}

Signing and delivery

Signing, retries and disabling are the same as for the team's alert webhooks: check the IB-Signature header with the endpoint's signing secret, answer 2xx within 10 seconds, and failed deliveries are retried on the same schedule. See Verify the signature and Delivery and retries.

The signing secret is shown once, when you add the endpoint. Endpoints must be public HTTPS URLs.

Team events

The team's own endpoints (Team → Webhooks) also get events about its apps as a whole, in the team's payload shape (id, type, created_at, data). The Webhooks page lists them under Apps, and an endpoint on All events gets them.

TypeWhendata
apps.plan.graceThe apps entered a 72-hour grace period: over the team's monthly budget, or the balance can't pay an Apps charge. Emailed too.plan, reason (over_budget or insufficient_balance), pauses_at
apps.plan.pausedThe apps paused: the grace period ran out, or Free's allowances were used up. Emailed too.plan, reason (also free_limit)
apps.plan.resumedApps in a grace period or paused run normally again. Emailed too.plan, reason (what had held them)
apps.deploy.succeededA production deploy of one of the team's apps went live, or a rollback finished.app_id, app_slug, app_name, environment, version, url (or rollback: true)
apps.deploy.failedA production deploy failed, timed out or was canceled.The app fields, version, state, note