Private beta: this contract may change before launch. Join the waitlist
Hijinks
Hijinks Webhook API

WorkspaceId

string · uuid

The Hijinks workspace, as shown in the dashboard.

Error

statusCode
​integer · required
message
​string | array · required

A human-readable reason. Not stable; branch on the status code.

error
​string
field
​string

On a schema 400, the first field at fault (dotted for nested fields).

InboundEvent

oneOf
Exactly one variant must match.

Decision Table

VariantMatching 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
Properties for Variant 1:
A member ran `/hijinks <text>` (or however your chat spells the command).
type
​const · required
Const value: command
​Channel · required

Where the event happened — a bare id, or an id with a display name.

​User · required

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.

text
​string · maxLength: 2000 · required

What followed the command, e.g. start, start science, leaderboard. Empty is help.

id
​RequestId · minLength: 1 · maxLength: 128

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.

RequestId

string · minLength: 1 · maxLength: 128

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

string · minLength: 1 · maxLength: 128 · pattern: ^(?!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

string · maxLength: 131 · pattern: ^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

oneOf
Exactly one variant must match.

Decision Table

VariantMatching Criteria
type = string
type = string
type = object · requires: id
Properties for Variant 1:
ChannelId · minLength: 1 · maxLength: 128 · pattern: ^(?!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

oneOf
Exactly one variant must match.

Decision Table

VariantMatching Criteria
type = string
type = object · requires: id
Properties for Variant 1:
ChannelId · minLength: 1 · maxLength: 128 · pattern: ^(?!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

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.
id
​string · minLength: 1 · maxLength: 128 · required
name
​string | null · maxLength: 128

CommandEvent

A member ran `/hijinks <text>` (or however your chat spells the command).
type
​const · required
Const value: command
​Channel · required

Where the event happened — a bare id, or an id with a display name.

​User · required

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.

text
​string · maxLength: 2000 · required

What followed the command, e.g. start, start science, leaderboard. Empty is help.

id
​RequestId · minLength: 1 · maxLength: 128

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.

ActionEvent

A member pressed a button, in a channel or in their DM.
type
​const · required
Const value: action
​MemberChannel · required

Where the event happened — a channel as in Channel, or the member's own DM as dm:<user.id>, bare or with a display name.

​User · required

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.

messageId
​string · minLength: 1 · maxLength: 128 · required

The Hijinks message.id of the message the button was on.

action
​string · minLength: 1 · maxLength: 512 · required

The button's action, echoed back untouched.

id
​RequestId · minLength: 1 · maxLength: 128

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.

MessageEvent

A member typed something: word-game guesses, rebus and charades answers, replies to a message with `awaitsReply`. A message that answers nothing in play is dropped, so forwarding every message is fine. Typed in the member's DM, it carries `channel: "dm:<user.id>"` and answers the latest awaiting-reply prompt Hijinks sent there; `replyTo`, when present, picks the prompt instead.
type
​const · required
Const value: message
​MemberChannel · required

Where the event happened — a channel as in Channel, or the member's own DM as dm:<user.id>, bare or with a display name.

​User · required

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.

text
​string · minLength: 1 · maxLength: 4000 · required
id
​RequestId · minLength: 1 · maxLength: 128

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.

replyTo
​string | null · maxLength: 128

The Hijinks message.id this replies to, when your chat has replies.

EventId

string · pattern: ^evt_[0-9A-HJKMNP-TV…

Unique per event and unchanged across its retries; dedupe on it.

MessageId

string · pattern: ^msg_[0-9A-HJKMNP-TV…

Minted by Hijinks. Keep a map from it to your chat's message id.

Sequence

integer · int64 · min: 1

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.

CreatedAt

string · date-time

When Hijinks created the event (ISO 8601, UTC).

ExpiresAt

string | null · date-time

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

string · minLength: 1

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.

MemberId

string · minLength: 1

A member's user.id, as your bridge sent it.

MessageKind

string · enum
Enum values:
text
card
game_start
question
time_up
answer_update
gotcha_bait
gotcha_reveal

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

oneOf
Exactly one variant must match.

Decision Table

VariantMatching Criteria
type = object · requires: label, action
type = object · requires: label, url
Properties for Variant 1:
label
​string · required
action
​string · maxLength: 512 · required

Opaque. Echo it back untouched; never parse it.

ActionButton

label
​string · required
action
​string · maxLength: 512 · required

Opaque. Echo it back untouched; never parse it.

LinkButton

label
​string · required
url
​string · uri · required

Message

id
​MessageId · pattern: ^msg_[0-9A-HJKMNP-TV… · required

Minted by Hijinks. Keep a map from it to your chat's message id.

kind
​MessageKind · enum · required

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.

Enum values:
text
card
game_start
question
time_up
answer_update
gotcha_bait
gotcha_reveal
text
​string · required

Chat-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.

​array[] · required

Rows of buttons, top to bottom, each row left to right. Empty when there are none.

image
​string | null · uri · required

An image or GIF to show with the message, or null.

awaitsReply
​boolean · required

Hijinks 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.

data
​object | null · required

The 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
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: message.create
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

channel
​OutboundChannel · minLength: 1 · required

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.

​Message · required

MessageUpdateEvent

id
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: message.update
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

channel
​OutboundChannel · minLength: 1 · required

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.

​Message · required

MessageEphemeralEvent

id
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: message.ephemeral
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

channel
​OutboundChannel · minLength: 1 · required

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.

user
​MemberId · minLength: 1 · required

A member's user.id, as your bridge sent it.

​Message · required

DmCreateEvent

id
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: dm.create
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

user
​MemberId · minLength: 1 · required

A member's user.id, as your bridge sent it.

​Message · required

PingEvent

id
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: ping
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

Cursor

string · pattern: ^\d{1,18}$

A poll position. Opaque; pass it back as after exactly as received.

OutboundEvent

oneOf
Exactly one variant must match.

Decision Table

VariantMatching 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
Properties for Variant 1:
id
​EventId · pattern: ^evt_[0-9A-HJKMNP-TV… · required

Unique per event and unchanged across its retries; dedupe on it.

type
​const · required
Const value: message.create
workspace
​WorkspaceId · uuid · required

The Hijinks workspace, as shown in the dashboard.

sequence
​Sequence · int64 · min: 1 · required

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.

createdAt
​CreatedAt · date-time · required

When Hijinks created the event (ISO 8601, UTC).

expiresAt
​ExpiresAt · date-time · required

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.

channel
​OutboundChannel · minLength: 1 · required

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.

​Message · required

EventPage

​OutboundEvent[] · maxItems: 100 · required

Oldest first; each exactly the envelope a push would have carried.

​required

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.

hasMore
​boolean · required

More events wait past this page; poll again at once.

gap
​boolean · required

Events 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.