For the complete documentation index, see llms.txt. This page is also available as Markdown.

Webhooks and signed event delivery

Register and store the secret

POST /v2/webhooks/subscriptions with your HTTPS URL and desired event types:

{
  "url":"https://your-service.example.com/webhooks/stackai",
  "event_types":["run.succeeded","run.failed"]
}

Use an authorized credential with org.webhooks.manage. Store the signing secret returned at creation immediately; list responses cannot recover it. To replace a lost secret, create a replacement subscription and retire the old one carefully. There is no PATCH subscription operation in this contract.

Completion notifications and availability

Use GET /v2/runs/{run_id} as the supported way to observe a workflow's completion. Creating a webhook subscription stores its URL and selected event names; it does not enable run-event delivery. Do not replace polling with a subscription when building a run-status integration.

Capability
What you can rely on

Create, list, and delete subscriptions

Manage the URL and accepted event types through the subscription endpoints

Observe completion of a run

Poll the run until it reaches a terminal status

Receive a run lifecycle notification

Subscription creation alone does not establish this capability; it is not a replacement for run polling

Replay a delivery or inspect delivery history

No public replay or delivery-history endpoint is provided

Accepted subscription event names are run.started, run.step.succeeded, run.step.failed, run.succeeded, run.failed, and run.cancelled. These names describe subscription filters, not a guarantee that an event will be produced for every run. The receiver guidance below applies when webhook deliveries are enabled for your deployment.

Authenticate deliveries, then deduplicate

Deliveries use the Standard Webhooks headers webhook-id, webhook-timestamp, and webhook-signature. Verify against the exact raw request body and the subscription's whsec_... secret before parsing or processing. Use a Standard Webhooks verifier with timestamp validation; JSON reserialization changes the bytes and can break verification.

Conceptual Python handler logic with the standardwebhooks package:

from standardwebhooks.webhooks import Webhook

# raw_body and headers come from your HTTP framework.
# secret comes from your secret manager, never from the incoming request.
verified_event = Webhook(secret).verify(raw_body, headers)
event_id = headers["webhook-id"]
# Atomically persist event_id and enqueue work only if it is new.
# Return 2xx after durable acceptance; process the work asynchronously.

Catch verification errors and reject invalid requests. Use durable, atomic deduplication; an in-memory set is insufficient across workers or restarts. Preserve the verified event's ID with your processing record. Retries reuse the same event ID and body. Do not assume event order or exactly-once delivery.

Successful 2xx responses acknowledge delivery. Redirects are not followed. Retryable client/server failures and transport failures can be retried; the current implementation has a bounded ladder of up to ten attempts with jitter. Return a suitable transient failure when you cannot durably accept work, rather than 200 and silently losing it. A 503 with numeric Retry-After can influence retry timing within server limits.

GET subscriptions to inventory active endpoints; DELETE a subscription to stop deliveries and remove it from that list. There is no public delivery-history or replay endpoint in this contract.

Last updated

Was this helpful?