Docs / Actions & workflows
Webhooks and signatures
A webhook action POSTs JSON to the connection's https URL, with your extra headers, X-Jev-Delivery: <run id> and X-Jev-Signature: t=<unix seconds>,v1=<hex>. v1 is HMAC-SHA256 of "<t>.<raw body>" with the connection's signing secret (shown once when you add it). Reply 2xx within 5 seconds; 429 and 5xx are retried, other 4xx are final. Redirects are not followed, and private or internal addresses are refused.
Python
import hmac, hashlib, time
def verify(secret: str, header: str, raw_body: bytes, tolerance=300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts["t"])
if abs(time.time() - t) > tolerance:
return False
want = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, parts["v1"])
Node.js
const crypto = require('crypto');
function verify(secret, header, rawBody, tolerance = 300) {
const p = Object.fromEntries(header.split(',').map((x) => x.split('=')));
if (Math.abs(Date.now() / 1000 - Number(p.t)) > tolerance) return false;
const want = crypto.createHmac('sha256', secret).update(p.t + '.').update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(want), Buffer.from(p.v1));
}
Create an account Open the Playground
Everything here also lives in the console, next to your keys and usage.