CommerceHook

API

The REST API is the same surface the dashboard uses, authenticated with an API key instead of a session. Base URL: https://app.commercehook.app.

Prefer a client? Download the OpenAPI specification and import it straight into Postman, Insomnia, Bruno, or Hoppscotch to get a ready collection of every request.

Authentication

Create a key in settings (it is shown once, at creation) and send it as a bearer token:

Authorization: Bearer chk_your_key_here

Keys grant full access to your account’s endpoints and events. Revoke a key in settings at any time; revocation is immediate.

Key-authenticated requests are limited to 120 per minute per key. Over the limit you receive a 429 with a Retry-After header saying how many seconds to wait.

Endpoints

Create an endpoint:

curl -X POST https://app.commercehook.app/api/endpoints \
  -H "Authorization: Bearer chk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production store"}'

Returns 201 with id, name, url (the address to register as your webhook destination), createdAt, and eventCount. Free plan limits apply: creating a second endpoint on Free returns 403.

List endpoints:

curl https://app.commercehook.app/api/endpoints \
  -H "Authorization: Bearer chk_your_key_here"

Each entry carries eventCount and lastReceivedAt (epoch milliseconds, null until the first delivery).

Rename with PATCH /api/endpoints/{id} and a {"name": "..."} body; delete with DELETE /api/endpoints/{id}. Deleting an endpoint removes its stored events immediately.

Events

List events for an endpoint, newest first:

curl "https://app.commercehook.app/api/events?endpointId={endpoint_id}" \
  -H "Authorization: Bearer chk_your_key_here"

Query parameters:

  • limit: 1 to 100, default 25
  • cursor: opaque pagination token from the previous response’s nextCursor (null when there are no more pages)
  • q: free-text search over the event type and payload

Each event summary carries id, eventType, platform, method, receivedAt, and a payload preview. Fetch one event in full, including the headers and the raw payload exactly as delivered:

curl https://app.commercehook.app/api/events/{event_id} \
  -H "Authorization: Bearer chk_your_key_here"

headers is what arrived with two exceptions: a credential header (Authorization, Cookie, Proxy-Authorization) has its value replaced by [redacted], and the headers Cloudflare adds in transit (cf-*, x-forwarded-*, x-real-ip, true-client-ip) are not stored. Signature headers are kept exactly as sent.

This pair of routes is also how a system that cannot accept inbound HTTP consumes webhooks at all: point the platform at CommerceHook and pull events on your own schedule. The pattern, with a worked loop, is in Consume webhooks by polling.

Export

Download an endpoint’s whole stored history as a file, streamed oldest first:

curl -OJ "https://app.commercehook.app/api/endpoints/{endpoint_id}/export" \
  -H "Authorization: Bearer chk_your_key_here"

Query parameters:

  • format: json (default) or har. JSON carries the endpoint’s metadata and every event with headers, query string, and the raw body exactly as delivered. HAR is a standard HAR 1.2 capture, so the file opens directly in browser devtools (Network tab, import) and anything else that reads HAR.
  • q: the same free-text filter as the event list, for exporting just a slice (“only the order.updated ones”).

The response streams, so a large history downloads without a timeout, and Content-Disposition names the file commercehook-{endpointId}.json or .har (curl -OJ keeps that name). How much history there is to export is set by your plan’s retention window. Both formats are also available from the endpoint page in the dashboard, under the event list.

Replay

Re-fire a stored event at any destination, typically your real handler once you have fixed it:

curl -X POST https://app.commercehook.app/api/events/{event_id}/replay \
  -H "Authorization: Bearer chk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-handler.example.com/webhooks"}'

The original payload, method, and platform headers are reproduced exactly; headers added in transit (Cloudflare’s, forwarding artefacts) and credential headers (stored redacted, so there is nothing real to send) are not, and an x-commercehook-replay header carries the original event id so your handler can tell replays from live traffic. The response reports what the destination did: ok, its status, durationMs, and the first 500 characters of its response body. A destination that answers with an error status is still a successful replay; 502 means it could not be reached at all.

Account

GET /api/me returns your account id, email, and plan; it is also the simplest way to check a key works.

Errors

Errors are JSON with an error message and a conventional status: 400 for invalid input, 401 for a missing or revoked key, 403 for plan limits, 404 for anything that is not yours (existence is never confirmed).