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.

EndpointScope
POST /api/apps/channels/{channelId}/chatchat:write
GET /api/apps/channels/{channelId}/chatchat:read
DELETE /api/apps/channels/{channelId}/chat/{messageId}chat:moderate
POST /api/apps/channels/{channelId}/timeoutschat:moderate
POST /api/apps/channels/{channelId}/banschat:moderate
DELETE /api/apps/channels/{channelId}/bans/{userId}chat:moderate

Send a message

POST /api/apps/channels/{channelId}/chat

Body fieldNotes
contentRequired. Up to 500 characters. Runs of whitespace, including newlines, are collapsed to one space and the ends are trimmed.
reply_to_message_idOptional. 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 fieldNotes
user_idRequired. The viewer's profile id (the user_id on their chat messages).
duration_secondsOptional, default 600. Clamped to 1 – 1,209,600 (14 days).
reasonOptional, 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 }
}
KeyNotes
slow_mode_seconds0 – 3600; 0 turns slow mode off. Out-of-range numbers are clamped.
followers_onlyOnly followers can chat.
min_account_age_hours0 – 8760. Accounts younger than this can't chat.
emote_onlyOnly emotes.
gifs_enabledWhether viewers can post GIFs.
announce_followsPost "… 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 fieldNotes
message_idRequired.
duration_minutesOptional, 1 – 1440. Unpin after this long.
until_stream_endOptional. 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}/vips with {"user_id": …}: make a viewer a VIP. Adding an existing VIP succeeds. 404 for 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

StatusWhen
400Empty or too-long content, blocked by the content filter, missing user_id / message_id.
401Missing, wrong or revoked secret: "Invalid application credential".
403Your 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.
404Unknown channel id, a channel with no chat yet, or an unknown message.
429Over the send limit.
{
  "success": false,
  "error": "This app is not on that channel with the chat:write scope",
  "missing_scope": "chat:write"
}