Skip to content
Browse documentation

Build

Publish API

Enqueue events into an endpoint with an API key instead of an inbound webhook signature.

POST /v1/endpoints/{id}/events accepts events from your own code. The API key replaces the inbound webhook signature: the endpoint’s HMAC, shared-secret or Basic Auth settings are not checked, and the stored event is marked signatureVerified: true.

Terminal window
curl -X POST "https://api.hooks.events/v1/endpoints/ep_abc123/events" \
-H "Authorization: Bearer $HOOKS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-42-created" \
-d '{
"payload": { "orderId": "ord_42", "total": 9900 },
"eventType": "order.created",
"headers": { "x-source": "checkout" }
}'

The key needs the endpoints:write scope. The body is strict:

Field Required Meaning
payload yes Any JSON value; serialized as the event payload
eventType no Overrides the type inferred from the payload
headers no Up to 50 extra headers, stored with the event and readable by templates
idempotencyKey no Same as the Idempotency-Key header
deliverAt no ISO 8601 UTC time for the first attempt; past values deliver immediately

Published events run through the same path as POST /in/{publicId}:

  • source normalization and provider extraction for the endpoint’s provider
  • endpoint inbound rate limit and rateLimitAction
  • workspace plan quota and payload-size caps
  • business dedupe, lifecycle received hooks and destination filters
  • delivery fan-out, task triggers and hooks listen relay

A filtered publish still returns 202 with status: "filtered" and writes the event for the audit trail, exactly like a filtered inbound webhook. A missing/archived endpoint answers 404, and a paused endpoint answers 410.

deliverAt schedules the first attempt instead of sending immediately. A destination’s own Initial delay (seconds) stacks on top: the later of deliverAt and now + delaySeconds wins. Scheduled deliveries show as scheduled with a planned time in the console, can be cancelled like any queued delivery, and are picked up by the one-minute scheduler (queue delays cover the first 12 hours).

Terminal window
-d '{ "payload": { "orderId": "ord_42" }, "deliverAt": "2026-11-06T10:00:00Z" }'

Send Idempotency-Key (or idempotencyKey in the body) to make retries safe. The key is stored as the event’s source delivery id, so a repeat submission returns the original eventId without creating a second event or delivery. Keys are scoped to the endpoint.

{
"eventId": "evt_01j9xk2m",
"status": "accepted"
}

status is accepted, filtered (with reason and per-destination rejections), or duplicate. Rate-limited publishes answer 429 with Retry-After.