Отправка rich-сообщений
Интеграция
С SDK достаточно трёх действий: укажите форматы в inject(). Для эфемерных сообщений в группах используйте инструкцию по отправке через HTTP.
httpx — прямой REST
# session is an httpx.AsyncClient; tg raises on a Telegram error.API = "https://sidekick-ads.com"AUTH = {"Authorization": "Bearer sk_live_xxxxx"}PLT = "plt_xxxxx"CAPS = {"rich_messages": True, "callbacks": True, "custom_emoji": False}# Private chat, plain text. Send the original reply even if the ad fails.async def reply_with_ad(session, tg, chat_id, user_id, reply, lang):await tg("sendMessage", {"chat_id": chat_id, "text": reply})try:response = await session.post(f"{API}/api/v1/ad", headers=AUTH, timeout=3.0, json={"user_id": user_id, "message": reply, "platform_id": PLT,"language_code": lang or "en","accept_formats": ["text", "response", "card", "consent", "quiz"],"capabilities": CAPS,},)response.raise_for_status()data = response.json()if not data.get("has_ad"):returnad = data["ad"]send = ad.get("send")if send:try:await tg(send["method"], {**send["params"], "chat_id": chat_id})returnexcept Exception:pass # Try the text ad below; do not request another impression.fallback = ad.get("fallback") or adawait tg("sendMessage", {"chat_id": chat_id, "text": "Ad\n" + fallback["text"],"reply_markup": {"inline_keyboard": [[{"text": fallback["button_text"], "url": fallback["button_url"],}]]},})except Exception:pass # Log the ad delivery failure; the bot reply was already sent.# Manual HTTP callback handler. session is an httpx.AsyncClient.# tg(method, params) must raise if Telegram rejects the call.async def on_sidekick_callback(session, tg, callback, api_key, capabilities):data = callback.get("data", "")if not data.startswith("sk:"):return Falsetry:_, token, payload = data.split(":", 2)message = callback["message"]chat = message["chat"]response = await session.post("https://sidekick-ads.com/api/v1/ad/interact",headers={"Authorization": f"Bearer {api_key}"},json={"token": token,"payload": payload,"user_id": callback["from"]["id"],"chat_type": chat["type"],"callback_query_id": callback["id"],"ephemeral_message_id": message.get("ephemeral_message_id"),"capabilities": capabilities,},timeout=3.0,)response.raise_for_status()delivery = response.json()["send"]method = delivery["method"]params = dict(delivery["params"])params.setdefault("chat_id", chat["id"])if method == "editMessageText":params.setdefault("message_id", message["message_id"])await tg(method, params)except Exception:# Report the failure in your logger without credentials or payloads.passfinally:try:await tg("answerCallbackQuery", {"callback_query_id": callback["id"],})except Exception:passreturn True
Требования к клиентам
- •Rich-блоки отображаются в клиентах Telegram, выпущенных 25.08.2026 или позже. В старых клиентах часть блоков может не отображаться, но текст и обычная кнопка
reply_markup(сервер всегда дублирует её) остаются видны. - •Логотипы брендов в виде пользовательских эмодзи отображаются, только если у владельца бота есть Telegram Premium. Указывайте
capabilities.custom_emojiс учётом этого. Иначе вместо логотипа будет название бренда жирным шрифтом. - •Группы: интерактивные сцены после нажатия видны только нажавшему пользователю. Первая сцена отправляется так же, только если бот — администратор чата (
bot_is_admin: true); иначе отправляется обычное сообщение. Telegram разрешает отправку ephemeral-сообщений без предварительного действия пользователя только ботам-администраторам.