Wire protocol 1.x

Everything on the socket is a short text frame: a number, a colon, then the details. You only need this page to write a client for another language or to read the wire log in the demos.

Protocol 1.x, for existing apps. Protocol 2.0 is live, and every new app from the dashboard uses it: start with the quickstart. This page is for apps that still run on 1.x, on ws.pikoman.se and api.pikoman.se. Moving to 2.0.

Connecting

Open a WebSocket to wss://ws.pikoman.se/{appId}. The first frame you receive carries your connection id:

042

Opcodes

Code Meaning Client sends Server sends
0 Connection Never 0:{connectionId}
1 Server message Never 1:{channel}:{event}:{payload}
2 Subscribe 2:{channel}
2:{channel}:{signature}:{permissions}:{data} for presence
2:{channel} as confirmation
2:{channel}:{count}:{connectionId}:{data} when a member joins
3 Join refused Never 3:{channel} when a presence signature is wrong
4 Unsubscribe 4:{channel} 4:{channel} as confirmation
4:{channel}:{count}:{connectionId} when a member leaves
8 Client message 8:{channel}:{toAll}:{event}:{payload} 8:{channel}:{senderId}:{event}:{payload}
9 Rate limited Never 9:RATE_LIMIT
16 Member list Never 16:{channel}:{members} after a presence join
64 Ping 64:{timestamp} The same frame, echoed

Only the first colons separate fields. The last field runs to the end of the frame, so payloads may contain colons freely.

A presence session, frame by frame

Connection 42 joins a room that already has one member, says hello, and receives a message published over HTTP.

Direction Frame What happened
Received 0:42 Connected, and this is our id.
Sent 2:presence-room:9f2c…e1:3:{"name":"Ada"} Join, with the string our backend signed.
Received 16:presence-room:{"17":"{\"name\":\"Linus\"}","42":"{\"name\":\"Ada\"}"} Everyone in the room, including us. Each value is that member's data as a JSON string.
Sent 8:presence-room:1:message:{"text":"hello"} A client message. toAll is 1, so we get it back as well.
Received 8:presence-room:42:message:{"text":"hello"} The relayed message, now carrying the sender's id.
Received 1:presence-room:bot:{"text":"Welcome, Ada"} A server message, published with POST /presence-room/bot.
Received 4:presence-room:1:17 Linus left. One member remains.

Keeping the connection alive

The server echoes any frame it does not otherwise understand, which is how ping works. The JavaScript client sends 64:{timestamp} after 6.5 seconds without traffic and reconnects if nothing arrives for 18.5 seconds. A client you write yourself should do something similar.

Limits

  • Client messages need a presence channel and a join signed with write permission.
  • One client message per connection every 20 ms. Extra ones are dropped and answered with 9:RATE_LIMIT.
  • Server messages cannot be sent over the socket. They come from the HTTP API only.

Previous: publishing over HTTP Next: moving to 2.0

We are rebuilding the dashboard

Self-service sign-up is closed while we do. Until the new dashboard is ready we set up apps by hand: write to us with a line about what you are building, and we will set up your app and get back to you.

Write to hello@pikoman.se