Dome Systems

Webhooks

Subscribe to Dome events and deliver signed webhooks to your endpoints or off-the-shelf providers, with retries and replay

Webhooks deliver selected workspace events as signed HTTP POSTs to your HTTPS endpoint or a provider. A subscription chooses which events to send. A destination receives them.

Refer to Webhooks concept for how signed delivery works. Refer to Event contracts reference for the wire contract.

Overview

A subscription matches events by type and filter; the Event catalog marks which types are delivered. A destination receives them as signed HTTP POSTs. Create both in one call with subscriptions create, or attach a second subscription to an existing destination. Providers and custom URLs use the same model. Discover provider fields with dome webhooks providers list. Operating limits (body cap, rate, retention) are on Webhooks.

Webhook event_type values use the same names as Audit schema-v4 operations (agent.suspend, tool.call, guard.filter.evaluate). There is no access.denied type: subscribe to the operation and filter on result=denied. Retired names such as mcp.tool_call.completed and llm.output.filtered do not match.

The typical workflow is:

  1. Create a subscription and optional filters.
  2. Test the destination, then verify signatures on custom HTTPS endpoints.
  3. Inspect attempt history and replay failures when needed.
  4. Rotate the signing secret when credentials change.

Requirements

Before you begin, authenticate to Dome and select a workspace.

Permissions

Webhook operations require platform permissions. People and scoped API keys call the webhooks API. Agent credentials cannot.

Most roles can inspect subscriptions and deliveries. Creating destinations, rotating secrets, and changing subscriptions need eventing.manage. Replay re-sends requests to your systems and can trigger downstream automation, so it uses a separate eventing.replay permission.

Default rolesPermissionGrants
All workspace roleseventing.viewList and inspect subscriptions, deliveries, providers
admin, operatoreventing.manageCreate, update, disable, delete, rotate secrets, test, cancel retries
admin, operatoreventing.replaySingle and bulk replay

Create a subscription

Create a subscription and its destination atomically. A failed request leaves neither record behind. The response reveals the destination's whsec_… signing secret once. Store it before moving on. It is only rotatable afterward, never readable.

On the API, pass either delivery_endpoint (create a new destination) or destination_id (attach to an existing one). Never both. Standalone destination RPCs (ListDestinations, CreateDestination, UpdateDestination, RotateDestinationSecret, DeleteDestination) support shared-destination setups. CLI and MCP create the destination inline with the subscription. The dashboard can also pick an existing destination.

Requires eventing.manage.

Custom HTTPS endpoint:

dome webhooks subscriptions create alerts \
  --url https://ops.example.com/hooks/dome \
  --event-type agent.suspend \
  --event-type bundle.deploy

Slack via incoming-webhook URL:

dome webhooks subscriptions create slack-alerts \
  --provider slack \
  --setting webhook_url=https://hooks.slack.com/services/T.../B.../XXXX \
  --event-type agent.suspend \
  --event-type agent.revoke \
  --filter 'result=denied'

For provider-specific settings, credentials, shared destinations, MCP, and API examples, see the webhooks CLI reference.

Filters

You can narrow which events deliver. An event must satisfy every filter that applies to its type. A filter constrains only event types that carry its field.

Exact match

dome webhooks subscriptions create prod-only \
  --url https://... --event-type agent.suspend \
  --filter 'agent_name=checkout-worker'

Glob pattern (* any run, ? one char, full-value match)

dome webhooks subscriptions create demo-tools \
  --url https://... --event-type tool.call \
  --filter 'tool_name~=demo-mcp/*'

OR set (repeat the same key)

dome webhooks subscriptions create critical-agents \
  --url https://... --event-type agent.suspend \
  --filter 'agent_name=checkout-worker' \
  --filter 'agent_name=billing-worker'

Envelope filters apply to every event type: stage (attempted / completed), result (allowed / denied), denial.reason, and error (boolean presence). Payload filters include agent_name, connection_name (resolved from IDs at delivery time), agent_id, tool_name, plus each event type's own filterable fields. dome audit catalog and the dashboard Event catalog mark them. Repeated keys OR. Distinct keys AND. Caps: 16 keys, 16 alternatives per key, 256-byte patterns with up to 8 wildcards.

