WebSocket endpoints
A deployed function with an enabled URL path is reachable as a WebSocket at:
wss://{store}/x/{slug}/ws
service owns the socket; every client event runs your function once through the same sandbox as HTTP calls. The route must be a single segment (/x/{slug}/ws); folder-namespaced paths fall through to the HTTP handler.
Actions
Your function is invoked with an action field that identifies the event:
| Action | When | Typical return |
|---|---|---|
ws_connect | The socket opens | { "subscribe": ["topic"], "messages": [{ "welcome": true }] } |
ws_message | The client sends {"type":"message","data":...} | Any JSON — sent back as the response |
ws_subscribe | The client asks to subscribe to a topic | { "allow": true } or { "allow": false, "reason": "..." } |
ws_close | The socket closes (best effort) | Any JSON — ignored |
Client envelopes
Send JSON text frames:
{ "type": "message", "request_id": "m1", "data": { "hello": "world" } }
{ "type": "subscribe", "request_id": "s1", "topic": "orders:42" }
{ "type": "unsubscribe", "topic": "orders:42" }
{ "type": "resume", "request_id": "r1", "last_event_id": 120 }
{ "type": "ping" }
The server replies with ready, response (echoes request_id, includes duration_ms), error, event, subscribed/unsubscribed, resume_ok/resync, and pong. Protocol-level ping/pong and heartbeats are handled by the platform and never invoke your function.
Authentication
auth_mode = public: no credentials. BrowserOriginhosts must still match the project domain (plus the platform designer origins used by the built-in console).auth_mode = token: pass the function token as?token=<token>or the subprotocolmodusell.token.<token>; server-side clients may usex-function-tokenorAuthorization: Bearer <token>.
Push, subscriptions and replay
Functions publish through the gateway (ctx.ws.publish(topic, data) in the SDKs). Publishing requires the ws_publish capability and a topic allowed by ws_topics (*, exact names, or prefix:*). Events are stored durably and fanned out to every subscriber, including across server instances.
Clients subscribe only when your function allows the topic. After a reconnect, send resume with the last event_id you saw to replay missed events (up to 200); a larger gap returns resync so the client can refetch state instead of streaming an unbounded backlog. Client messages sent while disconnected are lost — resend them with a stable request_id.
Limits
Rate 10 messages/s per connection (burst 20), 256 KiB frames, global execution concurrency 8, 100 connections per project and 20 per route, heartbeat every 25 s, idle close after 90 s. All are tunable with CUSTOM_CODE_WS_* environment variables. Slow clients are closed with code 1013 rather than blocking the server.
Try it in the designer
Open a function, go to Endpoint to enable the path (and optionally the ws/ws_publish capabilities), then use the Socket section: connect, send messages, subscribe, resume, and watch responses and pushed events live. Token-auth functions accept a pasted token in the console.

