Signing and Reliability
Sign event requests and handle replay protection.
POST /events/ingest verifies that the exact request body came from your system and has not been replayed.
Required headers
| Header | Value |
| --- | --- |
| x-event-signature | HMAC-SHA256 hex digest of the raw body. |
| x-event-timestamp | Current Unix time in seconds. |
| x-event-nonce | A new unique value for this HTTP attempt. |
Sign and send
import crypto from "node:crypto";
const payload = {
companyId: process.env.VERTEXY_COMPANY_ID,
eventSource: "checkout-service",
externalEventId: "evt_100001",
idempotencyKey: "evt_100001",
userId: "user_123",
eventType: "payment_succeeded",
timestamp: new Date().toISOString(),
metadata: {},
};
const body = JSON.stringify(payload);
const signature = crypto
.createHmac("sha256", process.env.VERTEXY_WEBHOOK_SECRET)
.update(body)
.digest("hex");
await fetch(`${process.env.VERTEXY_API_BASE_URL}/events/ingest`, {
method: "POST",
headers: {
"content-type": "application/json",
"x-event-signature": signature,
"x-event-timestamp": String(Math.floor(Date.now() / 1000)),
"x-event-nonce": crypto.randomUUID(),
},
body,
});Sign the exact bytes you send. Do not parse, reformat, or pretty-print the JSON after signing.
Retries and failures
Reuse the event idempotencyKey, but generate a new nonce and signature for each retry. Keep the timestamp current.
| Error | Meaning |
| --- | --- |
| Missing ingest signature | Signature header is absent. |
| Missing replay timestamp header | Timestamp header is absent. |
| Missing replay nonce header | Nonce header is absent. |
| Replay detected for nonce | The nonce was already used. |
| Invalid ingest signature | Digest does not match the raw body or company secret. |
Rotate the signing secret from Developer Settings or the endpoint documented in Authentication. Rotation invalidates the previous secret immediately.