@thunderclapjs/server
For your backend: anything with fetch and Web Crypto, including Node.js 22+ and edge runtimes. No dependencies. Install it with npm install @thunderclapjs/server.
ThunderclapServer
Server-side access to one app: publish events, mint client tokens and verify webhooks.
constructornew ThunderclapServer
Creates an SDK instance for one app.
new ThunderclapServer(options: ThunderclapServerOptions)Parameters
appIdstringrequiredThe app id (
THUNDERCLAP_APP_ID).secretstringrequiredAn active secret of the app (
THUNDERCLAP_SECRET). Keep it on your server.urlstringdefault"https://realtime.thunderclap.dev"The Thunderclap endpoint. Set it only for a custom domain.
fetchtypeof fetchFetch implementation; the global one by default.
Example
const thunderclap = new ThunderclapServer({
appId: process.env.THUNDERCLAP_APP_ID,
secret: process.env.THUNDERCLAP_SECRET,
});methodpublish
Publishes one event to one or more channels. Fan-out to subscribers is free.
publish(input: PublishInput): Promise<PublishResult>Parameters
channelstring | string[]requiredOne channel, or up to 100 to publish the same event to.
eventstringEvent name, up to 200 characters. Defaults to
message.dataunknownrequiredJSON-serializable data, up to 10 KB.
excludestringA client's
socketIdto skip, typically the one that triggered the event.
Returns
{ seq }: the sequence the event got on each channel, as { [channel]: [epoch, n] }. Store it with your copy of the message.
Throws
ThunderclapApiError when the request is refused.
Example
const { seq } = await thunderclap.publish({ channel: "room-42", data: { text: "Hi" } });methodbatch
Publishes up to 10 events in one request, in order. Cheaper than separate publishes.
batch(events: BatchEvent[]): Promise<BatchResult>Parameters
eventsArray<{ channel, event?, data, exclude? }>requiredThe events, each to a single channel.
eventdefaults tomessage.
Returns
{ results }: one { seq } per event, in order.
Throws
ThunderclapApiError when the request is refused.
methodtoken
Mints a token: a connection token for thunderclapJS's token option, or a per-channel token for its authorize callback.
token(options?: TokenOptions): Promise<string>Parameters
uidstringUser id. Required to join presence channels, where it identifies the member.
infounknownPublic user info shown to the other members of presence channels, up to 1 KB as JSON.
channelsstring[]Channel grants: exact names, or prefixes ending in
*(private-team-7-*).ttlSecondsnumberdefault3600Lifetime. Tokens are checked at connect and subscribe time only.
Returns
The signed token.
Throws
RangeError when info is over 1 KB.
Example
const token = await thunderclap.token({ uid: user.id, channels: [`private-user-${user.id}`] });methodverifyWebhook
Verifies a webhook request and returns its events. Requests are signed with every active secret, so this works with whichever one the instance holds, also during a rotation.
verifyWebhook(input: VerifyWebhookInput): Promise<WebhookPayload>Parameters
bodystring | Uint8ArrayrequiredThe raw body, exactly as received: parsing and re-serializing it breaks the signature.
signaturestring | null | undefinedrequiredThe
Thunderclap-Signatureheader.toleranceSecondsnumberdefault300Oldest signature accepted, against replayed requests.
Returns
The payload: { app, events }, each event with a unique id for deduplication.
Throws
ThunderclapWebhookError when the signature is missing, wrong or too old, or the app differs.
methodverifyWebhookRequest
Verifies a webhook delivered as a standard Request (Next.js route handlers, Workers, Bun, Deno), reading its body and signature header.
verifyWebhookRequest(request: Request): Promise<WebhookPayload>Returns
The payload, like verifyWebhook.
Throws
ThunderclapWebhookError, like verifyWebhook.
ThunderclapApiError
Thrown when the REST API refuses a request.
propertystatus
The HTTP status: 400 for invalid input, 401 for a wrong secret or a suspended app.
readonly status: numberThunderclapWebhookError
Thrown by verifyWebhook and verifyWebhookRequest when a request isn't a valid, recent one from Thunderclap for this app. Answer such requests with 401.
Constants
Values exported by the package.
constantWEBHOOK_SIGNATURE_HEADER
The header carrying a webhook request's signature.
const WEBHOOK_SIGNATURE_HEADER = "Thunderclap-Signature"