Webhooks
Sigmate POSTs every premium signal to your endpoint as soon as it fires. Each request is signed with an HMAC you can verify. Available on Pro and Alpha.
Setup#
- Open /dashboard/delivery and configure the Webhook card with your HTTPS URL.
- Copy the generated secret. It is shown once, then hashed on our side. Store it in your secret manager.
- Send the test ping and confirm your endpoint returns 2xx quickly. Sigmate treats any non-2xx response as a failure and records it on the dashboard.
Request format#
- Method. POST
- Content-Type.
application/json - X-Sigmate-Signature.
sha256=<hex>. Hex is the HMAC-SHA256 of the raw request body using your webhook secret. - X-Sigmate-Event. Always
signal.firedin v1. - User-Agent.
Sigmate-Webhook/1
Example payload#
The body schema matches the API stream signal frame. A trimmed example:
{
"id": "f3c7a1d2-8b4e-4d5f-9f2a-6e1c0d7a8b9f",
"detected_at": "2026-04-24T09:32:14.117Z",
"signal_type": "consensus_buy",
"rank": "A",
"rank_score": 82,
"token": {
"address": "7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr",
"symbol": "WIF",
"name": "dogwifhat",
"dex": "Raydium",
"market_cap_usd": 412000,
"liquidity_usd": 88300,
"price_usd": 0.0069
},
"wallet_count": 6,
"pool_wallet_count": 4,
"rug_check": {
"risk": "low"
},
"latency_ms": 388
}Verifying the signature#
Always verify the HMAC before trusting the payload. An attacker who learns your endpoint URL cannot forge a request without the secret.
Node.js / TypeScript
import crypto from "node:crypto";
const SECRET = process.env.SIGMATE_WEBHOOK_SECRET!;
// Inside your POST handler.
export function verifySigmate(req: Request, rawBody: string): boolean {
const header = req.headers.get("x-sigmate-signature") ?? "";
const match = header.match(/^sha256=([a-f0-9]{64})$/i);
if (!match) return false;
const expected = crypto
.createHmac("sha256", SECRET)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(match[1], "hex"),
);
}Python
import hmac, hashlib, re
SECRET = os.environ["SIGMATE_WEBHOOK_SECRET"].encode("utf-8")
def verify_sigmate(request) -> bool:
header = request.headers.get("x-sigmate-signature", "")
match = re.match(r"^sha256=([a-f0-9]{64})$", header, flags=re.I)
if not match:
return False
expected = hmac.new(SECRET, request.body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, match.group(1))Use the raw body
You must compute the HMAC over the exact raw bytes of the request body, not a re-serialized JSON object. If your framework parses JSON before your handler runs, reach for the raw-body middleware or equivalent before verifying.
Retries and idempotency#
- On non-2xx or timeout, Sigmate retries up to 3 times with a short backoff. After that, the failure is recorded on your dashboard and the signal is dropped from the webhook channel (other channels you have enabled are unaffected).
- Every payload carries a unique
id. Deduplicate on that field if your handler is not idempotent by construction. - Timeouts: Sigmate closes the connection after 5 seconds. Keep your handler fast, or offload heavy work to a queue and 2xx immediately.
Rotating the secret#
On the delivery page, click Rotate secret. The new secret is shown once, the old one stops being accepted immediately. Re-deploy your endpoint with the new value before rotating to avoid missed verifications.
Disabling#
Toggle the Webhook card off to pause delivery without deleting the configuration. Turn it back on and signals resume within a few seconds.