Skip to main content
A hands-on walkthrough to receive real-time depeg alerts. By the end you’ll have a running endpoint that receives signed DEPEG_TIER_CHANGE events and verifies them. For the full API and event reference, see Webhooks.

What you’ll build

A small HTTP server that:
  1. Receives webhook POSTs from Webacy,
  2. Verifies the X-Webhook-Signature (so you only trust real events),
  3. Reacts to the tier change.
1

Get your API key

You use your standard Webacy API key (x-api-key). If you don’t have one, contact info@webacy.com. No webhook-specific setup is needed.
2

Build a receiver that verifies signatures

Each delivery is signed with HMAC-SHA256 over the JSON-serialized event object, keyed by your subscription’s secret_key, and sent in the X-Webhook-Signature header. Always verify before trusting a payload.
const express = require("express");
const crypto = require("crypto");

const app = express();
const SECRET = process.env.WEBACY_WEBHOOK_SECRET; // the secret_key from step 3

function isValid(body) {
  const expected = crypto
    .createHmac("sha256", SECRET)
    .update(JSON.stringify(body.event)) // compact JSON of the event object
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(body.signature),
  );
}

app.post("/webhooks/webacy", express.json(), (req, res) => {
  if (!isValid(req.body)) return res.status(401).end();

  const { data } = req.body.event;
  console.log(
    `${data.symbol} on ${data.chain}: ${data.old_tier} -> ${data.new_tier} (${data.deviation_pct}% off peg)`,
  );
  // ...trigger your alerting / hedging logic here...

  res.status(200).end(); // any 2xx acknowledges; non-2xx triggers retries
});

app.listen(3000);
Deploy this to a public HTTPS URL (private/loopback hosts are rejected). For local testing, a tunnel like ngrok or a webhook.site bin works.
3

Create a subscription

Point a subscription at your URL and pick filters. Save the secret_key from the response — it’s only returned once.
curl -X POST https://api.webacy.com/webhooks/subscriptions \
  -H "x-api-key: $WEBACY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://your-app.com/webhooks/webacy",
    "eventTypes": ["DEPEG_TIER_CHANGE"],
    "filters": { "tiers": ["warning", "critical"], "minDeviationPct": 1.0 }
  }'
Response (note id and secret_key):
{
  "id": "42",
  "webhook_url": "https://your-app.com/webhooks/webacy",
  "event_types": ["DEPEG_TIER_CHANGE"],
  "filters": { "tiers": ["warning", "critical"], "minDeviationPct": 1.0 },
  "secret_key": "store-this-now",
  "is_active": true,
  "created_at": "2026-06-22T18:00:00.000Z"
}
Set WEBACY_WEBHOOK_SECRET in your receiver to that secret_key.
4

Send a test event

Trigger a synthetic delivery so you don’t have to wait for a real tier change:
curl -X POST https://api.webacy.com/webhooks/subscriptions/42/test \
  -H "x-api-key: $WEBACY_API_KEY"
Your endpoint should receive a DEPEG_TIER_CHANGE POST and log it. If the signature check passes, you’re done — that’s the same path real events take.
5

Go live

  • Filters: tune tiers, chains, tokens, minDeviationPct to only get the alerts you care about.
  • Retries: failed deliveries retry up to 5 times with backoff. Inspect history with GET /webhooks/deliveries and re-send with POST /webhooks/deliveries/{id}/retry.
  • Secret rotation: rotate with POST /webhooks/subscriptions/{id}/rotate-secret. The previous secret stays valid for 24h (sent as X-Webhook-Previous-Signature) so you can roll without downtime.
  • Billing: 1 CU per management call and 1 CU per delivery.

The event you receive

{
  "event": {
    "event_type": "DEPEG_TIER_CHANGE",
    "event_id": "1a0d2b92-7142-44de-8a7c-7faa57c96df3",
    "timestamp": "2026-06-22T18:01:30.702Z",
    "data": {
      "token_address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
      "chain": "eth",
      "symbol": "USDT",
      "old_tier": "ok",
      "new_tier": "warning",
      "risk_score": 42.5,
      "deviation_pct": 1.8,
      "price_usd": "0.982",
      "peg_usd": "1.000"
    }
  },
  "signature": "<hmac-sha256-hex>",
  "delivered_at": "2026-06-22T18:01:30.702Z"
}
Headers: X-Event-Type: DEPEG_TIER_CHANGE, X-Webhook-Signature, X-Event-ID (use for idempotency).
Stuck on signatures? The string you sign is the compact JSON of the event object only (not the full body, no extra whitespace). The Node and Python snippets above do exactly that.