Skip to main content
Webhooks let Verial push structured events to your own HTTPS endpoint instead of requiring you to poll. The most common use is being notified when a benchmark run completes, so CI, dashboards, or Slack bots can react without keeping an open connection during the rollout.

How It Works

  1. You register an endpoint URL and subscribe it to one or more event types.
  2. When a matching event occurs, Verial signs the JSON payload and POSTs it to your URL.
  3. Your endpoint verifies the signature, deserializes the payload, and acts on the event.
  4. Non-2xx responses are retried with exponential backoff. Persistent failures are surfaced in the dashboard and the webhook is paused if a circuit breaker trips.

Set Up an Endpoint

Webhooks are managed from the organization dashboard under Webhooks.
  1. Click Add endpoint.
  2. Enter the destination URL (must be HTTPS).
  3. Paste or generate a shared secret. Save a copy; you will use it to verify signatures.
  4. Choose the event types to subscribe to.
  5. Save. The endpoint starts receiving events immediately.
You can also manage webhooks via the internal API (see Authentication for the organization key flow).

Event Types

The webhook delivery pipeline is in place, but no event types are published yet. The subscribable event catalog is empty today and will be populated as lifecycle events ship (benchmark-run and task-run completion are the expected first shipments, likely under dotted names such as run.completed). Consult your dashboard for the authoritative list once events are available.
Subscribe each endpoint to only the events it needs. Until event codes ship, you can still register endpoints and generate signing secrets so they are ready to receive traffic.

Payload Shape

Every webhook delivery carries a JSON body shaped like this:
{
  "id": "evt_01H...",
  "type": "run.completed",
  "timestamp": "2026-04-23T12:34:56.000Z",
  "data": {
    "...": "event-specific fields"
  }
}
  • id: unique event identifier. Use it to deduplicate; Verial may retry the same event on transient failures.
  • type: event type code (for example run.completed).
  • timestamp: ISO 8601 timestamp of when the event occurred.
  • data: event-specific payload. Resource fields are snake_case on the wire.

Signature Verification

Every request carries three headers:
HeaderDescription
X-Webhook-IdThe webhook endpoint’s ID (informational)
X-Webhook-TimestampUnix seconds when the request was signed
X-Webhook-SignatureSignature in the form v1=<hex>
The signature is an HMAC-SHA256 of ${timestamp}.${raw_body} with your shared secret. Verify it on the raw request body, before any JSON parsing.

Node.js

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyWebhook(
  rawBody: string,
  timestampHeader: string,
  signatureHeader: string,
  secret: string,
  toleranceSeconds = 300,
): boolean {
  // Reject stale requests
  const now = Math.floor(Date.now() / 1000);
  const ts = Number(timestampHeader);
  if (!Number.isFinite(ts) || Math.abs(now - ts) > toleranceSeconds) {
    return false;
  }

  const expected = createHmac("sha256", secret)
    .update(`${ts}.${rawBody}`)
    .digest("hex");

  const provided = signatureHeader.replace(/^v1=/, "");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(provided, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}
Always verify on the raw request body, not a re-serialized JSON string. In Express, use express.raw({ type: "application/json" }) for the webhook route; in Hono, read await c.req.text() before JSON.parse.

Retries and Delivery Guarantees

Delivery is at-least-once with exponential backoff. Verial retries on 5xx responses and network errors up to the webhook’s configured maxRetries (default 5). 4xx responses are treated as non-retryable: fix your endpoint and re-send from the dashboard if needed. A webhook with repeated failures has its circuit breaker tripped and delivery pauses until the endpoint recovers or an operator re-enables it. The dashboard surfaces last success, last failure, and consecutive failure count for every webhook. Return a 2xx response as soon as you have accepted the event. Do heavy work asynchronously; if your handler takes longer than the webhook’s timeoutMs (default 30 seconds), Verial will treat the delivery as failed.

Idempotency

Your handler should be idempotent on the id field of the event. Retries can redeliver the same event; deduplicate by recording id in a short-lived store (Redis set, database unique index, etc.).

Next Steps

Run Results

Drill into a completed run after you receive benchmark_run.completed.

GitHub Actions

Pair webhooks with CI to notify PR authors asynchronously.

Authentication

Manage the organization API key used to configure webhooks.

Benchmark Runs

Event payloads mirror the benchmark-run and task-run object shapes.