Skip to content

Webhooks

Webhooks are the generic destination — use them for any system that doesn’t have a native TapPass exporter yet (Datadog, Elastic, PagerDuty, a custom bus, …).

config/observability.yaml
exports:
- name: pagerduty-alerts
destination: webhook
format: json
webhook:
url: https://events.pagerduty.com/v2/enqueue
method: POST
headers:
Authorization: "Token token=${PD_ROUTING_KEY}"
Content-Type: application/json
body_template: |
{
"routing_key": "${PD_ROUTING_KEY}",
"event_action": "trigger",
"payload": {
"summary": "TapPass {{event_kind}} on {{agent_id}}",
"severity": "{{severity}}",
"source": "tappass",
"custom_details": {{event_json}}
}
}
filters:
min_severity: error
event_kinds: [policy_block, auth_fail]
retry:
max_attempts: 5
backoff_seconds: [1, 2, 4, 8, 16]

body_template supports Jinja-style interpolation against the audit event:

VariableExample
{{audit_id}}ae_01JC...
{{timestamp}}2026-04-17T10:15:03Z
{{event_kind}}policy_block
{{agent_id}}support-bot
{{severity}}warn
{{event_json}}Full event as JSON
{{policy_result.verdict}}Nested access

Send detections to Slack, auth failures to PagerDuty, everything to S3:

exports:
- name: slack-detections
destination: webhook
webhook:
url: "${SLACK_WEBHOOK_URL}"
filters:
event_kinds: [detection]
min_severity: warn
- name: pagerduty-auth
destination: webhook
webhook:
url: https://events.pagerduty.com/v2/enqueue
headers:
Authorization: "Token token=${PD_ROUTING_KEY}"
filters:
event_kinds: [auth_fail]
min_severity: error
- name: s3-archive
destination: webhook
webhook:
url: "${S3_WEBHOOK_BRIDGE_URL}"
filters: {} # everything

Webhooks retry on 5xx, connection errors, and timeouts. On permanent failure (max retries exhausted), events go to the dead-letter queue and a webhook.dlq event is raised — itself ship-able to another destination.

Terminal window
tappass observability test --export pagerduty-alerts

Sends one synthetic event. If your endpoint returns anything non-2xx, the CLI prints the response body.