Viewport daemon, relay, and hosted runtime are available in alpha. Surfaces may change.
VIEWPORT
For teams

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 familyExamples
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}/resend

Idempotency

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 prod workflow.
  • 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

On this page