Webhook delivery
Send Viewport inbox, workflow, and audit events to your own systems with signed outbound delivery.
If Slack isn't enough, or you want Viewport events in your own system, set up an outbound webhook endpoint. Viewport POSTs a signed JSON payload to your URL for the subscribed event families.
This page is about outbound event delivery from Viewport. If you want an external system such as Jira, GitHub, or Linear to start a workflow run, connect the provider from Settings -> Integrations and create a workflow with that trigger. Advanced trigger routes verify signed events, map them into workflow inputs, and queue a run on a trusted runner.
What you can subscribe to
| Event family | Examples |
|---|---|
inbox_item.* | created, resolved, dismissed, timed_out |
plan.* | submitted, approved, denied, revised |
approval_gate.* | requested, approved, denied |
context.* | candidate_proposed, candidate_approved, candidate_discarded |
workflow_run.* | started, step_started, step_completed, failed, completed |
audit.* | All audit events. Pick when you want a SIEM-style firehose. |
member.* | invited / removed / role_changed |
machine.* | paired / revoked |
You can subscribe per-event-family or to a wildcard (audit.*).
Create an outbound endpoint
Settings -> Integrations -> Webhooks -> New endpoint.
Name: Linear bridge
URL: https://linear-bridge.acme.dev/viewport
Events: inbox_item.created, plan.approved, plan.denied
Secret: auto-generated (rotate any time)Save the endpoint and send a test delivery from the delivery details view before relying on it for production notifications.
Payload shape
POST /viewport HTTP/1.1
Content-Type: application/json
X-Viewport-Event: inbox_item.created
X-Viewport-Delivery: dlv_01J7…
X-Viewport-Signature: t=1715000000,v1=sha256_hex_signature
X-Viewport-Workspace: 01J7M8N9P0Q1R2S3T4U5V6W7X8
{
"type": "inbox_item.created",
"id": "evt_01J7…",
"occurred_at": "2026-05-11T14:42:00Z",
"workspace": {
"id": "01J7M8N9P0Q1R2S3T4U5V6W7X8",
"slug": "acme",
"name": "Acme Engineering"
},
"actor": {
"type": "system",
"kind": "agent_request"
},
"subject": {
"type": "inbox_item",
"id": "ibx_01J7…",
"kind": "plan_review",
"session_id": "ses_01J7…",
"preview": "Refactor auth middleware to bearer tokens.",
"expires_at": "2026-05-11T15:42:00Z",
"decision_url": "https://app.getviewport.com/inbox/ibx_01J7…"
}
}Signature verification
Every payload is signed. Compute the expected signature:
signed_payload = "{timestamp}.{raw_body}"
expected = HMAC-SHA256(secret, signed_payload)Compare against v1=… in X-Viewport-Signature. Reject if mismatch, or if t is older than 5 minutes (clock skew + replay protection).
Example (Node):
import crypto from 'node:crypto';
function verify(req) {
const sig = req.headers['x-viewport-signature'];
const [tPart, v1Part] = sig.split(',');
const t = tPart.replace('t=', '');
const v1 = v1Part.replace('v1=', '');
const expected = crypto
.createHmac('sha256', process.env.VIEWPORT_WEBHOOK_SECRET)
.update(`${t}.${req.rawBody}`)
.digest('hex');
return (
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1)) &&
Math.abs(Date.now() / 1000 - Number(t)) < 300
);
}Retries
If your endpoint returns non-2xx or times out (default 5s):
- 1st retry: 5s after the initial attempt.
- 2nd retry: 30s.
- 3rd retry: 5 min.
- 4th retry: 30 min.
- 5th retry: 2 hours.
After the 5th failed retry, the delivery is parked. You'll see it in Settings -> Integrations -> Webhooks -> Failed deliveries with the response body for debugging.
To replay a failed delivery, click Resend in the UI.
If you are building against the API directly, treat the resend endpoint as beta while the delivery UI is still changing:
POST /api/workspaces/{workspace}/webhooks/{endpoint}/deliveries/{delivery}/resendIdempotency
Every delivery has an X-Viewport-Delivery id. If you re-receive it (because of retries or replays), treat it as the same event. The consumer is expected to be idempotent.
Rate limits
Viewport limits webhook deliveries to 100 requests/second per endpoint. Bursts above that are queued. If you sustain over 100rps you'll see deliveries lag; contact us for higher limits.
Use cases
- Linear bridge: create a Linear issue when a plan is denied with a comment.
- PagerDuty: page on-call when an approval gate times out for a
prodworkflow. - Custom dashboard: aggregate session activity, mean-time-to-decide, by team or by repo.
- SIEM ingest: subscribe to
audit.*and forward to Splunk / Datadog.
Where to go next
- Provider integrations. The inbound event and brokered writeback model.
- Reference: Webhooks. Full event schema reference.
- Slack integration. The simpler path if Slack is enough.
- Audit log.