Webhook delivery

Set channel_type: "webhook" and channel_target to an HTTPS URL. SCMon POSTs a JSON body and signs it so you can prove it came from us.

Webhook URLs must be public HTTPS endpoints. Private, loopback and link-local addresses are rejected (SSRF protection), and all outbound calls leave from a single stable egress IP you can allowlist.

Payload

{
  "event": "transfer",
  "chain": "bsc",
  "watch_id": "wch_…",
  "token": "0x55d398326f99059ff775485246999027b3197955",
  "direction": "in",
  "from": "0xsender…",
  "to": "0xyour_wallet…",
  "counterparty": "0xsender…",
  "amount": "1000000000000000000000",
  "tx_hash": "0x…",
  "log_index": 12,
  "block": 38217640,
  "ts": 1718700000
}

amount is raw base units (see Rules). counterparty is the other side relative to your watched address.

Verifying the signature

Each request carries an x-scmon-signature header:

x-scmon-signature: t=1718700000,v1=9f86d081884c7d659a2feaa0c55ad015a…

v1 is HMAC-SHA256(secret, "{t}.{rawBody}") as hex, where secret is your account’s webhook_secret (from GET /v1/account). Recompute it over the raw request body, compare in constant time, and reject a stale t to block replays.

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

function verify(rawBody, header, secret, toleranceSec = 300) {
  const parts = Object.fromEntries(header.split(',').map((kv) => kv.split('=')));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? '');
  return a.length === b.length && timingSafeEqual(a, b);
}

Delivery & retries

  • Respond 2xx quickly to acknowledge. Any non-2xx (or a timeout) is treated as failed and retried with backoff.
  • Delivery is paused if your credit balance can’t cover the alert — it resumes automatically after you top up.
  • Requests arrive with user-agent: scmon-webhook/1.0 and content-type: application/json.