Publishing over HTTP
Your backend talks to Pikoman with plain HTTP requests. There is no server SDK to install: if your language can make a POST, it can publish.
Base URL and authentication
All requests go to https://api.pikoman.se and use HTTP basic auth, with the app id as the
username and the app secret as the password.
curl https://api.pikoman.se/orders/stats -u your-app-id:your-app-secret
Wrong credentials get a 401 with {"error": "Wrong credentials"}. A request the server
cannot read gets a 400.
Publish an event
POST /{channel}/{event}The request body is delivered as the event's payload to every client subscribed to the channel. Send JSON and the JavaScript client hands your handler a parsed object.
curl -X POST https://api.pikoman.se/orders/shipped \
-u your-app-id:your-app-secret \
-d '{"id": 1042, "status": "shipped"}'const credentials = Buffer.from(`${appId}:${appSecret}`).toString("base64");
const response = await fetch("https://api.pikoman.se/orders/shipped", {
method: "POST",
headers: { authorization: `Basic ${credentials}` },
body: JSON.stringify({ id: 1042, status: "shipped" }),
});
const { clients } = await response.json();let delivered: serde_json::Value = reqwest::Client::new()
.post("https://api.pikoman.se/orders/shipped")
.basic_auth(app_id, Some(app_secret))
.json(&serde_json::json!({ "id": 1042, "status": "shipped" }))
.send()
.await?
.json()
.await?;The response reports how many connected clients the event was delivered to:
{ "clients": 12 }Zero is a normal answer: it means nobody was listening at that moment. Events are not stored, so a client that connects later will not receive it.
Publish many events at once
POST /mass_events
The body is a JSON array. Each entry sends one payload to one or more channels, which is the cheap way to
notify a list of users. Leave out event to send the payload without an event name.
curl -X POST https://api.pikoman.se/mass_events \
-u your-app-id:your-app-secret \
-d '[
{ "channels": ["user-7", "user-9"], "event": "invite", "data": { "team": "Design" } },
{ "channels": ["dashboard"], "event": "tick", "data": { "online": 31 } }
]'{ "count": 3, "message": "success" }count is the number of channel deliveries that were queued, here two plus one.
Look inside a channel
| Request | Response | Use it for |
|---|---|---|
GET /{channel}/stats |
{"clients": 12} |
How many connections are subscribed. |
POST /{channel}/clients |
{"clients": {"42": "{\"name\":\"Ada\"}"}} |
Connection ids and, for presence channels, each member's signed data as a JSON string. |
Disconnect a client
DELETE /connection/{connectionId}
Closes one connection, for example when a user logs out or is banned. The connection id is the one the client
reports with pikoman.getClientId() and the one your presence endpoint receives.
{ "kicked": true }The client will try to reconnect, so also make your presence endpoint refuse that user. Without a fresh signature they cannot get back into a presence channel.
Channel and event names
- Names are part of the URL path and of a colon-separated frame, so avoid
/and:. - Public channels have no access control: anyone with your app id who knows the name can subscribe. For per-user channels, use a name that cannot be guessed, or use a presence channel.
- Only the
presence-prefix is special.