Webacy Webhooks push risk events to your endpoint in real time. Instead of polling our API, you receive a signed HTTP POST the moment something happens.
Fires when a stablecoin or RWA token’s depeg risk tier changes (for example ok → warning or warning → critical). Tiers follow the Depeg Monitor ratings: ok, watch, warning, and critical, plus premium for tokens trading above peg.Use cases
Alert desks and treasury teams the moment a holding starts to depeg
Auto-hedging / de-risking triggers in trading systems
Webhook subscriptions are managed with your standard API key (the x-api-key header). Create a subscription, pick your filters, and we start delivering.
The secret_key is returned only on creation (and on rotate-secret). Store it securely — it is never shown again.
Filters (all optional, ANDed together):
Field
Meaning
tiers
Only notify when the new tier is one of ok / watch / warning / critical / premium
chains
Only notify for these chains (e.g. eth, polygon)
tokens
Only notify for these token contract addresses (case-insensitive)
minDeviationPct
Only notify when deviation from peg (percent) is at least this value
See the API reference for the full subscription and delivery endpoints (GET/PATCH/DELETE /webhooks/subscriptions/{id}, POST /webhooks/subscriptions/{id}/test, rotate-secret, and GET /webhooks/deliveries).
The signature is HMAC-SHA256 of the JSON-serialized event object (compact, no spaces), keyed by your subscription’s secret_key, hex-encoded. It is sent both as X-Webhook-Signature and as signature in the body. Always verify before trusting a payload.
Hash the event object exactly as received — don’t re-order keys or reformat numbers before serializing, or the digest won’t match.
const crypto = require("crypto");// secret = the subscription's secret_key (from creation/rotate-secret)function isValid(body, secret) { // reject missing/malformed signatures before any buffer work if (typeof body?.signature !== "string" || !/^[a-f0-9]{64}$/i.test(body.signature)) { return false; } const expected = crypto .createHmac("sha256", secret) .update(JSON.stringify(body.event)) // compact JSON of the event object .digest("hex"); // decode as hex (32-byte digests), not UTF-8; timingSafeEqual needs equal lengths const expectedBuf = Buffer.from(expected, "hex"); const providedBuf = Buffer.from(body.signature, "hex"); return expectedBuf.length === providedBuf.length && crypto.timingSafeEqual(expectedBuf, providedBuf);}// Express exampleapp.post("/webhooks/webacy", express.json(), (req, res) => { if (!isValid(req.body, process.env.WEBACY_WEBHOOK_SECRET)) { return res.status(401).end(); } // ...handle req.body.event... res.status(200).end(); // any 2xx acknowledges and stops retries});
Test your integration without waiting for a real event: POST /webhooks/subscriptions/{id}/test delivers a synthetic DEPEG_TIER_CHANGE to your endpoint.
Respond with any 2xx to acknowledge. A non-2xx response or timeout is retried with backoff, up to 5 attempts.
Inspect delivery history with GET /webhooks/deliveries (filter by status / eventType, paginated). Statuses include pending, success, failed, and max_retries_exceeded.
Re-send a failed delivery with POST /webhooks/deliveries/{id}/retry (rate-limited to once per delivery per 5 minutes).
webhookUrl must be a public HTTPS endpoint; private/loopback hosts are rejected.
Each subscription API call and each delivery consumes 1 CU.
DEPEG_TIER_CHANGE webhooks work with your existing API key. Don’t have one yet? Sign up at developers.webacy.co. For help sizing volume, email info@webacy.com.