Bot API reference

Everything a KyaChat bot can do, with examples you can paste into a terminal.

Basics

The Bot API is a plain HTTPS API. Each call is one request to

https://api.kyachat.org/bot<token>/<method>

The API uses the conventions most bot frameworks already know: the token in the path, getUpdates or webhooks for incoming updates, and inline keyboards for buttons. Many existing bot libraries work once you set their API base URL to https://api.kyachat.org.

Examples use $TOKEN for your bot’s token. Keep it secret: anyone with the token controls the bot.

Bots and tokens

  • Create a bot in KyaChat Web under Settings > Bots: a name and an @username of 5 to 32 letters, digits or underscores, starting with a letter. You can have up to 20 bots, create 10 an hour and rotate 20 tokens an hour.
  • A token looks like <bot id>:<secret>, where the secret is 43 characters of base64url. It is shown once. KyaChat stores only a hash of it, so Settings shows just the first few characters.
  • Rotate token makes the old token fail straight away. Revoke bot deletes the bot account.
  • The token goes in the URL path only. There is no header form.
  • A bot is an ordinary account, so people find it by @username, open a private chat or add it to groups and channels. In a group a bot receives every message.

Requests and responses

  • Use GET or POST. Parameters can come from a JSON body (Content-Type: application/json), a form (application/x-www-form-urlencoded or multipart/form-data) or the query string. In forms, reply_markup is a JSON string.
  • Success: {"ok":true,"result":...}. Error: {"ok":false,"error_code":N,"description":"..."}, plus "parameters":{"retry_after":S} and a Retry-After header on 429.
curl -sS "https://api.kyachat.org/bot$TOKEN/getUpdates?offset=0&timeout=0"
{"ok":true,"result":[]}

Chat IDs

  • Private chat: chat.id is the person’s user ID, a positive number. A bot can only write to someone who has already messaged it; otherwise the API answers 403.
  • Group or channel: chat.id is a negative number. The bot must be a member. Posting in a channel needs admin rights with permission to post, and the post is signed by the channel (sender_chat).
curl -sS -X POST https://api.kyachat.org/bot$TOKEN/sendMessage -H 'Content-Type: application/json' -d '{"chat_id":2,"text":"Hello"}'
{"ok":false,"error_code":403,"description":"Forbidden: bot can't initiate a conversation with a user who has not messaged it first."}

Methods

getMe

Returns the bot’s own user. A quick way to check a token.

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/getMe
{"ok":true,"result":{"id":4,"is_bot":true,"first_name":"Match Day Bot","username":"matchday_bot"}}

sendMessage

chat_id and text (up to 4,096 characters; **bold**, __italic__ and `code` are shown formatted in the app). Optional reply_to_message_id and reply_markup.inline_keyboard: up to 10 rows of up to 8 buttons. Each button has text (1 to 64 characters) and exactly one of callback_data (1 to 64 bytes) or url (http or https).

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/sendMessage \
  -H 'Content-Type: application/json' \
  -d '{"chat_id":2,"text":"Hi Ben! Are you playing on **Saturday**?",
       "reply_to_message_id":7,
       "reply_markup":{"inline_keyboard":[[{"text":"Yes, count me in","callback_data":"rsvp:yes"},
                                        {"text":"Not this week","callback_data":"rsvp:no"}],
                                       [{"text":"Fixtures","url":"https://example.com/fixtures"}]]}}'

{"ok":true,"result":{"message_id":8,"date":1793154897,
 "chat":{"id":2,"type":"private","first_name":"Ben Ward","username":"benward"},
 "from":{"id":4,"is_bot":true,"first_name":"Match Day Bot","username":"matchday_bot"},
 "text":"Hi Ben! Are you playing on **Saturday**?","reply_to_message":{"message_id":7},
 "reply_markup":{"inline_keyboard":[...]}}}

editMessageText

chat_id, message_id, text and an optional reply_markup. Works on the bot’s own messages for 48 hours. After the edit the buttons are exactly the reply_markup you send: leave it out and the buttons disappear.

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/editMessageText -H 'Content-Type: application/json' \
  -d '{"chat_id":2,"message_id":8,"text":"Great, you are in for Saturday"}'
{"ok":true,"result":{"message_id":8,...,"text":"Great, you are in for Saturday"}}

deleteMessage

chat_id and message_id. The bot’s own messages, or other people’s where the bot is a group admin or a channel admin with permission to delete.

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/deleteMessage -H 'Content-Type: application/json' -d '{"chat_id":2,"message_id":11}'
{"ok":true,"result":true}

sendPhoto and sendDocument

Multipart form with chat_id, a file field photo or document, and optional caption and reply_to_message_id. Photos are converted to WebP (10 MB at most); documents can be up to 25 MB. photo in the result is a single object. Bots cannot download files yet.

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/sendPhoto -F chat_id=2 -F 'photo=@pitch.png;type=image/png' -F 'caption=Pitch 3 tomorrow'
{"ok":true,"result":{"message_id":9,...,"photo":{"file_name":"pitch.webp","mime_type":"image/webp","file_size":12220},"caption":"Pitch 3 tomorrow"}}

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/sendDocument -F chat_id=2 -F 'document=@fixtures.txt;type=text/plain'
{"ok":true,"result":{"message_id":10,...,"document":{"file_name":"fixtures.txt","mime_type":"text/plain","file_size":85}}}

