Outpost logoOutpost Docs

Webhooks

Push Outpost events to your own systems via HTTP callbacks.

Webhooks forward Outpost events to downstream systems through HTTP callbacks. Instead of polling for message outcomes, your service registers an endpoint and Outpost pushes notifications - message delivered, message failed, phone opted out - as they happen.

In the dashboard: webhook configurations are managed per project, see Managing Tenants & Projects.

How they relate

Webhook configs live on projects - the same boundary that owns API keys and produced the traffic. Each config declares a destination URL (HTTPS only), optional auth (Bearer or Basic), custom headers, and an explicit list of subscribed event types.

What you can subscribe to

  • Message events - the full lifecycle: QUEUED, PROVIDER_ACCEPTED, DELIVERED, ATTEMPT_FAILED, FAILED, BLOCKED, and the rest. ATTEMPT_FAILED fires when a delivery attempt fails but the message still has attempts remaining; FAILED fires exactly once, when the message settles as failed for good.
  • Phone events - only OPTED_OUT and OPTED_IN are webhook-eligible. Because phones are global, an opt-out is delivered to every project that has messaged that phone (each project's configs are evaluated independently).

Subscriptions are explicit: a config with no subscriptions receives nothing.

The delivery request

Deliveries are POST requests with a versioned JSON payload containing the event fields plus fresh context - a message object (status, isSettled, cost, attempt count, your metadata bag) for message events, or a phone object (opt-out state, validation state, carrier) for phone events. isSettled lets you tell a terminal FAILED apart from an in-progress retry without re-deriving it from status alone.

Every delivery carries identifying headers, including:

HeaderUse
x-outpost-eventThe event type - route on this
x-outpost-delivery-idUnique per attempt - deduplicate on this
x-outpost-project-idWhich project's config produced this
x-outpost-payload-versionPayload contract version (currently 1)

These header names are reserved and cannot be spoofed by custom header config.

Correlating with your own systems

Set metadata on your send request (items[].metadata) - Outpost never interprets it, but echoes it back inside the message context on every webhook delivery for that message.

Delivery semantics

  • A 2xx response marks the delivery SUCCEEDED; anything else marks it FAILED with the status code recorded.
  • Every attempt is persisted on the event record, so the dashboard can show exactly what was delivered where.
  • Failed deliveries are not currently retried automatically - design your endpoint to be available, and treat webhook data as a notification layer over the authoritative API.
  • A config can be paused without deleting it (endpoint.isActive: false); paused configs are skipped at fan-out time.

Managing configs

Webhook configs are managed as project subresources: GET/POST /v1/projects/:projectId/webhook-configs and GET/PUT/PATCH/DELETE on /v1/projects/:projectId/webhook-configs/:webhookConfigId. The outbound payload shape is also documented in the OpenAPI document's webhooks section.

API reference

Calling from TypeScript? See Generating a Typed Client.

On this page