Chat
Post in a channel's chat as your bot, read what was said, and moderate. Every endpoint takes your app secret as a Bearer token, and {channelId} is the creator's profile id from GET /api/apps/@me/channels.
| Endpoint | Scope |
|---|---|
POST /api/apps/channels/{channelId}/chat | chat:write |
GET /api/apps/channels/{channelId}/chat | chat:read |
DELETE /api/apps/channels/{channelId}/chat/{messageId} | chat:moderate |
POST /api/apps/channels/{channelId}/timeouts | chat:moderate |
POST /api/apps/channels/{channelId}/bans | chat:moderate |
DELETE /api/apps/channels/{channelId}/bans/{userId} | chat:moderate |
Send a message
POST /api/apps/channels/{channelId}/chat
| Body field | Notes |
|---|---|
content | Required. Up to 500 characters. Runs of whitespace, including newlines, are collapsed to one space and the ends are trimmed. |
reply_to_message_id | Optional. The id of the message you are replying to. |
curl -X POST https://api.thexive.com/api/apps/channels/CHANNEL_ID/chat \
-H "Authorization: Bearer $XIVE_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{"content": "Welcome in!", "reply_to_message_id": "5d2e7c10-4b8a-4f3e-9c61-a0b7d4e2f915"}'
{
"success": true,
"message": {
"id": "8a4c1e07-3d6b-4b2f-a9e5-7c0d2f8b1e64",
"stream_id": "c71d0f2a-8b3e-4a19-b5d6-0e4f9a2c7b18",
"user_id": "app:9b1f3c52-6a0e-4d7b-8f4e-2c1d5a7e9b30",
"display_name": "ModHelper",
"avatar_url": "https://media.xivecdn.com/…/icon.png",
"content": "Welcome in!",
"created_at": "2026-10-11T12:00:00.123Z",
"is_creator": false,
"is_moderator": false,
"is_priority": false,
"is_system": false,
"is_bot": true,
"chat_name_color": null,
"chat_badge": null,
"chat_badge_label": null,
"chat_badge_image": null,
"is_subscriber": false,
"subscriber_months": 0,
"watch_streak": 0,
"reply_to_message_id": "5d2e7c10-4b8a-4f3e-9c61-a0b7d4e2f915"
}
}
The message is posted in the channel's chat room (the live stream, or the most recent one when the creator is offline). Its author is app:<your application id>, shown with your app's name, icon and a BOT badge. avatar_url is your app's icon, or null.
- The platform's content filter applies to bots as it does to everyone. A blocked message gets
400: "That message goes against the community guidelines". - Rate limit: 20 messages per 30 seconds, per app, per channel. Over that you get
429. See Rate limits & errors. - A channel whose creator has never streamed has no chat yet:
404.
Read recent messages
GET /api/apps/channels/{channelId}/chat returns the last 50 messages, oldest first.
{
"success": true,
"stream_id": "c71d0f2a-8b3e-4a19-b5d6-0e4f9a2c7b18",
"messages": [
{
"id": "5d2e7c10-4b8a-4f3e-9c61-a0b7d4e2f915",
"user_id": "1f9a3b6c-7d2e-4c80-b5a4-e6f0d1c2b3a9",
"display_name": "pixelpanda",
"content": "hi!",
"is_system": false,
"is_bot": false,
"reply_to_message_id": null,
"created_at": "2026-10-11T11:59:58.512Z"
}
]
}
A channel with no chat yet answers {"success": true, "messages": []} without a stream_id. For a live feed, use channel.chat.message on EventSub rather than polling.
The channel's own bot
Every channel has a built-in bot that speaks for it: command replies, chest drops, follows, channel-point announcements, and anything the creator's Streamer.bot or Lumia posts as "Channel bot". It uses the creator's name and picture unless they gave it its own in Creator Studio. Its text lines arrive on channel.chat.message with chatter_user_id set to channel_bot:<creator profile id>, chatter_user_login null, the bot's name in chatter_user_name, its picture in avatar_url, is_bot: true and a bot badge. In the recent-messages list above the same lines have that user_id, "is_system": true and "is_bot": true. It isn't a viewer, so it can't be timed out or banned. Don't answer its lines with your own, or two bots can end up replying to each other.
Moderation
All moderation needs chat:moderate and answers {"success": true}. Each action is written to the creator's moderation log with your app's name on it, and reaches viewers' chat immediately.
Delete a message
curl -X DELETE https://api.thexive.com/api/apps/channels/CHANNEL_ID/chat/MESSAGE_ID \ -H "Authorization: Bearer $XIVE_APP_SECRET"
Unknown message: 404 "Message not found".
Time out a viewer
POST /api/apps/channels/{channelId}/timeouts
| Body field | Notes |
|---|---|
user_id | Required. The viewer's profile id (the user_id on their chat messages). |
duration_seconds | Optional, default 600. Clamped to 1 – 1,209,600 (14 days). |
reason | Optional, up to 200 characters. Shown in the moderation log. |
curl -X POST https://api.thexive.com/api/apps/channels/CHANNEL_ID/timeouts \
-H "Authorization: Bearer $XIVE_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{"user_id": "1f9a3b6c-7d2e-4c80-b5a4-e6f0d1c2b3a9", "duration_seconds": 300, "reason": "Spam links"}'
A new timeout for the same viewer replaces the old one.
Ban and unban
POST /api/apps/channels/{channelId}/bans with user_id (required) and reason (optional). Bans don't expire.
curl -X POST https://api.thexive.com/api/apps/channels/CHANNEL_ID/bans \
-H "Authorization: Bearer $XIVE_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{"user_id": "1f9a3b6c-7d2e-4c80-b5a4-e6f0d1c2b3a9", "reason": "Hate speech"}'
DELETE /api/apps/channels/{channelId}/bans/{userId} lifts a ban.
Bots can't act on the broadcaster or the channel's moderators. A timeout, ban or unban aimed at either gets 403 "A bot cannot act on the broadcaster or a moderator", and deleting one of their messages gets 403 too. A missing or malformed user_id gets 400.
Chat settings
GET and PATCH /api/apps/channels/{channelId}/chat/settings, scope chat:moderate. PATCH takes any of the keys below; keys you leave out don't change. Both answer with the full current settings.
curl -X PATCH https://api.thexive.com/api/apps/channels/CHANNEL_ID/chat/settings \
-H "Authorization: Bearer $XIVE_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{"slow_mode_seconds": 10, "emote_only": false}'
{
"success": true,
"settings": { "slow_mode_seconds": 10, "followers_only": false, "min_account_age_hours": 0, "emote_only": false, "gifs_enabled": true, "announce_follows": false }
}
| Key | Notes |
|---|---|
slow_mode_seconds | 0 – 3600; 0 turns slow mode off. Out-of-range numbers are clamped. |
followers_only | Only followers can chat. |
min_account_age_hours | 0 – 8760. Accounts younger than this can't chat. |
emote_only | Only emotes. |
gifs_enabled | Whether viewers can post GIFs. |
announce_follows | Post "… just followed" lines in chat. |
An unknown key or a wrong type gets 400. Settings apply across the creator's channel. Xive has no subscriber-only mode.
Pinned messages
Scope chat:moderate. POST /api/apps/channels/{channelId}/chat/pins pins a message from the current stream, replacing any pin already there.
| Body field | Notes |
|---|---|
message_id | Required. |
duration_minutes | Optional, 1 – 1440. Unpin after this long. |
until_stream_end | Optional. Unpin when the stream ends (the stream must be live). With both set, whichever comes first. |
{ "success": true, "pin": { "message_id": "5d2e7c10-…", "pinned_by": "3e0b8a51-…", "pinned_at": "2026-10-11T12:00:00Z", "expires_at": "2026-10-11T12:30:00Z", "until_stream_end": false } }
With neither lifetime, the pin stays until it's removed. DELETE /api/apps/channels/{channelId}/chat/pins unpins (and succeeds when nothing is pinned). 404 if the message isn't in the current stream's chat.
VIPs
Scope channel:manage.
GET /api/apps/channels/{channelId}/vips:{"vips": [{user_id, username, display_name, avatar_url, added_at}]}, newest first.POST /api/apps/channels/{channelId}/vipswith{"user_id": …}: make a viewer a VIP. Adding an existing VIP succeeds.404for an unknown user; the broadcaster can't be made a VIP.DELETE /api/apps/channels/{channelId}/vips/{userId}: remove one (succeeds when they weren't a VIP).
VIPs can use commands set to vip (see Chat commands).
Errors
| Status | When |
|---|---|
400 | Empty or too-long content, blocked by the content filter, missing user_id / message_id. |
401 | Missing, wrong or revoked secret: "Invalid application credential". |
403 | Your app is not on that channel with the scope this call needs. The body has a missing_scope field. Also: targeting the broadcaster or a moderator. |
404 | Unknown channel id, a channel with no chat yet, or an unknown message. |
429 | Over the send limit. |
{
"success": false,
"error": "This app is not on that channel with the chat:write scope",
"missing_scope": "chat:write"
}