Skip to content

basalt / webhooks/src / WebhookManager

Class: WebhookManager ​

Defined in: webhooks/src/index.ts:261

Register/list subscriptions and dispatch events to matching endpoints.

Constructors ​

Constructor ​

> new WebhookManager(store, deliverer, options?): WebhookManager

Defined in: webhooks/src/index.ts:268

Parameters ​

store ​

WebhookStore

deliverer ​

WebhookDeliverer

options? ​

WebhookManagerOptions = {}

Returns ​

WebhookManager

Methods ​

dispatch() ​

> dispatch(event, data, scope?): Promise<DeliveryResult[]>

Defined in: webhooks/src/index.ts:464

Delivers to every endpoint subscribed to event, fail-closed on tenancy:

  • inside a tenant context the delivery is FORCED to that tenant's endpoints plus tenant-agnostic ones (anti-widening);
  • off the request path an explicit tenantId does the same for that tenant;
  • with no tenant at all only tenant-agnostic endpoints are reached — never a tenant-bound one — unless { allTenants: true } asks for system fan-out. The result is re-filtered here, so a store that ignores the tenant argument can't widen delivery.

Parameters ​

event ​

string

data ​

unknown

scope? ​

string | WebhookDispatchOptions

Returns ​

Promise<DeliveryResult[]>


list() ​

> list(tenantId?, options?): Promise<WebhookEndpointView[]>

Defined in: webhooks/src/index.ts:447

Lists endpoints (secrets redacted). Anti-widening: a tenant in the ambient context always wins — a caller-supplied tenantId (which may carry client input) can never widen or switch the scope. With no context tenant, an explicit tenantId is honoured; no scope at all lists every endpoint, which with tenancy active requires { system: true }.

Parameters ​

tenantId? ​

string

options? ​
system? ​

boolean

Returns ​

Promise<WebhookEndpointView[]>


register() ​

> register(endpoint, options?): Promise<WebhookEndpoint>

Defined in: webhooks/src/index.ts:328

Registers an endpoint and returns it — including its signing secret, which is generated (whsec_…) when none is given for a tenant-bound endpoint (or when the deliverer has no default secret). Store it / show it to the customer now: list never returns secrets.

Bound to the ambient tenant when one is in context (a caller-supplied tenantId can't override it). With tenancy active and no tenant at all, pass an explicit tenantId, or { system: true } to deliberately create a global endpoint that receives every tenant's events.

The endpoint is validated before anything is stored: an unparseable URL, a scheme outside the deliverer's allowlist, a secret shorter than MIN_WEBHOOK_SECRET_LENGTH or an empty events list throws WebhookEndpointInvalidError; an id held by another scope throws WebhookEndpointIdInUseError.

Parameters ​

endpoint ​

Omit<WebhookEndpoint, "id"> & object

options? ​
system? ​

boolean

Returns ​

Promise<WebhookEndpoint>


rotateSecret() ​

> rotateSecret(id, options?): Promise<WebhookEndpoint>

Defined in: webhooks/src/index.ts:376

Rotates an endpoint's signing secret without breaking its receiver: the new secret becomes current, and for graceSeconds (default 24 h) every delivery is signed with BOTH — t=…,v1=<new>,v1=<old> — which verifySignature (and Stripe-style receivers) accept with either secret. The receiver switches to the new secret whenever it is ready; after the window only the new one signs.

Returns the endpoint with its new secret (hand it to the customer now — list() never returns secrets); the previous secret is not echoed back. Scoped like unregister: an endpoint outside the ambient (or given) tenant throws WebhookEndpointNotFoundError. An endpoint that signs with the plugin-wide default secret has no own secret to rotate — rotate the default in your configuration, or register() the endpoint with its own. graceSeconds: 0 is an immediate cut-over (e.g. after a leak).

Durable stores must persist previousSecret/previousSecretExpiresAt (the bundled SQLite and Prisma stores do; the Prisma schema needs the two columns — see its README).

Parameters ​

id ​

string

options? ​

WebhookRotateSecretOptions = {}

Returns ​

Promise&lt;WebhookEndpoint&gt;


unregister() ​

> unregister(id, options?): Promise&lt;void&gt;

Defined in: webhooks/src/index.ts:425

Removes an endpoint, scoped to the ambient tenant (or options.tenantId): a no-op for an endpoint another tenant owns. With tenancy active and no tenant, { system: true } is required.

Parameters ​

id ​

string

options? ​
system? ​

boolean

tenantId? ​

string

Returns ​

Promise&lt;void&gt;

Released under the MIT License.