getUpdates

offset (the first update_id you want), limit from 1 to 100 (default 100) and timeout from 0 to 25 seconds for long polling.

  • An offset confirms every update below it for good: they are not returned again, and a webhook set later does not resend them. Updates are kept for 14 days.
  • The API answers 409 while a webhook is set, and 409 for a second long poll by the same bot at the same time.
  • When the server is busy with other long polls, a poll may answer straight away as if timeout were 0. Simply poll again.
  • A bot never receives its own messages or system notices.
curl -sS -X POST https://api.kyachat.org/bot$TOKEN/getUpdates -H 'Content-Type: application/json' -d '{"timeout":10}'
{"ok":true,"result":[{"update_id":59,"message":{"message_id":7,"date":1793153398,"chat":{...},
  "from":{"id":2,"is_bot":false,"first_name":"Ben Ward","username":"benward"},"text":"/start"}}]}

setWebhook and deleteWebhook

url (https only, up to 2,000 characters, no user name or password in it) and an optional secret_token (1 to 256 of A-Z a-z 0-9 _ -).

  • Each update is posted as JSON. When you set a secret, every request carries the header X-KyaChat-Bot-Api-Secret-Token: <secret_token>. Check it before you trust the request.
  • Updates arrive one at a time per bot, in order. Any 2xx answer counts as delivered. Anything else (other status codes, redirects, which are never followed, timeouts of 8 seconds or 5 seconds to connect, TLS errors) is retried after 5 seconds, then 10, 20, 40 and so on up to 5 minutes, until it succeeds or you delete the webhook. Replies in your webhook’s response body are ignored: call the API instead.
  • For safety, webhook addresses that resolve to private, loopback, link-local or other internal networks are refused, both when you set the webhook and before every delivery.
  • deleteWebhook clears the address and the secret. Pending updates are then available to getUpdates.
curl -sS -X POST https://api.kyachat.org/bot$TOKEN/setWebhook -H 'Content-Type: application/json' \
  -d '{"url":"https://bot.example.com/kyachat","secret_token":"my-hook-secret_42"}'
{"ok":true,"result":true}

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/setWebhook -H 'Content-Type: application/json' -d '{"url":"http://bot.example.com/kyachat"}'
{"ok":false,"error_code":422,"description":"The webhook URL must be a plain https:// address."}

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/deleteWebhook
{"ok":true,"result":true}

Not available yet

Methods not listed here answer 404, for example answerCallbackQuery. A button stops showing as busy by itself once the tap is delivered; answer it with editMessageText or sendMessage.

curl -sS -X POST https://api.kyachat.org/bot$TOKEN/answerCallbackQuery -d callback_query_id=x
{"ok":false,"error_code":404,"description":"Method not found: answerCallbackQuery"}

Update objects

Update        {update_id, message | callback_query}
Message       {message_id, date, chat, from | sender_chat, text?,
               photo? | document? | voice? {file_name, mime_type, file_size},
               caption?, reply_to_message? {message_id}, reply_markup? {inline_keyboard}}
Chat          private: {id (user id), type: "private", first_name, username}
              group or channel: {id (negative), type: "group" | "channel", title, username}
User          {id, is_bot, first_name, username}
CallbackQuery {id, from (User), message (Message with its keyboard), data, chat_instance}

A button tap, as a webhook body or a getUpdates item:

{"update_id":66,"callback_query":{"id":"a441b176ab16cbe7f70c814d",
 "from":{"id":2,"is_bot":false,"first_name":"Ben Ward","username":"benward"},
 "message":{"message_id":8,...},"data":"rsvp:yes","chat_instance":"3"}}

Errors

CodeWhen
400The body says JSON but is not valid JSON.
401Wrong, revoked or rotated token.
403A chat the bot may not write to (nobody messaged it first, not a member, no permission to post, blocked), or a message that is not the bot’s to edit.
404Unknown method, or a message that does not exist or the bot cannot see.
409getUpdates while a webhook is set, or a second long poll at the same time.
422A parameter is missing or not valid.
429Too many requests. Wait for retry_after seconds.

Rate limits

  • 120 calls every 10 seconds per bot.
  • 30 wrong tokens a minute from one address. After that, every Bot API call from that address gets 429 for 60 seconds.
  • People tapping buttons: 30 taps every 30 seconds per person.
curl -sS -i -X POST https://api.kyachat.org/bot$TOKEN/getMe      # the 122nd call within 10 seconds
HTTP/1.1 429 Too Many Requests
Retry-After: 2
{"ok":false,"error_code":429,"description":"Too many requests. Slow down.","parameters":{"retry_after":2}}

Questions about the Bot API, or a method you need? Contact KyaChat support.