Skip to main content

Webhooks

HTTP callbacks that deliver signed event notifications when project resources change.

Overview

A webhook is scoped to a project. When you create a webhook you specify a URL and a list of event patterns to subscribe to. The server dispatches matching events automatically, retrying up to three times for failed deliveries. Every delivery is signed with HMAC-SHA256 so receivers can verify authenticity.

Webhooks are outbound — SOAT calls your endpoint when events occur. For the inbound direction — an external system calling SOAT to activate an orchestration, agent, or tool — see Triggers, whose webhook starter verifies an incoming HMAC signature the same way.

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

Data Model

Webhook

FieldTypeDescription
idstringPublic identifier
project_idstringID of the owning project
policy_idstring | nullOptional 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
webhook_idstringPublic ID of the webhook this delivery belongs to
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 | nullResponse body returned by the receiver
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-updated timestamp

Key Concepts

Event Patterns

Each webhook subscribes to one or more event patterns using dot-separated hierarchy:

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

See it end to end in Chat with an LLM - Step 9 (Create a session webhook subscription).

Delivery

When an event matches a webhook, the server sends an HTTP POST to the webhook URL. 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 queryable through the API. To watch a real delivery arrive and inspect its outcome, see Chat with an LLM - Step 11 (Verify delivery).

Before pointing url at a real endpoint, use soat listen to receive and inspect deliveries on your local machine.

Secret and Signature Verification

Every webhook has a secret generated at creation time. The secret is returned in the response body on create or secret rotation. You can also retrieve it explicitly via GET /api/v1/webhooks/{webhook_id}/secret (requires webhooks:GetWebhookSecret).

To verify a delivery:

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

Attach a policy to a webhook to filter deliveries without changing your event subscriptions. Policies are global resources (not scoped to any project); when one is set on a webhook, the event is only delivered if the policy evaluates to allow for the event context.

Formation Support

Webhooks can be created as part of a Formation. The webhook secret can be captured as a formation output using a ref_attr expression:

{
"resources": {
"MyWebhook": {
"type": "webhook",
"properties": {
"name": "my-hook",
"url": "https://example.com/hook",
"events": ["*"]
}
}
},
"outputs": {
"webhookId": { "ref": "MyWebhook" },
"webhookSecret": { "ref_attr": "MyWebhook.secret" }
}
}

Examples

Create a webhook

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

List webhooks

soat list-webhooks --project-id proj_ABC