Skip to content
Documentation menu
HTTP APIConcepts

Rich messages

Telegram examples. Choose your platform →

Text and images

FormatDescription
textA text ad with a CTA. Use inject() to append it to a bot reply, or fetch() to render it yourself.
imageA photo or animation with a caption and CTA. Use fetch() with image accepted, or fetch_image() / fetchImage(). Choose sendPhoto or sendAnimation from media_type.

Rich formats

Beyond the classic text CTA, Sidekick serves four rich ad formats built on Telegram Bot API 10.3 rich messages. The server assembles the complete Bot API payload — your bot (or SDK) only adds chat_id and forwards it. Everything is opt-in: bots that don't declare rich support keep today's behavior byte-for-byte.

FormatDescription
responseSponsored response — brand header (logo + name), ad copy, primary button, «Sponsored» footer. Reads like a native bot reply.
cardSponsored card — brand header, banner image, short text, button row, footer. The visual banner format.
consentConsent ad — a two-line question with «Tell me» / «Not interested». Agreeing reveals the full pitch (slideshow + CTA); declining opts the user out of the campaign.
quizSponsored quiz — questions edited in place, followed by a result card and CTA. Up to 9 questions; any match percentage comes from the campaign’s configured result.

Request additions

Three optional fields on POST /api/v1/ad (and inject()). Omit all of them and nothing changes — you get text ads exactly as today. Unknown accept_formats values are ignored by the server, never rejected, so a newer SDK against an older server keeps serving.

FieldTypeDescription
accept_formatsstring[]Formats your bot can render: "text", "response", "card", "consent", "quiz". Defaults to ["text"]. If no supported, capability-compatible format remains, the server falls back to ["text"].
capabilitiesobjectPython/HTTP: rich_messages, callbacks, custom_emoji. Node.js: richMessages, callbacks, customEmoji. Rich formats need rich_messages; consent/quiz also need callbacks. Declare custom_emoji only when your bot can use it; otherwise the logo becomes a bold brand name.
bot_is_adminbooleanWhether the bot is an admin of the group chat. With group_id, allows ephemeral delivery of scene 1. SDK 0.8.0 sends bot_is_admin but not group_id; use HTTP for group-aware requests.

Response — rich ad served

200 OK
{
"message": "Here is your answer.\n\nРеклама от Sidekick 👇\n\nTry Example for your next project.",
"has_ad": true,
"impression_id": "imp_example",
"ad": {
"text": "Try Example for your next project.",
"formatted_text": "Try Example for your next project.",
"button_text": "Learn more",
"button_url": "https://sidekick-ads.com/api/v1/click/imp_example",
"format": "response",
"send": {
"method": "sendRichMessage",
"params": {
"rich_message": {
"blocks": [
{
"type": "paragraph",
"text": [
{
"type": "bold",
"text": "Example"
}
]
},
{
"type": "paragraph",
"text": "Try Example for your next project."
},
{
"type": "buttons",
"align": "left",
"buttons": [
{
"text": "Learn more",
"style": "primary",
"url": "https://sidekick-ads.com/api/v1/click/imp_example"
}
]
},
{
"type": "footer",
"text": "Sponsored · реклама подобрана Sidekick"
}
]
}
}
},
"fallback": {
"format": "text",
"text": "Try Example for your next project.",
"formatted_text": "Try Example for your next project.",
"button_text": "Learn more",
"button_url": "https://sidekick-ads.com/api/v1/click/imp_example"
}
}
}
  • •ad.send is a ready Bot API call: forward send.params with your chat_id added to send.method. Media inside blocks are HTTPS URLs — Telegram downloads them on send, no uploads on your side.
  • •The invariant: message is always filled with the classic text version (your reply + spliced CTA), and ad.fallback carries the same as separate fields — rendered for your parse_mode. On any Telegram error, send those instead. A rich ad can never break your bot.
  • •send.ephemeral: true (group scene 1 for admin bots) means the payload includes ephemeral delivery — visible only to the target user. If Telegram answers BOT_NOT_ADMIN (rights revoked since your cache), retry the same payload without ephemeral_message_parameters. The SDK send helper does this automatically.
  • •Interactive buttons (consent, quiz) carry callback_data prefixed sk:. Forward the tap to POST /api/v1/ad/interact (same Bearer token) — the server renders the next scene and returns another { method, params } to forward. Include the same capabilities object as on /ad — without custom_emoji the next scene swaps the brand logo for a bold name (the SDK re-sends it automatically). Taps are free: billing follows the campaign model (CPM per impression, or per confirmed action for CPA offers) and never charges per tap; clicks keep going through the tracked redirect.