Webhook

Send events via HTTP POST to a URL endpoint. Outpost supports two webhook modes:

  • Default mode — Customizable headers and signature format
  • Standard Webhooks mode — Follows the Standard Webhooks specification

Creating a Webhook Destination

curl 'https://api.outpost.hookdeck.com/2025-07-01/tenants/<TENANT_ID>/destinations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_KEY>' \
--data '{
  "type": "webhook",
  "topics": ["user.created", "user.updated"],
  "config": {
    "url": "https://example.com/webhooks"
  }
}'

Configuration

Config

FieldTypeRequiredDescription
config.urlstringYesThe URL to send events to
config.custom_headersstringNoJSON object of custom HTTP headers to include

Credentials

FieldTypeRequiredDescription
credentials.secretstringNoSigning secret — auto-generated if not provided
credentials.previous_secretstringNoPrevious secret during a rotation window
credentials.previous_secret_invalid_atstringNoRFC 3339 timestamp when the previous secret expires

If secret is not provided, one is auto-generated. Tenants can trigger secret rotation but cannot set secrets directly.

Event Format

When you publish an event:

{
  "topic": "user.created",
  "data": { "user_id": "usr_123", "email": "user@example.com" },
  "metadata": { "source": "signup-service" }
}

Outpost sends an HTTP POST request:

POST /webhooks HTTP/1.1
Content-Type: application/json
x-outpost-id: evt_abc123
x-outpost-topic: user.created
x-outpost-timestamp: 1704067200
x-outpost-signature: t=1704067200,v0=abc123...
x-outpost-source: signup-service

{"user_id": "usr_123", "email": "user@example.com"}

The request body contains the event's data field as JSON. The metadata field is translated to headers using the configured prefix.

Signatures

Default Mode

The signature is computed over the timestamp and request body:

HMAC-SHA256(secret, "${body}")

The x-outpost-signature header value follows the format: v0=${signature}

To verify:

  1. Extract the timestamp and signature from the header
  2. Compute the expected signature using your secret
  3. Compare signatures using a constant-time comparison
  4. Optionally reject requests with old timestamps to prevent replay attacks

Standard Webhooks Mode

Follows the Standard Webhooks specification:

base64(HMAC-SHA256(secret, "${webhook-id}.${timestamp}.${body}"))

Use the official Standard Webhooks SDK to verify signatures. Secrets use the whsec_<base64> format.

Enable Standard Webhooks mode by setting DESTINATIONS_WEBHOOK_MODE=standard in the Config API or in Hookdeck Destinations settings.

Enable Standard Webhooks mode:

DESTINATIONS_WEBHOOK_MODE=standard

Secret Rotation

Rotate a webhook secret without downtime. During the rotation window, both the old and new secrets produce valid signatures.

curl --request PATCH \
'https://api.outpost.hookdeck.com/2025-07-01/tenants/<TENANT_ID>/destinations/<DESTINATION_ID>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_KEY>' \
--data '{
  "credentials": {
    "rotate_secret": "true",
    "previous_secret_invalid_at": "2025-01-15T00:00:00Z"
  }
}'

When rotation is triggered:

  1. The current secret becomes previous_secret
  2. A new secret is generated
  3. The previous secret remains valid until previous_secret_invalid_at (default: 24 hours)
  4. Both secrets appear in the signature header during the rotation window

Custom Headers

Tenants can add custom HTTP headers to webhook requests for authentication or routing:

curl 'https://api.outpost.hookdeck.com/2025-07-01/tenants/<TENANT_ID>/destinations' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <API_KEY>' \
--data '{
  "type": "webhook",
  "topics": ["*"],
  "config": {
    "url": "https://example.com/webhooks",
    "custom_headers": "{\"x-api-key\": \"secret123\"}"
  }
}'

Header names must start with a letter or digit and may contain letters, digits, underscores, and hyphens. The following headers cannot be overridden: content-type, content-length, host, connection, user-agent.

Custom webhook headers in the tenant portal are disabled by default. Enable them in Hookdeck User Portal settings.

Custom headers are disabled in the tenant portal by default. Enable with:

PORTAL_ENABLE_WEBHOOK_CUSTOM_HEADERS=true

Operator Configuration

Configure webhook operator behavior using these keys in the Config API or in Hookdeck Destinations settings: DESTINATIONS_WEBHOOK_HEADER_PREFIX, DESTINATIONS_WEBHOOK_DISABLE_EVENT_ID_HEADER, DESTINATIONS_WEBHOOK_DISABLE_TIMESTAMP_HEADER, DESTINATIONS_WEBHOOK_DISABLE_TOPIC_HEADER, DESTINATIONS_WEBHOOK_DISABLE_SIGNATURE_HEADER, DESTINATIONS_WEBHOOK_MODE, DESTINATIONS_WEBHOOK_SIGNATURE_ALGORITHM, DESTINATIONS_WEBHOOK_SIGNATURE_ENCODING, DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE, and DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATE.

Header Settings

VariableDefaultDescription
DESTINATIONS_WEBHOOK_HEADER_PREFIXx-outpost-Prefix for all webhook headers
DESTINATIONS_WEBHOOK_DISABLE_EVENT_ID_HEADERfalseDisable the event ID header
DESTINATIONS_WEBHOOK_DISABLE_TIMESTAMP_HEADERfalseDisable the timestamp header
DESTINATIONS_WEBHOOK_DISABLE_TOPIC_HEADERfalseDisable the topic header
DESTINATIONS_WEBHOOK_DISABLE_SIGNATURE_HEADERfalseDisable the signature header

Signature Settings

VariableDefaultDescription
DESTINATIONS_WEBHOOK_MODEdefaultSet to standard for Standard Webhooks compliance
DESTINATIONS_WEBHOOK_SIGNATURE_ALGORITHMhmac-sha256Signature algorithm
DESTINATIONS_WEBHOOK_SIGNATURE_ENCODINGhexEncoding: hex or base64
DESTINATIONS_WEBHOOK_SIGNATURE_CONTENT_TEMPLATE{{.Body}}Template for signed content
DESTINATIONS_WEBHOOK_SIGNATURE_HEADER_TEMPLATEv0={{.Signatures | join ","}}Template for signature header value