Documentation menuGetting started
Getting started
Install Vector, register an endpoint, send an event and verify it on the receiving side.
Install
pnpm add @sweberdev/vector
Vector needs Node.js 20.16 or newer for sending. Verifying also works in browsers, edge runtimes, Bun and Deno.
Send
import { createVector } from "@sweberdev/vector";
const vector = createVector();
// Usually done by your customer in your settings UI.
const endpoint = await vector.endpoints.create({
url: "https://example.com/webhooks",
tenant: "acme", // your customer's id
eventTypes: ["invoice.*"],
});
console.log(endpoint.secret); // whsec_... show this once to your customer
await vector.send({
tenant: "acme",
eventType: "invoice.paid",
payload: { invoiceId: "inv_123", amount: 4200, currency: "CHF" },
});
// Deliver everything that is due. In a server, use vector.start() instead.
await vector.process();
The endpoint receives a POST with this body:
{
"type": "invoice.paid",
"timestamp": "2026-10-05T12:00:00.000Z",
"data": { "invoiceId": "inv_123", "amount": 4200, "currency": "CHF" }
}
and the headers webhook-id, webhook-timestamp and webhook-signature.
createVector() without options keeps everything in memory, which is fine for trying it out. For production use the PostgreSQL store and run a worker.
Receive
// app/api/webhooks/route.ts (Next.js)
import { verifyRequest, WebhookVerificationError } from "@sweberdev/vector";
export async function POST(request: Request) {
try {
const { id, payload } = await verifyRequest(request, process.env.WEBHOOK_SECRET!);
// Use `id` to ignore duplicates, then handle payload.type and payload.data.
return new Response(null, { status: 204 });
} catch (error) {
if (error instanceof WebhookVerificationError) return new Response(null, { status: 401 });
throw error;
}
}
Your customers can use any Standard Webhooks library instead, in any language. See Receiving webhooks.
Try it locally
npx @sweberdev/vector secret # prints a new whsec_ secret
npx @sweberdev/vector listen --secret whsec_... # receiver on http://localhost:4000
In development, allow local URLs:
const vector = createVector({ urlPolicy: { allowPrivateNetworks: true } });