Webhooks

Subscribe to budget, Guardian, payment, key rotation, and account events. Signed payloads with retry.

HiWay can POST events to your endpoint as they happen, Guardian fires, budget thresholds crossed, payment failures, API keys rotated, account balance low. Configure one or more webhooks per workspace, optionally filter to specific event types, and verify payloads with a shared secret.

Available events

EventFired whenPayload includes
guardian.blockA Guardian rule blocks or throttles a request.rule name, workspace, key, request hash, action taken
budget.alertBudget Control crosses a verdict threshold (warn / downgrade / block).cap, spent, verdict, period reset date
payment.succeededA Stripe top-up or subscription invoice is paid.amount, currency, invoice ID, new wallet balance
payment.failedStripe reports invoice.payment_failed.amount, currency, failure code, attempt count
key.rotatedAn API key is rotated or revoked.key ID, key prefix, rotated_at
account.low_balanceWallet balance crosses 20%, 10%, or 0% of the last top-up.balance, last_topup, percentage tier (20/10/0)
security.event (Security Shield)Threat detected in monitor or block mode (see Security Shield SIEM docs).threat_type, score, action, req_id, hashed prompt

Configure a webhook

curl -X POST https://app.hiway2llm.com/api/v1/workspaces/WS_ID/webhooks \
  -H "Authorization: Bearer hw_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name":   "Production alerts",
    "url":    "https://your-app.example.com/hooks/hiway",
    "secret": "whsec_replace_with_a_long_random_string",
    "events": ["guardian.block", "budget.alert", "account.low_balance"]
  }'

Omit events to receive all event types. Pass an empty list to pause delivery without deleting the webhook.

Payload format

json
{
  "event":        "guardian.block",
  "workspace_id": "01HXYZ...",
  "timestamp":    "2026-05-29T10:30:00Z",
  "data": {
    "rule":          "context_bloat",
    "key_id":        "kid_abc123",
    "request_hash":  "sha256:...",
    "action":        "blocked",
    "threshold":     200000,
    "observed":      234567
  }
}

Signature verification

Every request includes an X-HiWay-Signature header computed from the shared secret you configured. Verify it before processing, protect your endpoint against forgery.

import crypto from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader),
  );
}

Use the raw body

Compute the signature over the exact bytes of the request body, before any JSON re-serialization. Frameworks that parse JSON before exposing the body can silently re-format whitespace and break the signature.

Retry & delivery semantics

  • Timeout: 5 seconds per delivery attempt.
  • Retry on 5xx, 408, 429, or connection error. Exponential backoff: 1s, 5s, 30s, 5min, 30min (5 attempts max).
  • Non-retried: 2xx, 3xx (counted as success), 4xx (except 408/429, counted as a client config error, no retry).
  • Each retry includes the same event_id for idempotency. Treat receipts as at-least-once.
  • After 5 failed attempts, the webhook is marked stale and a webhook.stale event is sent to your other webhooks (if any) so you don't go silent.

Delivery monitoring

Each webhook tracks last_fired_at and last_status (the HTTP code from your endpoint's most recent response). Visible in Dashboard → Settings → Webhooks. If last_status consistently shows 4xx, fix your auth/endpoint. If last_status = 0, your endpoint is unreachable (DNS, TLS, firewall).