Server
HTTP API
Pusher-compatible HTTP endpoints and request signing.
Endpoints
Realtime Publish
POST /apps/{appId}/eventsPOST /apps/{appId}/batch_events
Channel Queries
GET /apps/{appId}/channelsGET /apps/{appId}/channels/{channelName}GET /apps/{appId}/channels/{channelName}/users(presence only)
User Management
POST /apps/{appId}/users/{userId}/terminate_connections
Health and Ops
GET /upGET /up/{appId}GET /usageGET /metrics(metrics server port, default9601)
Signed Query Parameters
HTTP API routes under /apps/* require Pusher-style query auth:
auth_keyauth_timestampauth_versionauth_signaturebody_md5for non-emptyPOSTbody
Timestamp window is ±10 minutes.
Signature Format
String to sign:
{METHOD}\n{REQUEST_PATH}\n{SORTED_QUERY_EXCLUDING_AUTH_SIGNATURE}
Where query params are lowercase-key sorted pairs joined with &.
Node Signing Example
sign.ts
import crypto from "node:crypto";
export function signPusherRequest({
method,
path,
appKey,
appSecret,
body,
}: {
method: "GET" | "POST";
path: string;
appKey: string;
appSecret: string;
body?: string;
}) {
const auth_timestamp = Math.floor(Date.now() / 1000).toString();
const params: Record<string, string> = {
auth_key: appKey,
auth_timestamp,
auth_version: "1.0",
};
if (method === "POST" && body && body.length > 0) {
params.body_md5 = crypto.createHash("md5").update(body).digest("hex");
}
const queryForSig = Object.keys(params)
.sort()
.map((k) => `${k}=${params[k]}`)
.join("&");
const stringToSign = `${method}\n${path}\n${queryForSig}`;
const auth_signature = crypto
.createHmac("sha256", appSecret)
.update(stringToSign)
.digest("hex");
return { ...params, auth_signature };
}
Publish Example
publish.ts
import { signPusherRequest } from "./sign";
const path = "/apps/app-id/events";
const body = JSON.stringify({
name: "my-event",
channel: "my-channel",
data: JSON.stringify({ hello: "world" }),
});
const auth = signPusherRequest({
method: "POST",
path,
appKey: "app-key",
appSecret: "app-secret",
body,
});
const qs = new URLSearchParams(auth).toString();
await fetch(`http://127.0.0.1:6001${path}?${qs}`, {
method: "POST",
headers: { "content-type": "application/json" },
body,
});
Useful Query Flags
GET /channels?filter_by_prefix=presence-&info=user_countGET /channels/{name}?info=subscription_count,user_count,cache