Guides

Delivery Scheduling

Publish an event now, but defer fan-out until a future time — useful for anything that needs to land at a specific moment rather than the instant you call the API.

Publishing for the future

Add an optional deliver_at field to the publish request — everything else about publishing stays the same.

curl
curl -X POST https://ingest.staging.lobthat.com/api/2026-06/app_01J0ZXYZ/events \
  -H "Authorization: Bearer whk_<your_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "order.created",
    "payload": { "order_id": "ord_123" },
    "deliver_at": "2026-08-01T09:00:00Z"
  }'
Stored immediately, delivered later
The Event is written durably the moment you publish it — deliver_at only defers when fan-out happens, not whether the event exists. If you never set it, behavior is exactly today's: fan-out happens right away.
RFC 3339, future, within 30 days
deliver_at must be a valid RFC 3339 timestamp, strictly in the future, and no more than 30 days out. Any violation — malformed, in the past, or too far out — is rejected at publish time with 400 invalid_deliver_at, before anything is written.

Cancelling before it fires

Event scheduled POST .../events/{event_id}/cancel fan-out never happens

Cancellation only works on an event that's still waiting — once fan-out has actually started, it's too late.

SituationResult
already_cancelledEvent was already cancelled — cancelling twice is rejected.
already_fanned_outFan-out has already happened (including an immediate, non-scheduled publish) — too late to cancel.
not_scheduledThe event was never given a deliver_at in the first place.

How it shows up in Delivery Logs

A scheduled event has its own visible states, distinct from the normal delivered/retrying/failed lifecycle that only applies once fan-out has actually happened.

StatusMeaning
scheduledWaiting for deliver_at — no delivery attempts exist yet, and none will until then.
cancelledCancelled before fan-out — will never be delivered.
pendingNot scheduled at all, just hasn't fanned out yet (today's existing meaning, unchanged).
fanned_outFan-out has happened — normal delivery/retry tracking takes over from here.
Under the hood, deferred fan-out uses the queue's own native delayed-processing option — there's no separate scheduler or cron sweep involved, so a scheduled event fires exactly once its time arrives, not on the next periodic check.