Skip to main content

Webhooks

The Webhooks module lets you subscribe to events that occur within a project and receive HTTP POST callbacks when those events fire. Every delivery is signed with HMAC-SHA256 so you can verify authenticity on the receiving end.

Overview

A webhook is scoped to a project. When you create a webhook you specify a URL, a list of event patterns to subscribe to, and optionally a project policy that gates delivery. The server automatically dispatches matching events, retrying up to three times for failed deliveries.

See the Permissions Reference for the IAM action strings for this module.

Key Concepts

Event Patterns

Each webhook subscribes to one or more event patterns. Patterns use a dot-separated hierarchy:

PatternMatches
file.createdExactly the file.created event
file.*Any event starting with file.
*Every event in the project

Delivery

When an event matches a webhook, the server sends an HTTP POST to the webhook URL with a JSON payload containing the event data. The request includes three headers:

HeaderDescription
X-Soat-EventThe event type (e.g., file.created)
X-Soat-DeliveryUnique delivery ID
X-Soat-SignatureHMAC-SHA256 hex digest of the request body, signed with the webhook secret

Deliveries are retried up to three times. Each attempt and its outcome are recorded in a delivery log that you can query through the API.

Secret and Signature Verification

Every webhook has a secret generated at creation time. To verify a delivery, compute the HMAC-SHA256 of the raw request body using the secret and compare it to the X-Soat-Signature header:

const crypto = require('crypto');

const isValid = (secret, body, signature) => {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
};

Policy Gating

You can optionally attach a project policy to a webhook. When a policy is set, the event is only delivered if the policy evaluates to allow for the event context. This lets you filter deliveries without changing your event subscriptions.

Data Model

Webhook

FieldTypeDescription
idstringPublic identifier
project_idstringID of the owning project
policy_idstring | nullOptional project policy that gates delivery
namestringHuman-readable name
descriptionstring | nullOptional description
urlstringHTTPS endpoint that receives deliveries
eventsstring[]List of event patterns to subscribe to
activebooleanWhether the webhook is enabled
secretstringReturned only on create and secret rotation
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-updated timestamp

Webhook Delivery

FieldTypeDescription
idstringPublic identifier
event_typestringThe event type that triggered the delivery
payloadobjectThe event payload that was sent
statuspending | success | failedDelivery outcome
status_codenumber | nullHTTP response status code
attemptsnumberNumber of delivery attempts made
last_attempt_atstring | nullTimestamp of the most recent attempt
response_bodystring | nullTruncated response body from the receiver
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-updated timestamp

Examples

Create a webhook

soat create-webhook \
--project-id proj_ABC \
--name "My Webhook" \
--url https://example.com/hook \
--events "sessions.*"