Skip to main content

Webhooks (dev)

For end-user webhook setup, see Webhooks (user).

Register via GraphQL

mutation {
createWebhook(input: {
name: "my-system"
url: "https://my-system.example.com/vibe-webhook"
events: ["session.started", "session.terminated", "agent.disconnected"]
secret: "..."
retryPolicy: {maxAttempts: 6, backoff: "exponential"}
agentIds: [] # empty = all agents in workspace
}) { id signingKey }
}

Delivery contract

PropertyValue
MethodPOST
Content-Typeapplication/json
X-Vibecontrols-Delivery-IdUUID per delivery attempt (stable across retries)
X-Vibecontrols-Signaturet=<unix-ts>, v1=<hex-hmac-sha256>
RetriesPer webhook's retryPolicy
TrackingWebhook.deliveryCount + failureCount + lastDelivery + lastError

Verify signature

import {createHmac} from "crypto";

function verify(rawBody: string, sigHeader: string, secret: string): boolean {
const parts = Object.fromEntries(sigHeader.split(",").map(p => p.trim().split("=")));
const expected = createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
return expected === parts.v1;
}

Idempotency

Use X-Vibecontrols-Delivery-Id — store seen IDs and skip duplicates. Retries reuse the same ID.

Event payload shape

Each event has a stable JSON shape. The full payload schema for each event is documented under the GraphQL WebhookEventType enum in the live schema.

Next steps