Delivery is in calibration. Registration, signing, test events and replay all
work today, but live delivery to public endpoints is gated until the verdict rule
confirms calibration v1 on 2026-06-11. Register and test now — production
delivery switches on at the gate.
Why webhooks (vs WebSocket)
- WebSocket — you hold a connection. Best for read-only consumers with strict freshness needs (dashboards, agent runtimes).
- Webhooks — we push to your URL. Best for fire-and-forget reactions (notifications, automated risk pauses, audit logging). No connection to maintain.
Quickstart
- Register a webhook via the dashboard at pegana.xyz/account/webhooks. Telegram Login required.
- Implement signature verification at your endpoint (see signing).
- Test with the dashboard’s “Send test event” button.
Payload shape
The body is JSON, exactly:| Field | Type | Notes |
|---|---|---|
asset | string | Symbol (e.g. USDC, jitoSOL) |
from_state | string | One of PEGGED, DRIFT, DEPEG, CRITICAL, BLACK_SWAN, UNKNOWN |
to_state | string | Same enum |
discount_bps | integer | Spread at trigger, basis points, signed |
ts | string | ISO 8601 timestamp of the state change |
alert_id | string | UUID. Use for idempotency. |
HTTP headers we send
ed25519: prefix on the signature value — your verifier strips it before
base64-decoding. See signing for the full algorithm.
We do not ship the public key in a header on every request. Active keys are
published at https://api.pegana.xyz/v1/meta/webhook-keys; your verifier should
cache that list or read it from an env override.
URL requirements
- Must be
https://— we refuse HTTP - We SSRF-guard the URL: rejects private IP ranges (10.x, 172.16.x, 192.168.x),
localhost,
*.local,*.internal, and metadata endpoints - Returns must be 2xx for the delivery to count as successful. 3xx redirects are not followed
- We expect a response within 10 seconds. Beyond that, treated as failed and retried
What to do in your handler
A robust receiver does three things, in order:- Verify the signature (webhooks-signing)
- Check
x-pegana-timestampis within ±300 seconds of now (replay protection) - Idempotency: check
x-pegana-event-idagainst your local record — if seen already, return200 OKwithout re-acting
Retry policy
Failures (non-2xx, timeout, TLS error) trigger retries. Dispatcher config (crates/dispatcher-rs/src/main.rs):
max_attempts: 6, backoffs [5s, 30s, 5m, 30m, 2h].
| Attempt | Wait before this attempt |
|---|---|
| 1 (initial) | 0s |
| 2 | 5s |
| 3 | 30s |
| 4 | 5m |
| 5 | 30m |
| 6 | 2h |
Example receivers
We ship reference receivers in three languages, each with full verification logic (production code, not docs prose):TypeScript / Cloudflare Worker
Web Crypto API. Works on edge, Vercel functions, Node 18+.
Rust / axum
ed25519-dalek strict-mode verification.Python / FastAPI
cryptography library.Listing and managing webhooks
pegana.xyz/account/webhooks exposes the same actions plus
delivery history.
Next
Signing details
Ed25519 algorithm, signing input format, public key.
Retry policy
Failure modes, backoff schedule, and replay.