HTTP API
Your servers publish events and read channel information over HTTP. Every Pusher server library already speaks this API, so you rarely need to call it directly. This page is for when you do.
Base URL, with your own app id:
https://YOUR_HOST/apps/YOUR_APP_IDSigning requests
Every request carries these query parameters:
| Parameter | Value |
|---|---|
auth_key | your app key |
auth_timestamp | the current Unix time in seconds |
auth_version | 1.0 |
body_md5 | the MD5 of the request body, hex (POST requests only) |
auth_signature | the signature, below |
The signature is an HMAC-SHA256, in hex, keyed with your app secret, of this string:
METHOD
PATH
QUERYMETHOD is GET or POST, PATH is the request path (for example /apps/123/events), and QUERY is all the query parameters except auth_signature, sorted by name and joined as name=value with &. The three parts are joined with a newline.
Without a library, in Node:
js
import { createHash, createHmac } from "node:crypto";
const appId = "YOUR_APP_ID";
const key = "YOUR_APP_KEY";
const secret = process.env.PUSHER_APP_SECRET;
const body = JSON.stringify({
name: "my-event",
channels: ["my-channel"],
data: JSON.stringify({ hello: "world" }), // data is a string
});
const path = `/apps/${appId}/events`;
const query = [
`auth_key=${key}`,
`auth_timestamp=${Math.floor(Date.now() / 1000)}`,
"auth_version=1.0",
`body_md5=${createHash("md5").update(body).digest("hex")}`,
].join("&");
const signature = createHmac("sha256", secret)
.update(`POST\n${path}\n${query}`)
.digest("hex");
const response = await fetch(
`https://YOUR_HOST${path}?${query}&auth_signature=${signature}`,
{ method: "POST", headers: { "Content-Type": "application/json" }, body },
);
console.log(await response.json()); // { ok: true }Endpoints
| Method and path | Purpose |
|---|---|
POST /events | Publish one event to one or more channels |
POST /batch_events | Publish up to 10 events at once |
GET /channels | List occupied channels |
GET /channels/CHANNEL | Information about one channel |
GET /channels/CHANNEL/users | Members of a presence channel |
POST /users/USER_ID/terminate_connections | Close a signed-in user's connections |
All paths are under /apps/YOUR_APP_ID.
Publish an event
POST /events with a JSON body:
json
{
"name": "my-event",
"channels": ["my-channel", "other-channel"],
"data": "{\"hello\":\"world\"}",
"socket_id": "123.456"
}datais a string. Send JSON by serializing it first.- Use
channels(up to 100) or the single-channelchannel. socket_idis optional: that client will not receive the event, which is how you avoid echoing a change back to the browser that made it.
The response is {"ok":true}.
Publish a batch
POST /batch_events:
json
{
"batch": [
{ "channel": "my-channel", "name": "e1", "data": "x" },
{ "channel": "other-channel", "name": "e2", "data": "y" }
]
}A batch holds at most 10 events.
Channel information
GET /channels lists occupied channels. Filter with filter_by_prefix, for example ?filter_by_prefix=presence-:
json
{ "channels": { "room-1": { "subscription_count": 1, "occupied": true } } }GET /channels/room-1 returns the same fields for one channel. GET /channels/presence-room-1/users returns { "users": [{ "id": "42" }] }.
Errors
json
{ "error": "The secret authentication failed", "code": 401 }code | Meaning |
|---|---|
400 | The body is malformed or incomplete, or a batch has more than 10 events |
401 | The signature does not match: wrong secret, or the request was changed after signing |
404 | The app id does not exist |
413 | The event data is larger than your plan allows (see Limits and quotas) |
429 | You exceeded your publish or read rate, or the app is paused |
Rate limits
Publishing and reading are limited per app, per second, by your plan. A publish costs one point per channel, so an event to 20 channels costs 20, and a batch costs the sum of its events' channels. Each read request costs one. The limits are in Limits and quotas.