subscribe / bind / trigger
surface, the same channel model, and your existing auth endpoint reused as-is —
and just point them at TeleQuick. There is no bespoke API to learn.
On the client you have two first-class, drop-in options — pick either
without changing your channel or event code:
- Stock
pusher-jsover WebSocket — repointwsHostand you are done. Best when you want zero new dependencies and run on normal, reliable networks. - The TeleQuick QUIC-native realtime client — a
pusher-js-API-compatible drop-in that prefers WebTransport/QUIC and falls back automatically. Best when mobile or lossy-network resilience matters (see When to pick which).
This page is a reference for the compatible surface. If you already run
Pusher, the only required change is the connection host (client) and the
host option (server). App credentials come from the
Realtime Console.Connect a client
Construct a client with your app key and point it at the TeleQuick realtime host. Choose the transport-matched client below — the channel, bind, and connection-state code after this step is identical regardless of which you pick.- Stock pusher-js (WebSocket)
- TeleQuick QUIC-native client
Repoint stock
pusher-js by setting wsHost. Nothing else changes — this is the
pure drop-in migration path.Browser (pusher-js)
The realtime host,
realtime.telequick.dev. This is the one line that
repoints stock pusher-js from Pusher’s cluster onto TeleQuick.Set
true to connect over wss://. Recommended for all production traffic.Override only if you terminate on a non-default port. By default the client uses
443 under forceTLS.pusher-js (and the compatible client) addresses your app by key, not by
app ID — the app ID is only used server-side. The cluster option is ignored
when you set wsHost explicitly, which is what you want here.Your backend route that signs
private-* / presence-* subscriptions —
identical for both clients. Only needed if you use private or presence channels.Transport ladder
The Pusher protocol is what TeleQuick speaks; the QUIC-native client can carry it over three transports, negotiated in order and degrading automatically:| Rung | Transport | How it connects | Wins when |
|---|---|---|---|
| 1 | WebTransport / QUIC | HTTP/3 to /app/<key> | Lossy, mobile, or high-latency links — no TCP head-of-line blocking, faster reconnects via 0-RTT resumption, survives network changes. |
| 2 | WebSocket | wss:// to /app/<key> | Reliable wired networks, or where WebTransport is blocked. Identical to stock pusher-js. |
| 3 | SockJS | HTTP long-polling fallback | Restrictive proxies that break both of the above. |
Raw-QUIC on mobile is delivered through the native mobile SDKs, not the browser
package. In the browser, “QUIC” always means WebTransport/HTTP-3. If you need the
raw-QUIC mobile transport, confirm current availability for your platform in the
Realtime Console before you depend on it.
When to pick which
Be honest with your own traffic: on a clean wired network, WebSocket-over-TCP is already fast and stockpusher-js is the simplest thing that works. The
QUIC-native client earns its place on lossy, mobile, or high-latency
networks, where TCP head-of-line blocking and slow reconnects hurt.
| Situation | Recommended client |
|---|---|
| Pure drop-in migration off Pusher, no new deps | Stock pusher-js (WebSocket) |
| Desktop / server on reliable wired networks | Stock pusher-js (WebSocket) |
| Mobile web, flaky Wi-Fi, cellular, roaming | QUIC-native client |
| High packet loss or high RTT paths | QUIC-native client |
| Fast reconnect / connection migration matters | QUIC-native client |
Subscribe, bind, unsubscribe
Join a channel. Prefix decides the type: no prefix (or
public-) is open,
private- requires a signed subscription, presence- adds member state.Register a handler for an event on that channel.
bind_global receives all
events.Leave a channel; drops its binds and stops delivery.
Connection states
The client exposes the standard Pusher connection lifecycle. Bind to it to drive UI (a “reconnecting” banner, say) or to gate publishes:| State | Meaning |
|---|---|
initialized | Client constructed, not yet connecting. |
connecting | Opening the transport / handshaking. |
connected | Live; subscriptions and events flow. |
unavailable | Reachability lost; the client retries with backoff. |
failed | Transport unsupported in this environment. |
disconnected | Closed after pusher.disconnect(). |
Authorize private & presence channels
private-* and presence-* subscriptions are HMAC-signed with your app
secret. The browser never holds the secret: pusher-js POSTs the socket_id
and channel name to your channelAuthorization.endpoint, and your backend signs
the response with a Pusher server library. This is the standard Pusher auth flow
— reuse your existing endpoint unchanged.
Client requests authorization
On
subscribe("private-…") or subscribe("presence-…"), pusher-js POSTs
{ socket_id, channel_name } to your auth endpoint.Backend signs with the app secret
Your route constructs a Pusher server client with
{ appId, key, secret }
and returns the signed auth payload. For presence channels you also attach
the member’s user_id and user_info.- Node (Express)
- Python (Flask)
Presence channels deliver
pusher:subscription_succeeded with the current
member list, then pusher:member_added / pusher:member_removed as people come
and go — the standard presence events, bound the usual way.Publish from your server
Use the official Pusher server library, constructed with your{ appId, key, secret, host }, and call trigger(channel, event, data). This
fans the event out across TeleQuick’s edge — every subscriber on that channel
receives it.
- Node
- Python
- cURL (REST)
Publish
event with JSON data to one channel or an array of channels. data
is delivered to every subscriber’s matching bind.The underlying publish endpoint on the realtime host. Body is
{ name, channel | channels, data }; requests are HMAC-signed with the app
secret (the server libraries do this for you). The
Console Event Creator shows the exact cURL for
any event you compose.data is transmitted as a JSON string. The Pusher server libraries serialize an
object for you; over raw REST you pass a stringified body, as shown in the cURL
tab.Client events
Onprivate-* and presence-* channels, subscribers can publish client-*
events directly to each other (typing indicators, cursors) without a round trip
through your server. Enable client events for the app in the
Console settings first.
Webhooks
Register endpoints in the Console to receive signed event batches when channels become occupied or vacated and when presence members join or leave. Verify theX-Pusher-Signature HMAC (computed with the
webhook signing secret) before trusting a payload.
| Event | Fires when |
|---|---|
channel_occupied | First subscriber joins a channel. |
channel_vacated | Last subscriber leaves a channel. |
member_added | A member joins a presence-* channel. |
member_removed | A member leaves a presence-* channel. |
Channel-existence and presence webhooks plus per-delivery HMAC signing are
shipped. Some batching and additional webhook event groups (for example client-
event and cache webhooks) are still rolling out — treat those as preview and
confirm availability for your deployment in the Console before you depend on
them.
Compatibility scope
What is drop-in today
What is drop-in today
Public channels,
private-* HMAC subscription auth, presence-* with member
state, client-* events, subscribe/bind/unbind/unsubscribe, the full
connection-state lifecycle, and server-side trigger (single and multi-channel)
over both the server libraries and the REST publish endpoint. Both clients —
stock pusher-js and the TeleQuick QUIC-native client (@telequick/sdk/realtime)
— speak this surface identically, and the official Pusher server SDKs work by
changing only the host.Where to check before you rely on it
Where to check before you rely on it
Some webhook batching and the broader webhook event set are still landing (see
above). The browser QUIC path rides WebTransport (HTTP/3) and always has the
WebSocket/SockJS fallback beneath it; raw-QUIC on mobile ships through the
native SDKs — confirm availability for your platform before depending on it. If
you use an advanced or newer Pusher feature not listed under “drop-in”, verify it
against your deployment first.
Next steps
Realtime — Details
How channels, transports, and the edge fan-out fit together.
Realtime Console
Mint app keys, publish test events, and wire webhooks.
Realtime — Cookbook
Copy-pasteable snippets: presence, private channels, server publish.
Realtime — Recipes
End-to-end builds: a live presence list and server-pushed notifications.