Schemas
Error
statusCodemessageA human-readable reason. Not stable; branch on the status code.
errorfieldOn a schema 400, the first field at fault (dotted for nested fields).
InboundEvent
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · type="command" · requires: channel, user, text | |
| type = object · type="action" · requires: channel, user, messageId +1 more | |
| type = object · type="message" · requires: channel, user, text |
typeWhere the event happened — a bare id, or an id with a display name.
The member who acted. id is your chat's id for them, opaque to
Hijinks and stable — scores and DMs follow it. name is shown in
results and leaderboards; send it whenever you have it.
textWhat followed the command, e.g. start, start science, leaderboard. Empty is help.
idOptional. Your id for this request, unique per request; send the
same one when you retry it. A request repeating an id seen in the
last 24 hours is answered 202 and ignored.
RequestId
Optional. Your id for this request, unique per request; send the
same one when you retry it. A request repeating an id seen in the
last 24 hours is answered 202 and ignored.
ChannelId
^(?!dm:)Your chat's id for the channel, opaque to Hijinks; outbound events
address the channel by it. Ids starting with dm: are reserved:
Hijinks addresses members' DMs as dm:<user id> (see DmChannelId).
DmChannelId
^dm:.The acting member's DM with Hijinks: dm: followed by the event's
own user.id, exactly. Only action and message events may come
from a DM. A dm: id on a command, or one naming another member,
is refused with 400 (field channel) — the second rule spans two
fields, so this schema alone cannot express it.
MemberChannel
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = string | |
| type = object · requires: id |
^(?!dm:)Your chat's id for the channel, opaque to Hijinks; outbound events
address the channel by it. Ids starting with dm: are reserved:
Hijinks addresses members' DMs as dm:<user id> (see DmChannelId).
Channel
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = string | |
| type = object · requires: id |
^(?!dm:)Your chat's id for the channel, opaque to Hijinks; outbound events
address the channel by it. Ids starting with dm: are reserved:
Hijinks addresses members' DMs as dm:<user id> (see DmChannelId).
User
idnameCommandEvent
typeWhere the event happened — a bare id, or an id with a display name.
The member who acted. id is your chat's id for them, opaque to
Hijinks and stable — scores and DMs follow it. name is shown in
results and leaderboards; send it whenever you have it.
textWhat followed the command, e.g. start, start science, leaderboard. Empty is help.
idOptional. Your id for this request, unique per request; send the
same one when you retry it. A request repeating an id seen in the
last 24 hours is answered 202 and ignored.
ActionEvent
typeWhere the event happened — a channel as in Channel, or the member's
own DM as dm:<user.id>, bare or with a display name.
The member who acted. id is your chat's id for them, opaque to
Hijinks and stable — scores and DMs follow it. name is shown in
results and leaderboards; send it whenever you have it.
messageIdThe Hijinks message.id of the message the button was on.
actionThe button's action, echoed back untouched.
idOptional. Your id for this request, unique per request; send the
same one when you retry it. A request repeating an id seen in the
last 24 hours is answered 202 and ignored.
MessageEvent
typeWhere the event happened — a channel as in Channel, or the member's
own DM as dm:<user.id>, bare or with a display name.
The member who acted. id is your chat's id for them, opaque to
Hijinks and stable — scores and DMs follow it. name is shown in
results and leaderboards; send it whenever you have it.
textidOptional. Your id for this request, unique per request; send the
same one when you retry it. A request repeating an id seen in the
last 24 hours is answered 202 and ignored.
replyToThe Hijinks message.id this replies to, when your chat has replies.
EventId
^evt_[0-9A-HJKMNP-TV…Unique per event and unchanged across its retries; dedupe on it.
MessageId
^msg_[0-9A-HJKMNP-TV…Minted by Hijinks. Keep a map from it to your chat's message id.
Sequence
Strictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
ExpiresAt
When the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
OutboundChannel
A channel id your bridge sent in an inbound event — or dm:<user id>
on a message.update of a message first sent by dm.create.
MessageKind
What the message is, so a bridge can special-case a few kinds and
print the rest. text is a plain message with no buttons and no
data; card is a generic message (confirmations, errors,
celebrations, game announcements). New kinds may appear; print
unknown ones like card.
Button
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · requires: label, action | |
| type = object · requires: label, url |
labelactionOpaque. Echo it back untouched; never parse it.
ActionButton
labelactionOpaque. Echo it back untouched; never parse it.
Message
id^msg_[0-9A-HJKMNP-TV… · requiredMinted by Hijinks. Keep a map from it to your chat's message id.
kindWhat the message is, so a bridge can special-case a few kinds and
print the rest. text is a plain message with no buttons and no
data; card is a generic message (confirmations, errors,
celebrations, game announcements). New kinds may appear; print
unknown ones like card.
textChat-flavoured Markdown, ready to print. A bare \n is a line
break (see the API description). Always present; never empty for
a message worth showing.
Rows of buttons, top to bottom, each row left to right. Empty when there are none.
imageAn image or GIF to show with the message, or null.
awaitsReplyHijinks would like the member's next typed message to answer this
one. Offer a reply box or thread if your chat has one, and send the
answer as a message event with replyTo set. In a DM, replyTo
is optional: a message with channel: "dm:<user id>" answers the
latest prompt waiting there.
dataThe platform-neutral view model the message was rendered from,
for bridges that draw their own UI. Its shape depends on kind
and is not part of the stable contract during the beta.
MessageCreateEvent
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
channelA channel id your bridge sent in an inbound event — or dm:<user id>
on a message.update of a message first sent by dm.create.
MessageUpdateEvent
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
channelA channel id your bridge sent in an inbound event — or dm:<user id>
on a message.update of a message first sent by dm.create.
MessageEphemeralEvent
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
channelA channel id your bridge sent in an inbound event — or dm:<user id>
on a message.update of a message first sent by dm.create.
userA member's user.id, as your bridge sent it.
DmCreateEvent
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
userA member's user.id, as your bridge sent it.
PingEvent
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
Cursor
^\d{1,18}$A poll position. Opaque; pass it back as after exactly as received.
OutboundEvent
Decision Table
| Variant | Matching Criteria |
|---|---|
| type = object · type="message.create" · requires: id, workspace, sequence +4 more | |
| type = object · type="message.update" · requires: id, workspace, sequence +4 more | |
| type = object · type="message.ephemeral" · requires: id, workspace, sequence +5 more | |
| type = object · type="dm.create" · requires: id, workspace, sequence +4 more | |
| type = object · type="ping" · requires: id, workspace, sequence +2 more |
id^evt_[0-9A-HJKMNP-TV… · requiredUnique per event and unchanged across its retries; dedupe on it.
typeworkspaceThe Hijinks workspace, as shown in the dashboard.
sequenceStrictly increasing per workspace, so events that arrive out of order
can be put back in order (an older message.update than one already
applied can be skipped). Not contiguous. Taken from Hijinks' clock in
microseconds, so it keeps increasing across Hijinks restarts and
deploys. Below 2^53, so it fits a JSON number in every language.
createdAtWhen Hijinks created the event (ISO 8601, UTC).
expiresAtWhen the event goes stale (ISO 8601, UTC): past it, drop the event
unapplied. 60 seconds after createdAt for message.ephemeral and
ping; 10 minutes for a live game's messages and the answers to
commands; null — never stale — for prompts and results that stay
valid for hours (self-paced rounds, word games with their own end,
icebreakers, digests). Compare it with your own clock.
channelA channel id your bridge sent in an inbound event — or dm:<user id>
on a message.update of a message first sent by dm.create.
EventPage
Oldest first; each exactly the envelope a push would have carried.
Pass as after on the next poll. The after you sent when no
event was new. For after=latest, the newest cursor ("0"
when the workspace has never held an event). Null only when you
sent no after and nothing is held.
hasMoreMore events wait past this page; poll again at once.
gapEvents after your after expired (24 hours) before you fetched
them: the bridge missed something. Tell the channel if you like
("Hijinks was unreachable; some messages were missed") and carry
on from next. Always false without after.