Skip to content

Reference

Keys marked ? may be left out; a key left out is its default (no value, false, an empty list, an empty text, 0). Ids are lowercase GUIDs; times are microseconds since 1970, UTC.

Frame Shape
ready {"t":"ready","v":2,"id","s","g?","e?","replay","silence","retry","media","gateway?","slices","budget"} The line
numbered event {"c":<group>,"n":<number>,"t":<name>,"d":{…}} Frames
unnumbered event {"t":<name>,"d":{…}}
answer {"r":<i>} or {"r":<i>,"v":…} Calls and answers
error {"r":<i>,"e":<code>,"w":<words>}, and "wait":<ms> with limited
ping {"t":"ping"} after 15 seconds of nothing else
move {"t":"move"} Moving
Frame Shape
hello {"t":"hello","v":2,"r?","e?","a","f":1,"slice?"} The line
call {"i":<number>,"t":<name>,"d":{…}} i from 1 to 2,147,483,647; one frame a message, at most 64 KB
moved {"t":"moved"} Moving

All numbered, on the wisp’s own group.

Event Grant d
command always server, channel, id, user, name?, avatar?, command, options?, expires Commands
act always server, channel, message, id, user, name?, avatar?, action, value?, on?, expires Presses
server always (new, grants); shape for other changes id, name, icon?, owner, unread?, new?, grants?: hears?, does?, channels? Always
server.gone always id, why (removed, kicked, banned, deleted), name? Always
channel shape id, server, name, type?, new? shape
channel.gone shape id, server
layout shape server, nodes?
roles shape server, roles
emoji shape id, server, name, url, serverName
emoji.gone shape id, server
member members server, user, name?, avatar?, avatarColor?, banner?, bannerColor?, status?, flags?, joined, roleIds? members
member.roles members server, user, roleIds?
member.gone members server, user
message messages server, id, channel, parent?, author, name?, avatar?, text?, at, edited?, reply?, files?, imported?, card?, run? messages
message.edit messages server, id, channel, parent?, text?, files?, edited?, card?, run?
message.gone messages server, id, channel, parent?
reaction messages server, message, channel, parent?, emoji, user, name?, on?

A line’s parts: reply is id, author?, name?, text?; each of files (1 to 10) is id, url, name?, type?, mb?, w?, h?, expires?; run is id, user, name?, command? (left out on an answer to a press); imported is the name the line’s author had in the app it was brought over from.

Call d Answer
respond to (a run or a press), text? (up to 4,000), card? (or patch? with edit on a line), private?, edit? (a press only) v: the line’s id, the aside’s (the run’s own id), or the pressed line’s Commands, Presses
send channel, text, card?, replyTo?, parent?, sendId v: the line’s id send
edit message, text, card? or patch? ack edit
card.live message (its own line with a card) and card or patch; or to (a press on a private card, from the last minute) and a whole card ack Live frames
delete message ack delete
react message, emoji, parent?, on? ack react
roles server, user, add?, remove? ack roles
kick server, user ack kick and ban
ban server, user ack kick and ban
activity activity? (your wisp’s words, up to 1,024 characters; left out clears them) ack; one call every 15 seconds, and the words last two minutes Your wisp’s words
history channel (where it hears messages), before? or after? (a time), limit? (1 to 100) v: the lines, newest first, each as it hears message; thread replies not included Catching up
members server (where it hears members), offset?, limit? (1 to 1,000) v: the members in the order the apps draw them, each as it hears member
member server (where it hears members), user v: the member, as it hears member
tally message (its own line), action, after? (a person’s id), limit? (1 to 1,000; 1,000 when left out) v: each counted person’s user and at, in the order of their ids Tallies
draw message (its own line), action, count (1 to 100) v: up to count people’s ids, picked at random

A wisp does not send presence (Woosh keeps it for you), nor typing, read, view or follow, which are a person’s.

