Everything on this page is real pusher-js and Pusher server-library code. The only change from a stock Pusher app is the host. Point the client at the ClutchCall realtime host. Your existing code continues to work, because the wire protocol is Pusher Channels in both cases. Copy a block. Add your app credentials. Run it.
You need an app’s key, secret, and app ID for these recipes. Create them in the Realtime Console under Apps & keys. Each app is a Pusher-compatible key/secret pair. The console shows the secret once. Store the secret as an environment variable, never in client code.
In these recipes, the realtime host is realtime.clutchcall.dev. The control-plane publish API is on portal.clutchcall.dev. Replace <APP_KEY>, <APP_ID>, and <APP_SECRET> with your own values.

Subscribe to a public channel

Public channels are open. Any client with the app key can subscribe. There is no auth round trip. The only Pusher option that differs from a hosted Pusher app is wsHost.
WebTransport / QUIC transport. The same channels are reachable over WebTransport/QUIC and over WebSocket. The wire is the identical Pusher protocol, served on the /app/<APP_KEY> path. Stock pusher-js uses WebSocket. To use the QUIC transport, use the ClutchCall realtime client. That client is a drop-in pusher-js-compatible fork that adds WebTransport with automatic WebSocket fallback. The subscribe/bind API is unchanged from the block above. See Realtime — Details for the transport ladder.
string
required
The ClutchCall realtime host, realtime.clutchcall.dev. This is the single line that repoints a stock Pusher client at ClutchCall.
boolean
default:"true"
Always keep TLS on in production. Connections are wss://, and QUIC is TLS by construction.
string
This option is unused when wsHost is set (there are no Pusher clusters here). But pusher-js still expects the key to be present. Pass an empty string.

Presence channels and a live member list

Presence channels (presence-*) track who is here. They require the same auth step as private channels (below). In return, every subscriber gets the current member roster plus member_added / member_removed events.
1

Subscribe and read the initial roster

pusher:subscription_succeeded fires once with the full member list.
2

Bind to joins and leaves

Keep your local roster in sync as members come and go.
members.me, member.id, and member.info come from the presence_data that your auth endpoint returns (next section). The id must be unique per user. info is arbitrary JSON that you attach (name, avatar, role).

Private channels and the server auth endpoint

Private (private-*) and presence (presence-*) channels require an HMAC-signed subscription. When a client subscribes, pusher-js POSTs the socket_id and channel_name to your channelAuthorization.endpoint. Your server decides whether that user may join. Your server then signs the grant with the app secret. The signature is a standard Pusher auth token. The stock Pusher server library produces it for you.
1

Point the client at your auth endpoint

Set channelAuthorization: { endpoint: "/pusher/auth" } (shown above). On older pusher-js this option is called authEndpoint.
2

Authorize and sign on the server

Run your own access check. Then pass the request to the Pusher server library.
The app secret must stay only on your server. Any party that can produce these auth tokens can subscribe to any channel. Keep the secret in an environment variable. Never put it in browser code. If the secret leaks, rotate it from the console.

Trigger an event from your server

Server-side publishing uses the Pusher server library pointed at the ClutchCall host. trigger(channel, event, data) fans the event out across the edge mesh to every subscriber.
The REST data field is a string: a JSON-encoded string of your payload, not a nested object. The server libraries do the encoding and the request signature. Use raw cURL only when you cannot run a server library. Get the signed version from the console’s Event Creator.

Send a client event

Subscribers can publish directly to a channel with a client- prefixed event. This is useful for ephemeral signals like typing indicators or cursor positions. There is no server round trip. Client events are allowed only on private-* and presence-* channels, and only when client events are enabled for the app.
First enable client events for the app in the console, under Settings → App capabilities. When the setting is off, the engine silently rejects client-* triggers. Client events are not delivered back to the sender. They are rate-limited per connection.

Receive a webhook

ClutchCall POSTs signed event batches to endpoints that you register in the console (Webhooks). Each request carries an X-Pusher-Signature header. The header is an HMAC of the raw body under the webhook’s signing secret. Check the signature against the raw bytes before you parse the body. Compare in constant time.
The signing secret is separate from your app secret. The console shows it once, when you add the webhook. The X-Pusher-Key header identifies which app key the delivery is for. Channel existence (channel_occupied / channel_vacated) and presence (member_added / member_removed) are shipped. Additional groups shown in the console (client-event and cache-miss webhooks) are rolling out. Treat them as preview. Check delivery for your deployment before you depend on them.

Details

How the Pusher-compatible layer maps onto WebSocket and QUIC transports.

SDK & API

The client, server-publish, and auth surfaces in reference form.

Recipes

End-to-end builds: a live presence list and server-pushed notifications.

Console

Create app keys, publish test events, and configure webhooks. No code is necessary.