Automation
Deliver signed workspace events to your application.
Register HTTPS endpoints, subscribe to actual emitted events, inspect delivery history, and replay failed attempts.
Manage endpoints
/webhooksPro or Business/webhooksWorkspace endpoint limit applies/webhooks/:id/webhooks/:id/rotate-secret/webhooks/:idimport { veritas } from "@/lib/veritas";
const created = await veritas<{
webhook: { id: string };
secret: string;
}>("/webhooks", {
method: "POST",
body: JSON.stringify({
url: "https://example.com/api/veritas-webhook",
events: ["payment_link.paid", "verification.failed"],
}),
});
const webhookId = created.webhook.id;
// Store created.secret in your server secret manager.
const webhooks = await veritas("/webhooks");
await veritas(`/webhooks/${webhookId}`, {
method: "PATCH",
body: JSON.stringify({ active: false }),
});
const rotated = await veritas<{ secret: string }>(
`/webhooks/${webhookId}/rotate-secret`,
{ method: "POST" },
);
await veritas(`/webhooks/${webhookId}`, { method: "DELETE" });Delivery history
/webhooks/:id/deliveries/webhooks/:id/retry/:deliveryIdimport { veritas } from "@/lib/veritas";
const deliveries = await veritas(
"/webhooks/webhook_id/deliveries?page=1&limit=50",
);
await veritas(
"/webhooks/webhook_id/retry/failed_delivery_id",
{ method: "POST" },
);Delivery records move through queued, processing, retrying, succeeded, dead-letter, and cancelled states. Do not assume immediate delivery.
Events
Supported subscriptions are payment_link.paid, product.sold_out, verification.success, verification.failed, and webhook.dead_letter.
Verify signatures
Read X-Veritas-Signature. Its value is sha256=LOWERCASE_HEX_HMAC over the exact raw JSON bytes. Parse JSON only after verification.
import crypto from "node:crypto";
const webhookSecret = process.env.VERITAS_WEBHOOK_SECRET;
if (!webhookSecret) throw new Error("VERITAS_WEBHOOK_SECRET is required");
export async function POST(request: Request) {
// Verify the exact bytes received from Veritas before parsing JSON.
const rawRequestBody = Buffer.from(await request.arrayBuffer());
const signatureHeader =
request.headers.get("x-veritas-signature") ?? "";
const expectedHex = crypto
.createHmac("sha256", webhookSecret)
.update(rawRequestBody)
.digest("hex");
const expected = `sha256=${expectedHex}`;
const expectedBytes = Buffer.from(expected, "utf8");
const receivedBytes = Buffer.from(signatureHeader, "utf8");
const valid =
expectedBytes.length === receivedBytes.length &&
crypto.timingSafeEqual(expectedBytes, receivedBytes);
if (!valid) return new Response("Invalid signature", { status: 401 });
const event = JSON.parse(rawRequestBody.toString("utf8"));
// Handle the event and record its order/delivery ID before side effects.
console.log(event.event);
return new Response(null, { status: 204 });
}Retries and limits
Delivery attempts run immediately, then after 5, 15, and 45 seconds, with a 10-second request timeout. Active endpoints count toward the configured plan limit. Lowering a limit does not delete existing endpoints; it blocks creation or reactivation above the new capacity.