For partners
Verify webhooks
Check the Standard Webhooks signature on the raw body, dedupe on id, and order by seq.
Each delivery carries webhook-id, webhook-timestamp and webhook-signature headers. Verify them against the raw request body before parsing; re-serialized JSON won’t match.
import { verifyWebhook, WebhookVerificationError } from "@emerald-relay/node";
export async function POST(req: Request) {
let event;
try {
event = verifyWebhook(await req.text(), req.headers, process.env.RELAY_WEBHOOK_SECRET!);
} catch (e) {
if (e instanceof WebhookVerificationError) return new Response("bad signature", { status: 400 });
throw e;
}
await queue.push(event); // respond fast; process asynchronously
return new Response(null, { status: 204 });
}Delivery rules
- At-least-once: the same event can arrive twice. Dedupe on
idand ack the repeat asDUPLICATE. - Order isn’t guaranteed. Apply events by
seqper agency; the pull feed is always in order. - Return 2xx within 10 seconds. Failures retry at 10s, 1m, 5m, 30m, 2h, 6h, then every 12h for up to 72 hours.
- Events are thin. Fetch the full object from
links.selfwith the install’s access token.