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 25cursor: opaque pagination token from the previous response’snextCursor(nullwhen 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) orhar. 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 theorder.updatedones”).
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).