Edge Handle Reference
Every input and output handle on a flow node has a type, and edges in the flow editor are colored by that type so you can see at a glance what's wired where. This page lists every built-in type, its color, a short description, and — for object types — the shape of the data that travels through the edge.
When you hover a handle in the editor, the tooltip shows the same label and color shown here. If two handles are the same color, they're compatible.
Primitive Types
Special Types
Object Types
These types carry structured data. Use an Extract node to pull individual fields out of an object.
User
A Twitch user.
| Field | Type | Notes |
|---|---|---|
user_id | string | Twitch user ID |
user_login | string | Username (lowercase) |
user_name | string | Display name |
color | string? | Chat color (hex) |
profile_image_url | string? | Profile image URL |
type | string? | "staff", "admin", "global_mod", or "" |
broadcaster_type | string? | "partner", "affiliate", or "" |
Trigger executors only guarantee user_id, user_login, and user_name. Other fields may be absent depending on the trigger source.
Event
A generic event envelope used when a flow processes multiple event kinds through the same wire.
| Field | Type | Notes |
|---|---|---|
type | string | Event type identifier |
timestamp | number | When the event occurred (unix ms) |
payload | object | Event-specific data |
metadata | object? | Optional metadata |
Message
A simplified chat message — just text, fragments, and badges. Use this when you only need the message body.
| Field | Type | Notes |
|---|---|---|
text | string | Full message text |
fragments | array | Text, emote, mention, and cheermote fragments |
badges | array | Sender's chat badges |
Chat Message
The full Twitch chat-message payload — broadcaster + chatter info, message content, color, badges, cheer info, and shared-chat source fields.
| Field | Type | Notes |
|---|---|---|
broadcaster_user_id / _login / _name | string | Channel where the message landed |
chatter_user_id / _login / _name | string | Who sent it |
message_id | string | Unique message ID |
message.text | string | Plain text |
message.fragments | array | Parsed fragments (text / emote / mention / cheermote) |
color | string | Chatter's color (hex) |
badges | array | { set_id, id, info }[] |
message_type | string | "text", "channel_points_highlighted", "power_ups_message_effect", etc. |
cheer | object | null | { bits } when the message includes bits |
channel_points_animation_id | string | null | "simmer", "rainbow-eclipse", "cosmic-abyss" |
channel_points_custom_reward_id | string | null | Set when this message redeemed a custom reward |
source_broadcaster_user_* | string | null | Populated for shared-chat messages |
Redeem
A channel-point custom reward. Core fields are always present from EventSub; the optional settings populate when fetched from the Twitch REST API.
| Field | Type | Notes |
|---|---|---|
id | string | Twitch custom-reward ID |
title | string | Reward title |
cost | number | Point cost |
prompt | string | Description shown to viewers |
is_enabled | boolean? | Settings (REST only) |
background_color | string? | Hex |
is_paused | boolean? | |
is_user_input_required | boolean? | |
max_per_stream_setting | object? | { is_enabled, max_per_stream } |
max_per_user_per_stream_setting | object? | { is_enabled, max_per_user_per_stream } |
global_cooldown_setting | object? | { is_enabled, global_cooldown_seconds } |
should_redemptions_skip_request_queue | boolean? |
Power-up
A custom Power-up — a viewer-funded Bits redemption configured in the Twitch dashboard. Streamerly reads these; Twitch's API doesn't expose create/edit/delete or a redemption queue, so unlike Redeem there's no fulfill/cancel flow.
| Field | Type | Notes |
|---|---|---|
id | string | Twitch power-up ID |
title | string | Power-up title |
bits | number | Cost in Bits |
prompt | string | Description shown to viewers |
redemptionId | string? | Set only on trigger payloads; absent on the data node |
is_enabled | boolean? | Settings (data node only) |
is_paused | boolean? | |
is_in_stock | boolean? | |
is_user_input_required | boolean? | |
background_color | string? | Hex |
max_per_stream_setting | object? | { is_enabled, max_per_stream } |
max_per_user_per_stream_setting | object? | { is_enabled, max_per_user_per_stream } |
global_cooldown_setting | object? | { is_enabled, global_cooldown_seconds } |
Alert Types
These types are created by Alert Builder nodes and consumed by Alert Activator nodes.
SubAlert
Subscription alert payload — { type: "sub", name, tier, months, message, voice?, extra?, assets, display_message?, tts_message? }.
GiftSub
Gifted subscription alert — { type: "gift-subs", name | null, recipient | null, tier, quantity, assets, display_message? }. name is null when the gift is anonymous; recipient is null for bulk announcements.
Cheer
Cheer/bits alert — { type: "cheer", name | null, bits, message, voice?, extra?, assets, display_message?, tts_message? }.
Custom
Custom alert — { type: "custom", name?, data: Record<string, unknown>, assets, display_message? }. Used for alerts you build yourself.
Chatbox Event Payload Types
Each Twitch chatbox event emits its full payload as a single typed object so downstream check nodes / Select Event Variant can branch on it. Field naming is camelCase (matches site convention; normalized from Twitch's snake_case at the backend boundary).
Subscription
New subscription (no message).
| Field | Type | Notes |
|---|---|---|
userId | number? | Local user ID, when resolved |
twitchUserId | string | Twitch user ID |
username | string | |
tier | 1 | 2 | 3 | Mapped from Twitch's 1000/2000/3000 |
isGift | boolean |
Resub
Resubscription with a message.
| Field | Type | Notes |
|---|---|---|
userId | number? | |
twitchUserId | string | |
username | string | |
message | string | User-written resub message |
tier | 1 | 2 | 3 | |
cumulativeMonths | number | |
streakMonths | number |
Gift Sub
Gift sub batch (one or many subs at once).
| Field | Type | Notes |
|---|---|---|
gifterUserId | number? | Absent when anonymous |
gifterTwitchUserId | string? | Absent when anonymous |
gifterUsername | string | "Anonymous" when isAnonymous is true |
isAnonymous | boolean | |
giftCount | number | Number of subs in this batch |
tier | 1 | 2 | 3 | |
cumulativeTotal | number | Lifetime gifts to this channel; 0 when anonymous |
Raid
Incoming raid.
| Field | Type | Notes |
|---|---|---|
raiderUserId | number? | |
raiderTwitchUserId | string | |
raiderUsername | string | |
viewerCount | number |
Follow
New follower.
| Field | Type | Notes |
|---|---|---|
userId | number? | |
twitchUserId | string | |
username | string |
Channel Point Redeem
A custom-reward redemption event.
| Field | Type | Notes |
|---|---|---|
userId | number? | |
twitchUserId | string | |
username | string | |
rewardId | string | Twitch reward UUID — used by redeem-id-equals checks |
rewardTitle | string | |
rewardCost | number | |
rewardPrompt | string | |
userInput | string | Streamer-provided text input; "" when the reward has no input |
Dynamic Types
In addition to the built-in types above, the flow editor supports two dynamically-derived families:
Array Types
Any Array<T> is rendered as a lightened version of the inner type's color, and labeled T[].
Arrays don't nest — there is no Array<Array<X>>.
Custom Types
Custom:Name types get a deterministic HSL color derived from a hash of the name, and are labeled with just Name. Two flows that both define a custom type called WheelEntry will render that handle in the same color, but pick a different name and you'll get a different hue.
Type Compatibility
When you draw an edge between two handles, the types have to be compatible:
- A handle can connect to another handle of the same type.
- Any output can connect to an input of type
any. - A
pulseoutput can connect to most inputs (it acts as a trigger signal). Array<T>connects toArray<T>— arrays do not auto-unwrap.Custom:Fooonly connects toCustom:Foo.
The editor blocks incompatible connections and surfaces an inline error if the types don't match.
Where these come from
The canonical color and label registry is packages/frontend/src/flow/edges/edgeTypeUtils.ts (EDGE_TYPE_COLORS and EDGE_TYPE_LABELS). The data shapes live in:
packages/frontend/src/flow/types/data-structures.ts—FlowUser,FlowMessage,FlowEvent,FlowRedeempackages/shared/src/types/socket.ts—Chatbox*Payloadinterfacespackages/frontend/src/types/Alerts.ts—IAlertSub,IAlertGiftedSubs,IAlertCheer,IAlertCustompackages/shared/src/flow/type-utils.ts— theDataTypeunion and array/custom helpers
When you add a new built-in type, update the registry and this page.