Subscribe a URL to what happens in a store; the Gateway POSTs a signed payload when it happens. No public URL? Pull the same events with GET /events (MCP: dtc_list_events).

Subscribe

MCP: dtc_create_webhook, dtc_list_webhooks, dtc_delete_webhook. The URL must be a public https:// address. A webhook is a standing channel that receives store data, so:
  • creating one needs store:write and the read permission of every event you subscribe to (the table below): a connection never receives what it could not read with its own tools;
  • an agent key must send approval_context {"merchant_confirmed": true} after the store owner agreed to the URL and the events — without it the call answers status: "pending_approval" and creates nothing;
  • the signing secret is returned once — store it.
Listing needs store:read; deleting needs store:write. An operator key with agent:admin can do all three.

Events

Store events (the first twelve) carry event_id, store_id, occurred_at and the ids and numbers you need to fetch the details with the matching tool (for example order_id, order_number, total_cents, currency; money is in cents). Delivery is at least once: deduplicate on data.event_id.

Pull instead of push

Call again with after=<next_cursor> to get only newer events. Results are limited to the events your connection may read. Events are kept for 30 days.

Delivery format

Verify the signature

The signature is HMAC-SHA256(secret, raw_body). Compare in constant time:
Verify against the raw request body (not a re-serialized object), and reject on mismatch. Deliveries retry with backoff on non-2xx responses.