Acting in a server
Every action is a call on the line. Woosh runs each as your wisp, under its grant and its role
in that server, so every check a person meets holds for it too. A call outside the grant (an
item it was not given, a channel the grant does not name, a server it is not in) answers
refused with w “Not granted”. A check a person would meet answers with the words a person
would get, such as “Missing permission: KickMembers.” or “The server owner cannot be kicked.”.
| Call | Needs | Spends |
|---|---|---|
send |
post, in a granted channel |
the server’s calls, the channel’s lines |
edit |
post, in a granted channel; its own line |
the server’s calls, that line’s edits |
card.live |
post, in a granted channel; its own line, or for a private card a press on it from the last minute |
the server’s calls and that line’s edits; a private card’s frame, that card’s edits alone |
delete |
a granted channel; its own line, or anyone’s with manage messages | the server’s calls |
react |
react, in a granted channel |
the server’s calls |
roles |
manage roles; each role below its own highest | the server’s calls |
kick |
kick members; someone whose highest role is below its own | the server’s calls |
ban |
ban members; the same | the server’s calls |
activity |
nothing | one call every 15 seconds |
Every call also spends the line’s own budget. Budgets and limits has the numbers,
respond is on Commands, card.live on Live frames, and
the reads on Catching up.
Post a line.
{"i":13,"t":"send","d":{"channel":"6d4c2b3e-9f5a-4b7c-8d6e-1f2a3b4c5d66","text":"The jackpot is open. Anyone here can spin.","sendId":"b6c7d8e9-fa0b-4c1d-93e4-f5a6b7c8d9ea"}}{"r":13,"v":"0199dea4-3397-71a2-b3b4-cf3a4b5c6d87"}d |
|
|---|---|
channel |
where: a server channel the grant names |
text |
up to 4,000 characters. Required |
card |
a card, on a channel’s line (not in a thread) |
replyTo |
a line in the same channel that this one answers |
parent |
the line whose thread it goes in |
sendId |
an id you make once per line. Required |
v is the line’s id. Make sendId once for each line and send it again with every retry of
that line: Woosh never posts the same sendId twice, and a retry of a line already posted
answers that line’s id. So a failed or limited send is always safe to repeat. The people
looking at the channel hear message; your wisp, which knows what it sent, does not hear it
back.
A wisp attaches no files: its pictures go on a card, uploaded first, as Pictures shows.
@ and a member’s name in text mentions them, as a person’s line does (@ana): a notice
while they look, a row in their inbox, a push when they are away. Words on a card mention
nobody: {user:<id>} there shows a name and tells no one. An edit mentions nobody new.
w |
|
|---|---|
| “Not granted” | no post here, or a channel outside the grant |
| “A wisp acts in a server’s channels.” | a DM, or no such channel |
| “A send holds words or a file” | no text |
| “A wisp’s line carries text too, for a build that does not know cards.” | a card without text |
| “A card goes on a channel’s line, not in a thread.” | a card with parent |
| “A message can be at most 4,000 characters” | |
| “Message not found.” | a parent that is not a line in that channel |
Replace your own line’s text and card. What the call holds replaces both: send the text every time, and the card too, or the line loses it.
{ "i": 60, "t": "edit", "d": { "message": "0199dea4-3064-7e7f-8081-9c0d1e2f3a54", "text": "Win a monitor. Entries close Sunday 20:00.", "card": { "blocks": [ { "type": "text", "text": "**Win a monitor**", "size": "large" }, { "type": "text", "text": "Entries close {at:1792353600000000}.", "size": "small" }, { "type": "actions", "actions": [{ "action": "enter", "label": "Enter", "kind": "tally", "tell": true }] } ] } }}{"r":60}In place of card you may send a patch, merged into the card
the line holds. A line in a thread carries no card. The people looking hear message.edit. For
frames between edits, which are never stored, see live frames.
Someone else’s line answers {"r":61,"e":"refused","w":"You can only edit your own messages."}
(“You can only edit your own replies.” in a thread). Also refused:
w |
|
|---|---|
| “Not granted” | no post here, or a channel outside the grant |
| “An edit holds the line’s text.” | no text |
| “An edit sends a whole card or a patch, not both.” | |
| “The line has no card to patch.” | a patch for a line without a card |
| “A card goes on a channel’s line, not in a thread.” | a card for a thread’s line |
| “A message can be at most 4,000 characters.” | |
| “Message not found.” | no such line |
delete
Section titled “delete”Take a line down: your own, or anyone’s with manage messages. A line’s thread goes with it.
{"i":62,"t":"delete","d":{"message":"0199dea4-1d31-7b4c-9d5e-6f7a8b9c0d21"}}{"r":62}The people looking hear message.gone. Someone else’s line without manage messages answers
{"r":63,"e":"refused","w":"You cannot delete this message."} (“You cannot delete this
reply.” in a thread). A line in a channel outside the grant answers “Not granted”.
Add a reaction with on, take it off without it.
{"i":14,"t":"react","d":{"message":"0199de8f-6c10-7a1b-8c3d-4e5f6a7b8c01","emoji":":fire:","on":true}}{"i":15,"t":"react","d":{"message":"0199de8f-6c10-7a1b-8c3d-4e5f6a7b8c01","emoji":":fire:"}}d |
|
|---|---|
message |
the line, or the reply in a thread |
emoji |
a standard emoji by its name in colons (:fire:), or one of the server’s own as <:name:id> |
parent |
the line whose thread holds it, when message is a reply in a thread |
on |
true adds it; left out takes it off |
Each answers an ack ({"r":14}), and the people looking hear reaction. A reaction already there, one
that is not there to take off, or a 21st kind on one line changes nothing. “Not granted” means
no react here, or a channel outside the grant.
Give a member roles (add) or take them (remove), role ids each below your wisp’s own
highest role. A role it gives may carry only permissions your wisp has itself. The server hears
member.roles.
{"i":68,"t":"roles","d":{"server":"5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55","user":"7a2e4c19-0b3d-4f6a-8e25-91c3d5f0a622","add":["2d3e4f5a-6b7c-4d8e-9fa0-1b2c3d4e5f60"]}}{"i":69,"t":"roles","d":{"server":"5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55","user":"7a2e4c19-0b3d-4f6a-8e25-91c3d5f0a622","remove":["2d3e4f5a-6b7c-4d8e-9fa0-1b2c3d4e5f60"]}}w |
|
|---|---|
| “A roles call adds or removes a role.” | neither add nor remove |
| “Missing permission: ManageRoles.” | |
| “Member not found.” | someone not in the server |
| “Role not found.” | a role that is not the server’s |
| “The @everyone role is implicit and cannot be assigned.” | |
| “Cannot manage a role at or above your highest role.” | |
| “You can only hand out permissions you have.” |
kick and ban
Section titled “kick and ban”Take a member out of the server, or ban them. They hear it as they would from a person:
server.gone, with kicked or banned. A ban holds whether or not they are in the server:
while it stands, they cannot join.
{"i":70,"t":"kick","d":{"server":"5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55","user":"b84d0e37-5c2a-4e91-a6f3-0d7c8e1b9433"}}{"i":72,"t":"ban","d":{"server":"5c3b1a2d-8e4f-4a6b-9c7d-0e1f2a3b4c55","user":"b84d0e37-5c2a-4e91-a6f3-0d7c8e1b9433"}}Nobody kicks or bans the server’s owner: {"r":71,"e":"refused","w":"The server owner cannot be kicked."}.
w |
|
|---|---|
| “Missing permission: KickMembers.” or “Missing permission: BanMembers.” | |
| “The server owner cannot be kicked.” or “The server owner cannot be banned.” | |
| “Cannot kick a member with an equal or higher role.” or “Cannot ban a member with an equal or higher role.” | |
| “Member not found.” | a kick of someone not in the server |
| “User not found.” | a ban of someone who does not exist |
Your wisp’s words
Section titled “Your wisp’s words”Set words of your wisp’s own with activity, up to 1,024 characters. They reach every server
your wisp is in, so a wisp may call activity once every 15 seconds; sooner answers limited
with the wait.
{"i":9,"t":"activity","d":{"activity":"Spinning the reels"}}Words last two minutes from the call that set them: to keep them, send them again within that
time (the same words again tell nobody). Leave activity out to clear them. The apps do not
draw a wisp’s words yet.
A wisp sends no presence: it is online while its line is up, and Woosh keeps that for it.
Permissions
Section titled “Permissions”What your wisp asks for in permissions (when you make it) and what an admin gives it, as bits
added together:
| Permission | Bit | Lets it |
|---|---|---|
| manage channels | 2 | |
| manage roles | 4 | roles |
| manage emoji | 8 | |
| kick members | 16 | kick |
| manage messages | 32 | delete anyone’s line |
| move members | 64 | |
| ban members | 128 | ban |
| create invites | 256 | |
| manage invites | 512 |
Administrator is never given to a wisp. The permissions with nothing beside them can be asked for and given, but no call a wisp makes uses them yet.
The permissions sit on a role made for your wisp when it is added, named after it. An admin changes them by changing the wisp’s grant (Quick start), and they reach the whole server, whatever channels the grant names. Where that role sits among the server’s roles decides whom your wisp can act on, and admins move it like any role.
© 2026 Woosh AS. All rights reserved.