Skip to content
Preview: The API is still being rolled out and details may change before launch. Follow progress in the changelog.

Messages

POST /v1/chats/{chat_id}/messages

Sends 1 to 5 messages into a chat the bot is in. There are two ways:

  • reply: with the event’s reply_token (reply token); every message replies to the message that called the bot.
  • push: without reply_token, at any time. To reply to a particular message, add reply_to_message_id.
Field Type Rules
messages array Required, 1 to 5 (message types); only {"type":"text","text":"..."} for now
reply_token string Optional; single use, 60 seconds, must be for the chat in the path
reply_to_message_id integer Optional; can’t be combined with reply_token
client_id string Optional; A–Z a–z 0–9 _ -, 1 to 60 characters; prevents duplicate posts when you retry
Terminal window
curl -s -X POST https://api.sukson.dev/v1/chats/0b6c3a52-5d0e-4c8e-9a51-6f1e7f6f2b10/messages \
-H "Authorization: Bearer $SUKSON_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "type": "text", "text": "Today'\''s weather" },
{ "type": "text", "text": "Chiang Mai 24–31°C, 40% rain" }
],
"client_id": "daily-2026-11-07"
}'
{
"messages": [
{ "message_id": 812346, "chat_id": "0b6c3a52-5d0e-4c8e-9a51-6f1e7f6f2b10", "created": true },
{ "message_id": 812347, "chat_id": "0b6c3a52-5d0e-4c8e-9a51-6f1e7f6f2b10", "created": true }
]
}
  • created is false when this client_id was already sent: you get the existing message instead of a duplicate. Messages 2 to 5 use your client_id with -2 to -5 appended.
  • Every message counts separately against the monthly quota and the per-chat limits.
  • Messages are sent in order. If one is refused (a rate limit, the quota or a blocked term, say), the rest aren’t sent, but the ones already sent stay. Retrying with the same client_id is safe.
  • The exception is a reply_token request that failed part-way: the token is already spent, so the same retry gets 400 REPLY_TOKEN_INVALID. Retry as a push with the same client_id, using reply_to_message_id (or no reply target) instead of reply_token.
HTTP code When
404 NOT_FOUND No such chat, a malformed chat_id, or a chat the bot isn’t in
403 CHAT_INACTIVE The chat is closed
403 FORBIDDEN details.reason is paused or banned (the bot is paused or banned in this chat; see status in chats), or attacher_lost_rights (whoever added the bot no longer has that right)
403 BANNED The bot is on this room’s ban list (the room’s moderators banned the bot account). Not the same as FORBIDDEN reason banned, which is the bot’s status in the chat
400 REPLY_TOKEN_INVALID Unknown, used, expired, another bot’s or another chat’s token
422 UNSUPPORTED_MESSAGE_TYPE A type that isn’t available yet
422 BANNED_TERM The text contains one of the chat’s blocked terms
429 RATE_LIMITED / SLOW_MODE Too fast; see Retry-After
403 QUOTA_EXCEEDED The monthly quota is used up; wait for next month or change plan

PATCH /v1/messages/{message_id}

Edits one of the bot’s own messages, within 48 hours of sending it.

Terminal window
curl -s -X PATCH https://api.sukson.dev/v1/messages/812346 \
-H "Authorization: Bearer $SUKSON_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"text":"Today'\''s weather (updated 09:00)"}'
{ "message_id": 812346, "chat_id": "0b6c3a52-5d0e-4c8e-9a51-6f1e7f6f2b10" }
Field Rules
text Required, not empty, at most 4,096 characters

Errors: 404 NOT_FOUND (no such message, not one of the bot’s messages, or the bot is no longer in that chat), 403 CHAT_INACTIVE (the chat is closed), 403 FORBIDDEN with details.reason paused, banned or attacher_lost_rights, 429 RATE_LIMITED (details.retry_after), 422 INVALID (empty or too long text), 403 EDIT_WINDOW_PASSED (after 48 hours), 422 NOT_EDITABLE, 422 BANNED_TERM.

DELETE /v1/messages/{message_id}

Deletes one of the bot’s own messages. No body.

{ "message_id": 812346, "chat_id": "0b6c3a52-5d0e-4c8e-9a51-6f1e7f6f2b10" }

Errors: 404 NOT_FOUND (no such message, not one of the bot’s messages, or the bot is no longer in that chat), 403 CHAT_INACTIVE (the chat is closed), 403 FORBIDDEN with details.reason paused, banned or attacher_lost_rights. Bot-wide refusals are on the errors page (FORBIDDEN plan_limit/owner_inactive, RESTRICTED, BOTS_DISABLED).