e Means
refused Woosh said no; w says why. Do not retry also any code you do not know
limited past a budget; nothing done. Again after wait ms Budgets and limits
failed it may or may not have run. Retry what is safe to repeat

The words in w are for your log and may change. The ones you will meet most: “Not granted”, “Already answered”, “Too late”, “No such run or press”, “That is switched off”. A check a person would meet too answers with a person’s words, such as “Missing permission: KickMembers.” or “The server owner cannot be kicked.”.

Code What to do
4426 version stop
4401 unauthorized a new token, then again at once; if a second 4401 follows, back off
4403 revoked stop
4429 retry=<s> wait the seconds named
1013 retry=<s> wait the seconds named
1012 restart come back at once
1011 connect failed back off; check the slice
1000 moved nothing

The details are on The line.

Not on your line, but what your calls become:

Frame To
message with card and run the people looking at the channel your line, with who ran which command above it
aside the person alone, unnumbered id, channel, author (your wisp), name?, avatar?, to?, text?, card?, at: a private answer, kept nowhere; the same id again replaces it
card.live the people looking, unnumbered id, channel, parent?, card or patch: a frame of your card
commands the server server, at: its commands changed. Your wisp does not hear it

https://api.woosh.no, with Authorization: Bearer <token>. JSON keys in camelCase.

Route Who
POST /api/auth/login you username (or your email) and password: answers your own token
POST /api/oauth/token the wisp, with its id and secret an hour’s token, and the line to open. At most 120 requests a minute from one address. Refusals: 400 unsupported_grant_type, 401 invalid_client, 429
POST /api/wisps its owner make one: answers the wisp and its secret, shown once
GET /api/wisps its owner your wisps
PATCH /api/wisps/{id} its owner change its name, description, asks or slices
POST /api/wisps/{id}/secret its owner a new secret; the old one’s lines close with 4403
PUT /api/wisps/{id}/commands its owner, with their own token (a wisp’s cannot) its commands, replaced whole
GET /api/wisps/{id} anyone signed in what the approval page shows: who made it, its reach, whether it was reviewed, all it asks for
POST /api/servers/{id}/wisps an Administrator add a wisp with what is approved: answers the wisp as the server holds it, with asksMore
GET /api/servers/{id}/wisps an Administrator the server’s wisps, each with what it asks for beyond its grant
PATCH /api/servers/{id}/wisps/{wisp} an Administrator change a grant
DELETE /api/servers/{id}/wisps/{wisp} an Administrator take a wisp out: answers 204
GET /api/servers/{id}/commands any member the server’s commands, for the picker: each wisp’s wisp, name, avatarUrl, channels (null: every channel) and commands
POST /api/wisps/files the wisp, with its own token a picture for its cards: answers its url (Pictures)

A wisp’s token reaches only POST /api/oauth/token and POST /api/wisps/files. Everything else it does and reads is a call on its line. A REST refusal answers 403, 404 or 409 with {"error": "<words>", "traceId": "…"}. A body Woosh cannot read answers 400 (or 415 for the token route sent as something other than a form), a wrong sign-in 401, and too many requests 429. The token route answers {"error": "invalid_client"} or {"error": "unsupported_grant_type"}, and a picture past two a second answers 429 with Retry-After.

A card is color? (#rrggbb) and blocks: at most 40 parts, 4,000 characters and 8 KB.

Block Holds
text text (with marks), size?, tone?
fields fields: 1 to 10 of name (1 to 256 characters) and value (1 to 1,024)
grid rows: 1 to 5 rows of 1 to 5 cells, each one of text, emoji, or url and alt; tone?; action? with value? and disabled?
media url, alt, size? (small, normal or large)
gallery items: 2 to 10 of url, alt
section text, and media or action beside it (not both), tone?
progress value, max, label?, tone?
actions actions: 1 to 5
pages pages: 2 to 10 of label, blocks
divider nothing

Any block or cell may carry a key for patches. The whole model is on Cards.

© 2026 Woosh AS. All rights reserved.