Перейти к содержимому
Разделы документации
HTTP APIВыдача рекламы

Отправка 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"):
return
ad = data["ad"]
send = ad.get("send")
if send:
try:
await tg(send["method"], {**send["params"], "chat_id": chat_id})
return
except Exception:
pass # Try the text ad below; do not request another impression.
fallback = ad.get("fallback") or ad
await 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 False
try:
_, 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.
pass
finally:
try:
await tg("answerCallbackQuery", {
"callback_query_id": callback["id"],
})
except Exception:
pass
return True

Требования к клиентам

  • Rich-блоки отображаются в клиентах Telegram, выпущенных 25.08.2026 или позже. В старых клиентах часть блоков может не отображаться, но текст и обычная кнопка reply_markup (сервер всегда дублирует её) остаются видны.
  • Логотипы брендов в виде пользовательских эмодзи отображаются, только если у владельца бота есть Telegram Premium. Указывайте capabilities.custom_emoji с учётом этого. Иначе вместо логотипа будет название бренда жирным шрифтом.
  • Группы: интерактивные сцены после нажатия видны только нажавшему пользователю. Первая сцена отправляется так же, только если бот — администратор чата (bot_is_admin: true); иначе отправляется обычное сообщение. Telegram разрешает отправку ephemeral-сообщений без предварительного действия пользователя только ботам-администраторам.