Guides

Send events

Post an event once and let Dispatch fan it out to every subscribed customer endpoint.

Sending is one authenticated POST. Dispatch checks the event, finds the endpoints that should receive it, and queues one delivery for each.

curl -X POST https://api.getensue.com/v1/dispatch/events \
  -H "authorization: Bearer ens_live_…" -H "content-type: application/json" \
  -H "idempotency-key: order-1042-shipped" \
  -d '{
    "type": "order.shipped",
    "customer": "acme",
    "data": { "order_id": "1042", "carrier": "UPS" }
  }'

Request

Field Notes
type Required. An existing, non-archived event type.
data Required. A JSON object, validated against the type’s current schema.
customer Send only to this customer’s endpoints. Your external_id or a cst_… ID.
endpoint_id Send only to this endpoint (dst_…). It must be active and subscribed to the type.
idempotency_key Up to 200 characters. May also be sent as an Idempotency-Key header.

Response

202 Accepted once the message and its deliveries are stored:

{
  "id": "msg_…",
  "event_type": "order.shipped",
  "version": 1,
  "customer": "acme",
  "idempotency_key": "order-1042-shipped",
  "delivery_count": 2,
  "created": 1767225600000
}

202 means Ensue has the message durably. The deliveries are attempted straight afterwards and retried if they fail, so you never need to retry a send that was accepted. delivery_count is how many endpoints it was queued for; it can be 0 when nothing subscribes.

Who receives it

You send Delivered to
customer only That customer’s active endpoints subscribed to the type
nothing but type Every customer’s active endpoints subscribed to the type
endpoint_id Just that one endpoint, which must be subscribed

Paused endpoints are skipped. Sending to a paused endpoint by ID fails with 409 endpoint_paused, so a targeted send never silently goes nowhere.

What the endpoint receives

The delivered body is an envelope around your data:

{
  "id": "msg_…",
  "type": "order.shipped",
  "version": 1,
  "timestamp": "2026-11-10T09:30:00.000Z",
  "data": { "order_id": "1042", "carrier": "UPS" }
}

Along with the Standard Webhooks headers webhook-id, webhook-timestamp and webhook-signature. The webhook-id is the message ID and is the same on every retry, so customers can de-duplicate on it.

Idempotency

Network failures happen between your app and Ensue, too. Send an idempotency key that is stable for the thing that happened, such as the order ID plus the event name, so you can retry a send safely.

  • The same key with the same request answers 200 with the original message and "duplicate": true. Nothing is sent twice.
  • The same key with a different request answers 409 idempotency_key_reused, so a reused key can never silently swallow a different event.
  • Two simultaneous sends with one key resolve to one message.

Validation errors

A body that doesn’t match the schema answers 422:

{
  "ok": false,
  "error": "invalid_data",
  "message": "data doesn't match order.shipped v1: Required property 'order_id' not found",
  "errors": [{ "path": "/", "message": "Required property 'order_id' not found" }]
}

Nothing is sent and nothing is counted. See Limits and errors for every response.