Per-request events (tool.call, guard.filter.evaluate, guard.validator.evaluate) are high volume. Point them at a log sink rather than a chat channel, and narrow with filters. model.call is on the audit trail and is not delivered as a webhook.

Test a subscription

Send a fixed eventing.test event through a subscription's destination to verify signing, headers, and the destination's own routing.

Requires eventing.manage.
dome webhooks subscriptions test alerts

The command prints the queued delivery ID. Check the outcome with dome webhooks deliveries get <id>.

Tool: dome_webhooks_subscription_test

Test a webhook subscription
Send a test event through the webhook subscription named alerts.

Verify a signature

Verify custom HTTPS deliveries with any Standard Webhooks library. Return 2xx within 10 seconds to acknowledge. Acknowledge first, process async. Slow handlers time out and burn retry budget.

import { Webhook } from "standardwebhooks";

const wh = new Webhook(process.env.DOME_WEBHOOK_SECRET); // whsec_...

app.post("/webhooks/dome", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = wh.verify(req.body, req.headers);
    // Dedupe on req.headers["dome-event-id"], then process async.
    res.status(202).send();
  } catch {
    res.status(400).send("invalid signature");
  }
});
from standardwebhooks.webhooks import Webhook

wh = Webhook(os.environ["DOME_WEBHOOK_SECRET"])  # whsec_...

@app.post("/webhooks/dome")
def receive(request):
    try:
        event = wh.verify(request.body, dict(request.headers))
        # Dedupe on request.headers["dome-event-id"], then process async.
        return HttpResponse(status=202)
    except Exception:
        return HttpResponse(status=400)

Inspect deliveries

Inspect delivery attempt history, including the retained body while it is available.

Requires eventing.view.

Failed deliveries in a time window:

dome webhooks deliveries list --status failed --start 2026-07-14T00:00:00Z

One delivery with attempt history and the retained body:

dome webhooks deliveries get <delivery-id> --body

Tools: dome_webhooks_delivery_list, dome_webhooks_delivery_get.

List failed webhook deliveries
List failed webhook deliveries since 2026-07-14T00:00:00Z.

Replay deliveries

Replay one delivery or bulk-replay failures in a window. A replay creates a new delivery from the retained body (fresh webhook-id, same Dome-Event-Id) so consumers that dedupe correctly ignore the overlap. Bulk replay processes up to 500 deliveries per run. Repeat to continue. Canceled deliveries are never recovered.

Requires eventing.replay.

Replay one delivery:

dome webhooks deliveries replay <delivery-id>

Bulk-replay terminal failures from the last 24 hours:

dome webhooks deliveries replay-failed --since 24h

Narrow by subscription and status:

dome webhooks deliveries replay-failed --since 7d --subscription alerts --status failed,dlq

replay-failed prints matched · replayed · skipped (body expired) · failed. It is safe to re-run: deliveries with a live or succeeded replay are not matched again.

Tools: dome_webhooks_delivery_replay, dome_webhooks_delivery_replay_failed, dome_webhooks_delivery_cancel.

{
  "name": "dome_webhooks_delivery_replay_failed",
  "arguments": { "since": "24h", "subscription": "alerts" }
}
POST /v1/webhooks/deliveries/replay-failed
Content-Type: application/json

{
  "workspace_id": "ws_...",
  "since": "2026-07-14T00:00:00Z",
  "destination_id": "dst_...",
  "statuses": ["failed", "dlq"],
  "max_deliveries": 500
}

The response returns matched, replayed, skipped_body_expired, and failed counts plus replay_delivery_ids. Also available: ReplayDelivery, CancelDeliveryRetry.

Reference: Eventing ReplayFailedDeliveries RPC
Replay failed webhook deliveries
Replay all failed webhook deliveries from the last 24 hours.

Rotate the signing secret

Rotate a destination's signing secret without dropping deliveries. For 24 hours, the webhook-signature header carries a signature per key (current first, previous second) so a consumer verifying with either secret keeps working. Update your verifier to the new secret within the 24-hour grace window.

Requires eventing.manage.
dome webhooks subscriptions rotate-secret alerts

The command prints the new signing secret once (whsec_…) with its key ID.

Tool: dome_webhooks_subscription_rotate_secret

Rotate a webhook signing secret
Rotate the signing secret for the webhook subscription named alerts.

Next steps

On this page

Was this page helpful?