Developers
Bot API reference
Everything you need to build a Blackbird bot: set-up, every method with examples, the objects your bot receives, and the rules.
The download is the whole reference in one Markdown file, for your notes or your tools.
Introduction
Blackbird bots are programs that chat. You create a bot in the app, get its token, and your code talks to the Bot API over HTTPS with JSON. People find the bot by its @username, press Start, and chat with it like with anyone else. Admins can add bots to groups.
The API follows the shape of Telegram's Bot API, so code written for Telegram needs few changes: the base address and the token header. Telegram libraries put the token in the address, which Blackbird refuses unless the bot's owner turns on Bot Studio › Settings › Telegram libraries; then they work with only the base address changed. See Coming from Telegram.
| Base address | https://api.blackbirdtalk.com/bot/v1/ |
| Auth | Authorization: Bearer <token> on every request (bearer in any case). Not in the address: /bot<token>/... answers 401, unless the owner turned on Telegram libraries |
| Format | JSON in, JSON out. Form-encoded bodies are accepted too. |
| Method names | Case-insensitive: sendMessage, sendmessage and SENDMESSAGE are the same. |
Official libraries
The fastest way to build a bot. Both libraries cover every method on this page, check your buttons against the same rules the server uses before sending, retry safely (a message is never sent twice), handle each chat in order, and come with a fake server for tests. They are generated from the same API description as this page, so a new method reaches them with the next deploy.
| Install | Needs | |
|---|---|---|
| Python | pip install blackbirdtalk | Python 3.11+ |
| JavaScript / TypeScript | npm install @blackbirdtalk/bot | Node.js 22+, Deno, Bun or Workers |
from blackbirdtalk import Bot, Button
bot = Bot() # reads BLACKBIRD_TOKEN
@bot.command("start")
async def start(msg):
await msg.answer("Welcome!", buttons=[[
Button("Pay ₹49", callback="pay_49", style="main", icon="card")]])
@bot.button("pay_49")
async def pay(tap):
await tap.answer("Payment started")
bot.run()import { Bot, Button } from "@blackbirdtalk/bot";
const bot = new Bot(); // reads BLACKBIRD_TOKEN
bot.command("start", (msg) => msg.answer("Welcome!", {
buttons: [[new Button("Pay ₹49", { callback: "pay_49", style: "main", icon: "card" })]],
}));
bot.button("pay_49", (tap) => tap.answer("Payment started"));
bot.start();Each library prints one line a day when a newer version is out. New fields from the server show up on objects even before you update, and a method or parameter newer than your library can still be passed. Their guides: blackbirdtalk on PyPI and @blackbirdtalk/bot on npm. Start a project with blackbirdtalk new mybot (Python) or npx @blackbirdtalk/bot new mybot, and check a token with blackbirdtalk check.
The rest of this page is the HTTP API itself, for other languages and for the details. Each method shows its library name.
Quick start
- In the app open Settings › Bot Studio › New bot. Pick a name and an
@usernameending inbot. Your account must be at least 7 days old; you can own up to 20 bots. - Copy the token from the bot's Overview tab. You can copy it again at any time, or Replace it if it leaks: the old one stops working at once (
401) and the bot's webhook is removed, so set it again with the new token. - Call
getMeto check the token, then read updates withgetUpdatesand answer withsendMessage.
curl -H "Authorization: Bearer $TOKEN" https://api.blackbirdtalk.com/bot/v1/getMeA complete echo bot with plain HTTP (with a library it is a few lines, see Official libraries):
import requests
TOKEN = "bb_..." # from Bot Studio
API = "https://api.blackbirdtalk.com/bot/v1/"
H = {"Authorization": "Bearer " + TOKEN}
offset = 0
while True:
r = requests.post(API + "getUpdates", headers=H,
json={"offset": offset, "timeout": 25}, timeout=40)
for u in r.json()["result"]:
offset = u["update_id"] + 1
m = u.get("message")
if m and m.get("text"):
requests.post(API + "sendMessage", headers=H, json={
"chat_id": m["chat"]["id"],
"text": "You said: " + m["text"],
})const TOKEN = "bb_..."; // from Bot Studio
const API = "https://api.blackbirdtalk.com/bot/v1/";
const H = { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" };
let offset = 0;
for (;;) {
const r = await fetch(API + "getUpdates", { method: "POST", headers: H,
body: JSON.stringify({ offset, timeout: 25 }) });
for (const u of (await r.json()).result) {
offset = u.update_id + 1;
if (u.message?.text) {
await fetch(API + "sendMessage", { method: "POST", headers: H,
body: JSON.stringify({ chat_id: u.message.chat.id, text: "You said: " + u.message.text }) });
}
}
}Making requests
Send every method as POST (or GET) to /bot/v1/<method>. Parameters go in a JSON body, a form-encoded body, or the query string. reply_markup may be an object or a JSON string.
Every answer has ok. On success the value is in result; on failure there is an error_code and a human-readable description.
{"ok": true, "result": {"message_id": 5502, "date": 1793870000, "chat": {...}}}
{"ok": false, "error_code": 400, "description": "Bad Request: text must be 1 to 4096 characters"}The token is not accepted in the URL, where proxies and logs would keep it, unless the bot's owner turned on Telegram libraries (see Coming from Telegram).
Errors
| Code | Meaning | What to do |
|---|---|---|
| 400 | A parameter is missing or wrong. | Read description; it names the parameter. |
| 401 | The token is missing or not valid (maybe replaced in Bot Studio). | Copy the current token from Bot Studio. |
| 403 | Not allowed: the person has not pressed Start, paused the bot, is not on its list (Who can use it), or the group did not give the bot that power. | Don't retry; the person or admin decides. |
| 404 | Unknown method. | Check the name against this page. |
| 409 | getUpdates while a webhook is set, or another program started polling with the same token (the older call ends: "terminated by other getUpdates request"). | Run one copy of your bot per token, and read updates one way: remove the webhook, or stop polling. |
| 429 | Too many messages or calls. | Wait parameters.retry_after seconds (also in the Retry-After header). |
| 500 | Something failed on Blackbird's side. | Retry later with the same client_id. |
Getting updates
An update is something that happened for your bot: a message, a button tap, a group event. Read them in one of two ways, never both:
- Polling with
getUpdates: simplest, works from any computer, no public address needed. - Webhook with
setWebhook: Blackbird POSTs each update to your HTTPS address.
One program per token. A token has one open getUpdates call at a time: when a second program starts polling, the first one's call ends with 409, as on Telegram. A new token (Replace in Bot Studio) or giving the bot away ends the old token's call at once with 401 and removes the webhook (someone holding a leaked token could have pointed it at their own server). Updates still waiting are kept for the new token.
Updates nobody collects are dropped after 24 hours (a bot whose code is down keeps its newest 20,000). Each update has an update_id and one of these fields:
| Field | When |
|---|---|
message | Someone sent the bot a message (in its chat, or addressed to it in a group). |
callback (also callback_query) | Someone tapped one of the bot's message buttons. |
my_membership | The bot was added to or removed from a group. |
member | People joined or left a group the bot is in. |
join_request | Someone asked to join a group where the bot can approve requests. |
access_request | Someone asked to use the bot (Who can use it: Chosen people). Has from. |
access | The owner changed Who can use it in Bot Studio. Has audience, message, allowed. |
poll | New counts for one of the bot's polls, after a vote or when it closes. |
poll_answer | Someone voted in a public poll: poll_id, user, option_ids (empty: vote taken back). |
Webhooks
Each POST to your address carries the secret you set as the X-Blackbird-Bot-Secret header. Check it, so nobody else can feed your bot. Answer with any 2xx within 10 seconds; anything else is retried with growing gaps, and Bot Studio shows the last error. If your server is gone, remove the webhook in Bot Studio › Settings › Webhook. One webhook per bot: a new setWebhook replaces the old address, and ends any open getUpdates call.
Chat ids
You don't look up chat ids, you receive them: every message and callback has chat.id. Keep it if you want to write to that person or group later. Ids are numbers that mean something only to your bot.
- A person's chat id is positive; a group's is negative.
- Your bot can write to a person only after they pressed Start, and never while they have paused it.
- To find your own chat id: send your bot any message, then read
message.chat.idfromgetUpdates. - A group's id is also shown to its admins in Control center › Bots.
Who can use your bot
Each bot has one access setting: Everyone, Only me (owner) or Chosen people (chosen). It can be changed in two places, and both change the same setting: the owner in Bot Studio › Settings › Who can use it, and your code with setAccess. A change made in Bot Studio is sent to your code as an access update, so the two never disagree.
Blackbird enforces the setting on its servers, whatever your code does:
- People who are not allowed can't find the bot in search, write to it or add it to a group. Their messages never reach your bot.
- If your code writes to someone who is not allowed, it gets
403with the reason. - Someone who opens the bot's link sees its chat with its name, photo and your access message (for example "For class 10 students only") in place of the message box. With Chosen people they can also tap Request access.
- A request reaches your code as an
access_requestupdate, appears in Bot Studio, and shows as a line in the owner's own chat with the bot. Approve it from any of them:approveAccessin code, or one tap in Bot Studio or the chat. The person then sees a line in their chat with the bot, yes or no. These lines come from Blackbird: your code never receives them as messages. - The owner and chosen people can add a private bot to their groups; there it answers that group.
// Only people on the list, with a message for everyone else
{"audience": "chosen", "message": "For class 10 students only. Tap Request access.", "allow": [262527487]}Start links
https://blackbirdtalk.com/u/yourbot?start=promo opens your bot in the app. When the person taps Start, you get /start promo (also split into command and args). The payload is 1-64 of A-Z a-z 0-9 _ -. Use it to know where someone came from: a shop page, a QR code on a poster.
Bots in groups
An admin adds a bot in Control center › Bots if the owner allowed groups (Bot Studio › Settings). A bot is never a member: it sees only messages meant for it, which are a /command, a message with its @username, or a reply to one of its messages. In end-to-end encrypted groups the phone sends the bot a readable copy of just those messages.
What else it may do depends on the powers the admin gave it:
| Power | Methods |
|---|---|
| Pin messages | pinMessage, unpinMessage |
| Delete messages | deleteMessage on other people's messages |
| Remove members | removeMember |
| Approve join requests | approveJoin, declineJoin, and join_request updates |
Formatting
Send parse_mode with HTML, MarkdownV2 or Markdown (as on Telegram), or the formatting itself as entities (caption_entities for a file). The app shows bold, *italic*, underline, strikethrough, spoilers (tap to reveal), code and code blocks (tap to copy; a block shows its language and a Copy line), quotes and links. An expandable quote (<blockquote expandable>, or **> ... || in MarkdownV2) folds to three lines with Show more. A link must be http or https; the app shows its address before opening it. Hidden text stays hidden in the chat list, in notifications and in reply quotes.
{"chat_id": 262527487, "parse_mode": "HTML",
"text": "<b>Order #4521</b> confirmed. <a href=\"https://shop.example.com/t/4521\">Track it</a>"}Dates, times and live countdowns use Telegram's date_time: <tg-time unix="1794167173" format="r">2 hours</tg-time> (MarkdownV2: !2 hours). Format r is a live countdown that ticks in the bubble (02:14:33, 3 days 4 hours, then Ended); the bot sends nothing more. Telegram's other letters (w weekday, d/D short/long date, t/T short/long time, for example wDt) show the moment in each person's own language and time zone. A tap shows the full date. Older apps show the words the bot wrote.
The answer has the words without the marks and entities with their place (offsets in UTF-16 units). Unlike Telegram, a mark that is never closed is shown as written instead of failing the call. Older apps show the words without the formatting.
Limits
| Limit | Value |
|---|---|
| Messages | 30 a second per bot; 60 a minute into one private chat; 20 a minute into one group (edits and files count) |
| API calls | 60 a second per bot, any method |
| Typing | One sendChatAction per chat every 3 seconds is shown; extra calls are answered ok |
| Text | 1-4096 characters, counted as Unicode characters: an emoji is one (Telegram counts UTF-16 units, where most emoji are two, so up to twice as many emoji fit here) |
| File caption | Up to 1024 characters, counted the same way |
| Files | The app's size limits (up to 500 MB). Not empty. A file_size you send must be the exact size |
| Albums | 2-10 photos and videos (sendAlbum); at most 500 MB in one request |
| Formatting | Up to 100 entities a message; their offsets and lengths count UTF-16 units, as on Telegram |
| Commands | Up to 100; names 1-32 of a-z 0-9 _; descriptions 1-256 characters |
| Message edits and deletes | Within 48 hours |
| Unread updates | Kept 24 hours |
- Bot chats are not end-to-end encrypted: your server reads them, and the app says so. Never ask for passwords or one-time codes.
- People can report a bot. Many reports in a week switch it off until Blackbird reviews it.
Methods
All methods, in the order you usually meet them.
getMe
Checks the token and returns the bot.
Library: bot.get_me() in Python, bot.getMe() in JavaScript.
No parameters.
Returns The bot: id, username, name, about, can_join_groups, audience (see Who can use your bot).
curl -X POST https://api.blackbirdtalk.com/bot/v1/getMe \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getMe",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getMe", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);getUpdates
Returns new updates, waiting up to timeout seconds when there are none.
Library: bot.get_updates() in Python, bot.getUpdates() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
offset | Integer | No | The last update_id you handled + 1. Confirms everything before it. Negative (-1): keep only the last update and forget older ones. |
limit | Integer | No | 1-100. Default 100. |
timeout | Integer | No | Seconds to wait for an update, 0-25. Use 25. |
Returns A list of updates.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getUpdates \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"offset": 812, "timeout": 25}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getUpdates",
headers={"Authorization": "Bearer " + TOKEN},
json={
"offset": 812,
"timeout": 25
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getUpdates", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"offset": 812, "timeout": 25}),
});
console.log(await r.json());setWebhook
Sends updates to your HTTPS address instead of getUpdates.
Library: bot.set_webhook() in Python, bot.setWebhook() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | String | Yes | A public https address. |
secret_token | String | No | 1-256 of A-Z a-z 0-9 _ -, sent back as X-Blackbird-Bot-Secret. |
drop_pending_updates | Boolean | No | Throw away updates waiting now. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setWebhook \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/hook", "secret_token": "s3cr3t"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setWebhook",
headers={"Authorization": "Bearer " + TOKEN},
json={
"url": "https://example.com/hook",
"secret_token": "s3cr3t"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setWebhook", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"url": "https://example.com/hook", "secret_token": "s3cr3t"}),
});
console.log(await r.json());deleteWebhook
Goes back to getUpdates.
Library: bot.delete_webhook() in Python, bot.deleteWebhook() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
drop_pending_updates | Boolean | No | Throw away updates waiting now. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/deleteWebhook \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/deleteWebhook",
headers={"Authorization": "Bearer " + TOKEN},
json={})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/deleteWebhook", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
console.log(await r.json());getWebhookInfo
The webhook and its health.
Library: bot.get_webhook_info() in Python, bot.getWebhookInfo() in JavaScript.
No parameters.
Returns url, pending_update_count, and last_error_date, last_error_message after a failure.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getWebhookInfo \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getWebhookInfo",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getWebhookInfo", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);sendMessage
Sends a text message.
Library: bot.send_message() in Python, bot.sendMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | From an update's chat.id. |
text | String | Yes | 1-4096 characters. |
reply_to_message_id | Integer | No | Answer a message in the same chat. |
reply_markup | Object | No | Buttons or a keyboard. See Buttons. |
client_id | String | No | Up to 64 characters. Retrying with the same id never sends twice. |
parse_mode | String | No | HTML, Markdown or MarkdownV2. See Formatting. |
entities | Array | No | Instead of parse_mode: Telegram's entities (offsets in UTF-16 units). |
Returns The sent message, with entities when it is formatted.
curl -X POST https://api.blackbirdtalk.com/bot/v1/sendMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "text": "<b>Hello!</b>", "parse_mode": "HTML"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/sendMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"text": "<b>Hello!</b>",
"parse_mode": "HTML"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/sendMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "text": "<b>Hello!</b>", "parse_mode": "HTML"}),
});
console.log(await r.json());copyMessage
Sends a copy of a message the bot can read (in its own chats; never an end-to-end encrypted one), without a link to it.
Library: bot.copy_message() in Python, bot.copyMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | Where the copy goes. |
from_chat_id | Integer | Yes | The chat the message is in: a person's chat with the bot, or a group it is in. |
message_id | Integer | Yes | |
caption | String | No | A new caption for a photo, video or file. Leave it out to keep the caption. |
parse_mode | String | No | Formatting of the new caption. |
caption_entities | Array | No | Instead of parse_mode. |
reply_to_message_id | Integer | No | |
reply_markup | Object | No | Buttons on the copy. The original's buttons are not copied. |
Returns {"message_id": ...} of the copy.
curl -X POST https://api.blackbirdtalk.com/bot/v1/copyMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "from_chat_id": 262527487, "message_id": 5502}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/copyMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"from_chat_id": 262527487,
"message_id": 5502
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/copyMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "from_chat_id": 262527487, "message_id": 5502}),
});
console.log(await r.json());forwardMessage
Forwards a message the bot can read; it shows as "Forwarded", as a person's forward does.
Library: bot.forward_message() in Python, bot.forwardMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | Where it goes. |
from_chat_id | Integer | Yes | The chat the message is in. |
message_id | Integer | Yes |
Returns The forwarded message, with forwarded: true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/forwardMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "from_chat_id": 262527487, "message_id": 5502}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/forwardMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"from_chat_id": 262527487,
"message_id": 5502
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/forwardMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "from_chat_id": 262527487, "message_id": 5502}),
});
console.log(await r.json());editMessage
Changes the text or buttons of one of your bot's messages.
Telegram name: editMessageText, editMessageReplyMarkup, editMessageCaption
Library: bot.edit_message() in Python, bot.editMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
message_id | Integer | Yes | Your bot's message, at most 48 hours old. |
text | String | No | New text, 1-4096 characters. |
reply_markup | Object | No | New buttons; {} removes them. Leave it out to keep them. |
parse_mode | String | No | Formatting of the new text (new text without it is plain). |
entities | Array | No | Instead of parse_mode. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/editMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "message_id": 5502, "text": "Updated"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/editMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"message_id": 5502,
"text": "Updated"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/editMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "message_id": 5502, "text": "Updated"}),
});
console.log(await r.json());deleteMessage
Deletes a message: your bot's own, or in a group anyone's if it has the delete power.
Library: bot.delete_message() in Python, bot.deleteMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
message_id | Integer | Yes | At most 48 hours old. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/deleteMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "message_id": 5502}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/deleteMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"message_id": 5502
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/deleteMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "message_id": 5502}),
});
console.log(await r.json());sendChatAction
Shows "typing…" for a few seconds.
Library: bot.send_chat_action() in Python, bot.sendChatAction() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
action | String | Yes | typing. Telegram's other actions (upload_photo, record_voice, ...) show as typing too. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/sendChatAction \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "action": "typing"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/sendChatAction",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"action": "typing"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/sendChatAction", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "action": "typing"}),
});
console.log(await r.json());answerCallback
Answers a button tap. Answer every tap within 60 seconds, even with nothing.
Telegram name: answerCallbackQuery
Library: bot.answer_callback() in Python, bot.answerCallback() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
callback_id | String | Yes | The callback.id from the update. |
text | String | No | Up to 200 characters, shown as a short note. |
alert | Boolean | No | Show text in a dialog instead. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/answerCallback \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"callback_id": "cb_7f3a", "text": "Saved"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/answerCallback",
headers={"Authorization": "Bearer " + TOKEN},
json={
"callback_id": "cb_7f3a",
"text": "Saved"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/answerCallback", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"callback_id": "cb_7f3a", "text": "Saved"}),
});
console.log(await r.json());setCommands
Sets the list people see when they type /. The same list as Bot Studio › Commands.
Telegram name: setMyCommands, deleteMyCommands
Library: bot.set_commands() in Python, bot.setCommands() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
commands | Array | Yes | [{"command": "quiz", "description": "Start a quiz"}], up to 100. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setCommands \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"commands": [{"command": "quiz", "description": "Start a quiz"}]}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setCommands",
headers={"Authorization": "Bearer " + TOKEN},
json={
"commands": [
{
"command": "quiz",
"description": "Start a quiz"
}
]
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setCommands", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"commands": [{"command": "quiz", "description": "Start a quiz"}]}),
});
console.log(await r.json());getCommands
Returns the command list.
Telegram name: getMyCommands
Library: bot.get_commands() in Python, bot.getCommands() in JavaScript.
No parameters.
Returns A list of {command, description}.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getCommands \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getCommands",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getCommands", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);setName
Changes the bot's name, the same one as Bot Studio › Name.
Telegram name: setMyName
Library: bot.set_name() in Python, bot.setName() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | Yes | 1-64 characters. |
language_code | String | No | Leave out: a bot has one name for every language, so any value is refused. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setName \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Quiz Master"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setName",
headers={"Authorization": "Bearer " + TOKEN},
json={
"name": "Quiz Master"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setName", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"name": "Quiz Master"}),
});
console.log(await r.json());getName
Returns the bot's name.
Telegram name: getMyName
Library: bot.get_name() in Python, bot.getName() in JavaScript.
No parameters.
Returns {name}.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getName \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getName",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getName", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);setDescription
Changes the description people see before they start the bot.
Telegram name: setMyDescription
Library: bot.set_description() in Python, bot.setDescription() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
description | String | No | Up to 512 characters. Empty clears it. |
language_code | String | No | Leave out (one description for every language). |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setDescription \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"description": "Daily quizzes for class 10. Tap Start."}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setDescription",
headers={"Authorization": "Bearer " + TOKEN},
json={
"description": "Daily quizzes for class 10. Tap Start."
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setDescription", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"description": "Daily quizzes for class 10. Tap Start."}),
});
console.log(await r.json());getDescription
Returns the description.
Telegram name: getMyDescription
Library: bot.get_description() in Python, bot.getDescription() in JavaScript.
No parameters.
Returns {description}.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getDescription \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getDescription",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getDescription", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);setAbout
Changes the short line on the bot's profile and in search.
Telegram name: setMyShortDescription
Library: bot.set_about() in Python, bot.setAbout() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
about | String | No | Up to 120 characters. Empty clears it. Telegram's short_description works too. |
language_code | String | No | Leave out (one line for every language). |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setAbout \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"about": "Quizzes every day"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setAbout",
headers={"Authorization": "Bearer " + TOKEN},
json={
"about": "Quizzes every day"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setAbout", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"about": "Quizzes every day"}),
});
console.log(await r.json());getAbout
Returns the short line.
Telegram name: getMyShortDescription
Library: bot.get_about() in Python, bot.getAbout() in JavaScript.
No parameters.
Returns {about, short_description} (the same text twice).
curl -X POST https://api.blackbirdtalk.com/bot/v1/getAbout \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getAbout",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getAbout", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);sendPoll
Sends a poll or a quiz on the app's own poll card. People vote with one tap and see the result at once. The bot gets a poll update with the counts after each vote and, for a public poll, poll_answer (who chose what; an empty option_ids is a vote taken back).
Library: bot.send_poll() in Python, bot.sendPoll() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
question | String | Yes | 1-300 characters. |
options | Array | Yes | 2-12 answers, 1-100 characters each: strings, or Telegram's {"text": ...}. |
is_anonymous | Boolean | No | Default true: nobody, the bot included, learns who chose what. false: the bot gets poll_answer and voters see who voted. |
type | String | No | regular (default) or quiz. |
allows_multiple_answers | Boolean | No | Regular polls only. |
correct_option_id | Integer | No | Quiz: the right answer, from 0. Each person sees it after answering; an answer is final. |
correct_option_ids | Array | No | Instead of correct_option_id: Telegram's newer list, with exactly one answer. |
explanation | String | No | Quiz: up to 200 characters, shown with the right answer. |
open_period | Integer | No | Close by itself after 5 seconds to 7 days (Telegram stops at 10 minutes). |
close_date | Integer | No | Instead of open_period: Unix time to close. |
reply_to_message_id | Integer | No | Answer a message in the same chat. |
reply_markup | Object | No | Buttons under the poll. |
client_id | String | No | Retrying with the same id never sends twice. |
Returns The sent message, with poll: id (the message id as a string), question, options (text, voter_count), total_voter_count, is_closed, is_anonymous, type, allows_multiple_answers, and for a quiz correct_option_id and explanation.
curl -X POST https://api.blackbirdtalk.com/bot/v1/sendPoll \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "question": "Which day suits you?", "options": ["Saturday", "Sunday"], "is_anonymous": false}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/sendPoll",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"question": "Which day suits you?",
"options": [
"Saturday",
"Sunday"
],
"is_anonymous": False
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/sendPoll", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "question": "Which day suits you?", "options": ["Saturday", "Sunday"], "is_anonymous": false}),
});
console.log(await r.json());stopPoll
Closes one of your bot's polls now. Everyone sees the final result.
Library: bot.stop_poll() in Python, bot.stopPoll() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
message_id | Integer | Yes | The poll's message. |
Returns The final poll.
curl -X POST https://api.blackbirdtalk.com/bot/v1/stopPoll \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": 262527487, "message_id": 9041}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/stopPoll",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": 262527487,
"message_id": 9041
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/stopPoll", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": 262527487, "message_id": 9041}),
});
console.log(await r.json());sendDocument
Sends a file. The app shows it by its type: a photo as a photo, a video as a video.
Telegram name: sendPhoto, sendVideo, sendAudio, sendVoice, sendAnimation, sendVideoNote
Library: bot.send_document() in Python, bot.sendDocument() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
file | File | No | Multipart upload; put this part last. Telegram's names (document, photo, video, audio, voice) work too. |
file_id | String | No | Instead of file: a file your bot was sent or sent before (also accepted in photo, document, ...). A web link is not fetched. |
caption | String | No | Up to 1024 characters. |
file_size | Integer | No | The size in bytes, with file, so a too-big file is refused before upload. |
reply_to_message_id | Integer | No | Answer a message in the same chat. |
reply_markup | Object | No | Buttons under the file (in a multipart upload, as a JSON string). |
parse_mode | String | No | Formatting of the caption. |
caption_entities | Array | No | Instead of parse_mode. |
Returns The sent message, with file.
curl -X POST https://api.blackbirdtalk.com/bot/v1/sendDocument \
-H "Authorization: Bearer $TOKEN" \
-F chat_id=262527487 -F caption="Your report" \
-F file=@report.pdfwith open("report.pdf", "rb") as f:
r = requests.post("https://api.blackbirdtalk.com/bot/v1/sendDocument",
headers={"Authorization": "Bearer " + TOKEN},
data={"chat_id": 262527487, "caption": "Your report"},
files={"file": f})sendAlbum
Sends 2-10 photos and videos as one album (or 2-10 documents, or audio files, one after another).
Telegram name: sendMediaGroup
Library: bot.send_album() in Python, bot.sendAlbum() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
media | Array | Yes | 2-10 of {type, media, caption, parse_mode, caption_entities}: type is photo, video, document or audio; media is attach://<name> for an upload or a file_id. Photos and videos may be mixed; documents only with documents, audio only with audio. |
files | File | No | Multipart: each upload in its own field, named as in attach://<name>. |
reply_to_message_id | Integer | No | The first item answers this message. |
Returns The sent messages; an album's carry the same media_group_id. An album shows one caption, the first one given (captions on later photos are not shown).
curl -X POST https://api.blackbirdtalk.com/bot/v1/sendAlbum \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/sendAlbum",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/sendAlbum", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);editMedia
Puts a new photo, video or file (and caption) on one of your bot's file messages, in place.
Telegram name: editMessageMedia
Library: bot.edit_media() in Python, bot.editMedia() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | |
message_id | Integer | Yes | Your bot's photo, video or file message, at most 48 hours old. |
media | Object | Yes | {type, media, caption, parse_mode, caption_entities}, as in sendAlbum. No caption removes it. |
files | File | No | Multipart: the upload, named as in attach://<name>. |
reply_markup | Object | No | New buttons; leave it out to keep them. |
Returns The changed message. The old file is deleted; a photo in an album stays in it.
curl -X POST https://api.blackbirdtalk.com/bot/v1/editMedia \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/editMedia",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/editMedia", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);getFile
Describes a file.
Library: bot.get_file() in Python, bot.getFile() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
file_id | String | Yes | From a message's file. |
Returns file_id, file_name, mime_type, file_size, file_path. Download with GET /bot/v1/file/<file_id> and the same header.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getFile \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"file_id": "48213"}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getFile",
headers={"Authorization": "Bearer " + TOKEN},
json={
"file_id": "48213"
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getFile", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"file_id": "48213"}),
});
console.log(await r.json());getChat
Describes a person's chat or a group.
Library: bot.get_chat() in Python, bot.getChat() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes |
Returns The chat. In a group also my_powers.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getChat \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getChat",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getChat", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213}),
});
console.log(await r.json());getChatMember
Someone's place in a group: creator (the owner), administrator with their powers (and Telegram's can_* fields), member, or left. Ask with the bot's own id to see what the group lets it do.
Library: bot.get_chat_member() in Python, bot.getChatMember() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group, or a person's chat. |
user_id | Integer | Yes | From from.id. |
Returns {status, user, powers, custom_title}. For someone not in the group only their id comes back, never their name.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getChatMember \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getChatMember",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getChatMember", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "user_id": 262527487}),
});
console.log(await r.json());getChatAdmins
The group's owner and admins.
Telegram name: getChatAdministrators
Library: bot.get_chat_admins() in Python, bot.getChatAdmins() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
Returns A list like getChatMember's.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getChatAdmins \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getChatAdmins",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getChatAdmins", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213}),
});
console.log(await r.json());getMemberCount
How many people are in the group now (2 for a private chat).
Telegram name: getChatMemberCount, getChatMembersCount
Library: bot.get_member_count() in Python, bot.getMemberCount() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes |
Returns A number.
curl -X POST https://api.blackbirdtalk.com/bot/v1/getMemberCount \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/getMemberCount",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getMemberCount", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213}),
});
console.log(await r.json());pinMessage
Pins a message in a group. Needs the pin power.
Telegram name: pinChatMessage
Library: bot.pin_message() in Python, bot.pinMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
message_id | Integer | Yes |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/pinMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "message_id": 5502}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/pinMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"message_id": 5502
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/pinMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "message_id": 5502}),
});
console.log(await r.json());unpinMessage
Unpins it.
Telegram name: unpinChatMessage
Library: bot.unpin_message() in Python, bot.unpinMessage() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
message_id | Integer | Yes |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/unpinMessage \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "message_id": 5502}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/unpinMessage",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"message_id": 5502
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/unpinMessage", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "message_id": 5502}),
});
console.log(await r.json());removeMember
Removes someone from a group. Needs the remove power.
Telegram name: banChatMember, kickChatMember
Library: bot.remove_member() in Python, bot.removeMember() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
user_id | Integer | Yes | From from.id. |
ban | Boolean | No | Also stop them from coming back. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/removeMember \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/removeMember",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/removeMember", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "user_id": 262527487}),
});
console.log(await r.json());approveJoin
Lets someone in who asked to join. Needs the approve power.
Telegram name: approveChatJoinRequest
Library: bot.approve_join() in Python, bot.approveJoin() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
user_id | Integer | Yes |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/approveJoin \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/approveJoin",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/approveJoin", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "user_id": 262527487}),
});
console.log(await r.json());declineJoin
Turns the request down.
Telegram name: declineChatJoinRequest
Library: bot.decline_join() in Python, bot.declineJoin() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
user_id | Integer | Yes |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/declineJoin \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213, "user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/declineJoin",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213,
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/declineJoin", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213, "user_id": 262527487}),
});
console.log(await r.json());getAccess
Who can use the bot: the setting, the people on the list, and waiting requests. The same thing Bot Studio shows.
Library: bot.get_access() in Python, bot.getAccess() in JavaScript.
No parameters.
Returns audience (everyone, owner, chosen), message, allowed and requests (lists of users).
curl -X POST https://api.blackbirdtalk.com/bot/v1/getAccess \
-H "Authorization: Bearer $TOKEN"r = requests.post("https://api.blackbirdtalk.com/bot/v1/getAccess",
headers={"Authorization": "Bearer " + TOKEN})
print(r.json()["result"])const r = await fetch("https://api.blackbirdtalk.com/bot/v1/getAccess", { method: "POST",
headers: { "Authorization": "Bearer " + TOKEN } });
console.log((await r.json()).result);setAccess
Changes who can use the bot. Send only what you want to change.
Library: bot.set_access() in Python, bot.setAccess() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
audience | String | No | everyone, owner (only the owner) or chosen (the list). |
message | String | No | Up to 300 characters, shown to people who may not use the bot. |
allow | Array of Integer | No | User ids (from.id) to add to the list. Up to 200 people in all. |
remove | Array of Integer | No | User ids to take off the list. |
Returns The new state, as getAccess.
curl -X POST https://api.blackbirdtalk.com/bot/v1/setAccess \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"audience": "chosen", "message": "For class 10 students only."}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/setAccess",
headers={"Authorization": "Bearer " + TOKEN},
json={
"audience": "chosen",
"message": "For class 10 students only."
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/setAccess", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"audience": "chosen", "message": "For class 10 students only."}),
});
console.log(await r.json());approveAccess
Lets in someone who asked (an access_request update).
Library: bot.approve_access() in Python, bot.approveAccess() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | Integer | Yes | The request's from.id. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/approveAccess \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/approveAccess",
headers={"Authorization": "Bearer " + TOKEN},
json={
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/approveAccess", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"user_id": 262527487}),
});
console.log(await r.json());declineAccess
Turns a request down.
Library: bot.decline_access() in Python, bot.declineAccess() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | Integer | Yes | The request's from.id. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/declineAccess \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id": 262527487}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/declineAccess",
headers={"Authorization": "Bearer " + TOKEN},
json={
"user_id": 262527487
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/declineAccess", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"user_id": 262527487}),
});
console.log(await r.json());leaveGroup
The bot leaves a group.
Telegram name: leaveChat
Library: bot.leave_group() in Python, bot.leaveGroup() in JavaScript.
| Parameter | Type | Required | Description |
|---|---|---|---|
chat_id | Integer | Yes | A group. |
Returns true.
curl -X POST https://api.blackbirdtalk.com/bot/v1/leaveGroup \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"chat_id": -1048213}'r = requests.post("https://api.blackbirdtalk.com/bot/v1/leaveGroup",
headers={"Authorization": "Bearer " + TOKEN},
json={
"chat_id": -1048213
})
print(r.json())const r = await fetch("https://api.blackbirdtalk.com/bot/v1/leaveGroup", {
method: "POST",
headers: { "Authorization": "Bearer " + TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({"chat_id": -1048213}),
});
console.log(await r.json());Objects
What updates and results are made of.
Update
| Field | Type | Description |
|---|---|---|
update_id | Integer | Increasing number. |
message | Message | Optional. |
callback | Callback | Optional. Also as callback_query. |
my_membership | Object | Optional. chat, status (added, removed), by, date. |
member | Object | Optional. chat, event (joined, left, removed), users, by, date. |
join_request | Object | Optional. chat, from, answer, date. |
access_request | Object | Optional. from, date. |
access | Object | Optional. audience, message, allowed, changed_in, date. |
poll | Object | Optional. The poll, as sendPoll returns it. |
poll_answer | Object | Optional. poll_id, user, option_ids. |
Message
| Field | Type | Description |
|---|---|---|
message_id | Integer | |
date | Integer | Unix time. |
chat | Chat | |
from | User | |
text | String | Optional. |
command | String | Optional. quiz for "/quiz physics". |
args | String | Optional. physics. |
entities | Array | Optional. With a command: [{"type": "bot_command", "offset": 0, "length": 5}], as on Telegram. |
contact | Contact | Optional. Someone shared their contact with a request: contact button. |
location | Object | Optional. latitude, longitude, shared with a request: location button. |
kind | String | Optional. For a file: image, video, voice, doc (from the file's type, so a PNG sent with sendDocument is image and shows as a photo). |
caption | String | Optional. A file's caption. |
file | File | Optional. |
photo, document, video, voice | Object | Optional. The same file under Telegram's name for its kind (photo is a list with one size: file_id, width, height, file_size). |
reply_to_message_id | Integer | Optional. |
Chat
| Field | Type | Description |
|---|---|---|
id | Integer | Positive for a person, negative for a group. |
type | String | private or group. |
name | String | A person's name (also first_name). |
username | String | A person's username. |
title | String | A group's name. |
member_count | Integer | A group's size. |
User
| Field | Type | Description |
|---|---|---|
id | Integer | |
is_bot | Boolean | |
name | String | Also first_name. |
username | String |
Callback
| Field | Type | Description |
|---|---|---|
id | String | Pass to answerCallback. |
from | User | |
message | Message | The message with the button: message_id, date, chat, from, text, and its buttons as reply_markup (inline_keyboard). |
data | String | The button's callback. |
Contact
| Field | Type | Description |
|---|---|---|
id | Integer | The person's id (also user_id). |
name | String | Also first_name. |
username | String | |
is_bot | Boolean | |
phone_number | String | Always empty: Blackbird never gives a bot a phone number or e-mail. |
File
| Field | Type | Description |
|---|---|---|
file_id | String | |
file_unique_id | String | The same for every copy of one file (sent again by file_id); use it to spot a file you have seen. |
file_name | String | |
mime_type | String | Decided by Blackbird from the file's bytes, not from the upload's label. |
file_size | Integer | Bytes. |
Coming from Telegram
Code written for Telegram's Bot API works with these differences. Where both names are listed, either one works.
| Telegram | Blackbird | |
|---|---|---|
| Base address | https://api.telegram.org/bot<token>/ | https://api.blackbirdtalk.com/bot/v1/ + header Authorization: Bearer <token>. The token is not taken from the address by default (/bot<token>/... answers 401 JSON), because addresses end up in logs. Telegram libraries (python-telegram-bot, aiogram, Telegraf, node-telegram-bot-api) can change only the base address: turn on Bot Studio › Settings › Telegram libraries and set it to https://api.blackbirdtalk.com/bot (files: https://api.blackbirdtalk.com/file/bot). Turn it on only for such code; if the token may have leaked into a log, press Replace token. The official libraries need nothing |
| Token | 123456:ABC... | bb_123456_ABC...; Telegram's shape 123456:ABC... (the same token, bb_ dropped and the first _ made :) is accepted too, for libraries that check it (aiogram) |
| Button taps | callback_query | callback (also sent as callback_query) |
| Answer a tap | answerCallbackQuery, callback_query_id, show_alert | answerCallback, callback_id, alert (both accepted) |
| Edit | editMessageText, editMessageReplyMarkup | editMessage (both accepted) |
| Commands | setMyCommands, getMyCommands | setCommands, getCommands (both accepted) |
| Name and texts | setMyName, setMyDescription, setMyShortDescription and the get ones | setName, setDescription, setAbout and the get ones (both accepted). One text for every language: a language_code is refused |
| Members | getChatMember, getChatAdministrators, getChatMemberCount | The same, with getChatAdmins and getMemberCount as Blackbird's names. Someone outside the group comes back as left with only their id |
| Incoming commands | entities with bot_command | Same entities, plus command and args ready to use |
| Shared contact | contact with phone_number, first_name, user_id | user_id, first_name (and name, username); phone_number is always empty |
| Message buttons | inline_keyboard with callback_data, url, copy_text | buttons with callback, url, copy (both accepted) |
| Button colours | style: primary, success, danger | Same names (primary is main), plus warning and normal |
| Keyboard | keyboard, one_time_keyboard, input_field_placeholder | keyboard, one_time, placeholder (both accepted) |
| Person's name | first_name, last_name | name (also sent as first_name) |
| Groups | banChatMember, pinChatMessage, approveChatJoinRequest, leaveChat | removeMember, pinMessage, approveJoin, leaveGroup (both accepted) |
| Formatting | parse_mode (HTML, Markdown, MarkdownV2), entities | Same, shown in the app (links: http and https only). A mark that is never closed is shown as written instead of a 400 |
| Dates and times | date_time (<tg-time>, tg://time) | Same; format r is a live countdown that ticks in the app |
| Albums | sendMediaGroup with attach:// files | Same (sendAlbum); one caption per album, the first one given |
| Change a file | editMessageMedia | Same (editMedia) |
| Copy and forward | copyMessage, forwardMessage | Same, for messages the bot can read; a forward shows "Forwarded" |
| Files | sendPhoto, sendDocument, ... with the file in photo, document, ... | Same names accepted (also file); a web link is not fetched, upload the file. The type comes from the file's bytes, never its label: a photo sent with sendDocument shows as a photo, sendPhoto with something that is not a picture is refused (400), an SVG is always a document, and a file that is not the video or sound it claims arrives as a document |
| Replies | reply_parameters or reply_to_message_id | Both accepted |
| Chat actions | typing, upload_photo, record_voice, ... | All accepted, all shown as typing |
| Webhook secret | X-Telegram-Bot-Api-Secret-Token | Sent too, beside X-Blackbird-Bot-Secret |
| Files people send | photo (sizes), document, video, voice | Same fields (one photo size, with its width and height), plus file and kind |
| Sent message's buttons | reply_markup.inline_keyboard | Same, beside buttons; a keyboard is not echoed, as on Telegram |
| Polls | sendPoll, stopPoll, poll and poll_answer updates | Same, on the app's poll card; a poll can stay open up to 7 days (open_period), not only 10 minutes |
| Not available | inline mode, payments, stickers, games, mini apps; sendLocation, sendContact, logOut, close | Answer 404 unknown method. The photo is set in Bot Studio |
Questions or a bug in the API: buildsevaa@gmail.com