Добавьте спонсоров в бота за 5 минут
ParadiseGram подбирает спонсоров, создаёт отдельный Smart Link для каждого задания и проверяет выполнение. Вам нужны только два запроса: получить задания и проверить их.
https://www.paradisegram.ruAPI-ключ передавайте только со своего сервера: Authorization: Bearer pg_live_...
Актуальная стоимость
Smart Link работает всегда — для всех ботов и пользователей, без исключений. Это обязательный контур защиты.
Быстрый старт за 5 минут
- В @ParadiseGrmbot откройте Зарабатывать → Новый заказ → Бот.
- Выберите подключение с токеном или без токена через API, затем дождитесь модерации.
- Скопируйте API-ключ из карточки бота → Интеграция API.
- Перед выдачей основного контента вызовите
POST /v1/tasks/resolve. - Если пришёл
tasks_required, покажите все кнопки изtasksи не выдавайте контент до проверки. - Кнопка «Проверить» вызывает
POST /v1/tasks/verify-all. Когда невыполненных заданий не осталось — продолжайте основной сценарий бота.
tasks — продолжить; непустой tasks — показать Smart Link и дождаться проверки.Добавление бота: с токеном или без
С токеном · под ключ
Отправьте токен от @BotFather. ParadiseGram хранит его зашифрованным и может самостоятельно отправлять пользователю готовый блок спонсоров.
Подходит: если хотите минимум кода.
Без токена · API-only
Telegram-токен не передаётся. Отправьте одну строку:
8802642146 @SignalBot Signal BotВместо username можно указать https://t.me/SignalBot. Вы получите такой же API-ключ, настройки, статистику и модерацию, но кнопки показываете своим кодом.
| Возможность | С токеном | Без токена |
|---|---|---|
| Получение спонсоров | Да | Да |
| Smart Link и проверка | Да | Да |
| Настройки, лимит, статистика | Да | Да |
| Кто отправляет кнопки | ParadiseGram или ваш код | Только ваш код |
| Telegram-токен хранится | Зашифрованно | Нет |
Логика как в блоке обязательной подписки
| status | Что делать вашему боту |
|---|---|
tasks_required | Показать каждую ссылку из tasks, добавить кнопку «Проверить», основной контент пока не выдавать. |
delivered | ParadiseGram уже отправил готовый блок. Остановить текущий обработчик и ждать проверки. |
no_tasks / completed | Спонсоров нет либо всё выполнено — продолжить основной сценарий. |
user_not_in_bot | Попросить пользователя сначала запустить вашего бота. Для API-only без токена эта проверка недоступна и статус обычно не используется. |
| HTTP 5xx / сеть | Записать ошибку и не ломать бота. Рекомендуемый режим — пропустить пользователя, затем повторить запрос при следующем действии. |
Количество ссылок равно числу реально доступных заданий, но не превышает настройку «Макс. спонсоров». Уже выполненные задания и каналы, на которые пользователь подписан, повторно не выдаются.
Готовое задание для ChatGPT, Codex или другого ИИ
Скопируйте блок целиком и вставьте в ИИ вместе с исходниками своего бота:
Интегрируй ParadiseGram Publisher API в моего Telegram-бота.
Base URL: https://www.paradisegram.ru
API key бери из переменной окружения PARADISEGRAM_API_KEY и никогда не отправляй в Telegram или клиентский JavaScript.
Перед выдачей основного контента вызывай POST /v1/tasks/resolve с user_id, chat_id, username, first_name, language_code и is_premium.
Если status=tasks_required, покажи ВСЕ элементы tasks. Для каждого используй title, button_text, url и строго соблюдай open_mode: url = обычная URL-кнопка, webapp = WebAppInfo.
Добавь кнопку «Проверить», которая вызывает POST /v1/tasks/verify-all с user_id.
Если остались incomplete/pending — снова покажи невыполненные задания. Если всё verified либо resolve вернул no_tasks/completed — продолжи исходный сценарий бота.
Награду начисляй только один раз и только когда verify вернул status=verified и rewardable=true.
На таймаут/HTTP 5xx логируй request_id и не ломай пользователю основной бот.
Не удаляй существующие интеграции и обработчики. Добавь таймаут 10 секунд, защиту от двойного начисления и тесты.Готовый минимальный пример · aiogram 3
Этот пример показывает весь обязательный цикл: resolve → кнопки → verify-all → продолжение.
import os
import httpx
from aiogram import F, Router
from aiogram.filters import CommandStart
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message, CallbackQuery, WebAppInfo
router = Router()
BASE_URL = "https://www.paradisegram.ru"
API_KEY = os.environ["PARADISEGRAM_API_KEY"]
async def paradise_post(path: str, payload: dict) -> dict:
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
BASE_URL + path,
headers={"Authorization": f"Bearer {API_KEY}"},
json=payload,
)
response.raise_for_status()
return response.json()
async def resolve_for(user, chat_id: int) -> dict:
return await paradise_post("/v1/tasks/resolve", {
"user_id": user.id,
"chat_id": chat_id,
"username": user.username,
"first_name": user.first_name,
"language_code": user.language_code,
"is_premium": bool(user.is_premium),
"limit": 10,
})
async def show_sponsors(message: Message, data: dict) -> bool:
tasks = data.get("tasks") or []
if not tasks:
return False
rows = []
for task in tasks:
kwargs = {"text": task.get("button_text") or task["title"]}
if task.get("open_mode") == "webapp":
kwargs["web_app"] = WebAppInfo(url=task["url"])
else:
kwargs["url"] = task["url"]
rows.append([InlineKeyboardButton(**kwargs)])
rows.append([InlineKeyboardButton(text="Проверить", callback_data="pg:check")])
await message.answer("Выполните задания:", reply_markup=InlineKeyboardMarkup(inline_keyboard=rows))
return True
async def send_main_content(message: Message) -> None:
await message.answer("Основной контент вашего бота")
@router.message(CommandStart())
async def start(message: Message) -> None:
try:
data = await resolve_for(message.from_user, message.chat.id)
if await show_sponsors(message, data):
return
except httpx.HTTPError:
pass # API временно недоступен: не ломаем основной бот
await send_main_content(message)
@router.callback_query(F.data == "pg:check")
async def check(callback: CallbackQuery) -> None:
await callback.answer("Проверяем...")
try:
await paradise_post("/v1/tasks/verify-all", {"user_id": callback.from_user.id})
data = await resolve_for(callback.from_user, callback.message.chat.id)
if await show_sponsors(callback.message, data):
return
except httpx.HTTPError:
await callback.message.answer("Проверка временно недоступна. Попробуйте ещё раз.")
return
await send_main_content(callback.message)Для JavaScript, PHP и cURL используйте готовые вкладки ниже. Контракт ответа одинаковый для всех языков.
Авторизация
Authorization: Bearer pg_live_...Ключ передаётся только в заголовке защищённых методов. Не помещайте его в URL, клиентский JavaScript, кнопки, логи или репозиторий. Каждый ответ содержит X-Request-ID; тело ошибки содержит тот же request_id.
Получить задания
POST /v1/tasks/resolve
Вызывайте перед основным контентом, чтобы получить актуальные задания для конкретного пользователя.
curl -X POST "https://www.paradisegram.ru/v1/tasks/resolve" -H "Authorization: Bearer pg_live_..." -H "Content-Type: application/json" -d '{"user_id":123456789,"chat_id":123456789,"username":"ivan","first_name":"Иван","language_code":"ru","is_premium":false,"limit":3}'import httpx
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
"https://www.paradisegram.ru/v1/tasks/resolve",
headers={"Authorization": "Bearer pg_live_..."},
json={"user_id": 123456789, "chat_id": 123456789, "username": "ivan", "first_name": "Иван", "language_code": "ru", "is_premium": False, "limit": 3},
)
response.raise_for_status()
print(response.json())// Node.js 18+ · выполняйте только на сервере
const response = await fetch("https://www.paradisegram.ru/v1/tasks/resolve", {
method: "POST",
headers: { Authorization: "Bearer pg_live_...", "Content-Type": "application/json" },
body: JSON.stringify({ user_id: 123456789, chat_id: 123456789, username: "ivan", first_name: "Иван", language_code: "ru", is_premium: false, limit: 3 }),
});
console.log(await response.json());<?php
$ch = curl_init("https://www.paradisegram.ru/v1/tasks/resolve");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer pg_live_...", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["user_id" => 123456789, "chat_id" => 123456789, "username" => "ivan", "first_name" => "Иван", "language_code" => "ru", "is_premium" => false, "limit" => 3]),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);{
"status": "tasks_required",
"tasks": [
{
"task_id": "01J...",
"title": "Подписаться",
"action_type": "channel",
"button_text": "Открыть",
"url": "https://example.com/smart/token",
"open_mode": "url",
"price": 0.84,
"expires_at": "2026-08-23T12:30:00Z",
"status": "pending"
}
],
"expires_at": "2026-08-23T12:30:00Z",
"message": "Покажите все Smart Link пользователю обычными URL-кнопками."
}limit принимает 1–10, но фактическое число ограничено настройкой «Макс. спонсоров» бота. Все значения url ведут через Smart Link, а action_type сохраняет реальное условие спонсора: channel или bot. Всегда соблюдайте open_mode: url открывайте обычной URL-кнопкой, webapp — как Telegram Web App.
Проверить одно задание
POST /v1/tasks/{task_id}/verify
Когда выбирать: Используйте, когда у вас есть task_id одной конкретной кнопки и нужно обновить только её состояние.
curl -X POST "https://www.paradisegram.ru/v1/tasks/TASK_ID/verify" -H "Authorization: Bearer pg_live_..." -H "Content-Type: application/json" -d '{"user_id":123456789}'import httpx
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
"https://www.paradisegram.ru/v1/tasks/TASK_ID/verify",
headers={"Authorization": "Bearer pg_live_..."},
json={"user_id": 123456789},
)
response.raise_for_status()
print(response.json())// Node.js 18+ · выполняйте только на сервере
const response = await fetch("https://www.paradisegram.ru/v1/tasks/TASK_ID/verify", {
method: "POST",
headers: { Authorization: "Bearer pg_live_...", "Content-Type": "application/json" },
body: JSON.stringify({ user_id: 123456789 }),
});
console.log(await response.json());<?php
$ch = curl_init("https://www.paradisegram.ru/v1/tasks/TASK_ID/verify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer pg_live_...", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["user_id" => 123456789]),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);{
"status": "verified",
"task_id": "TASK_ID",
"message": "Задание подтверждено",
"rewardable": true
}Проверить все активные задания
POST /v1/tasks/verify-all
Когда выбирать: Используйте после показа всего списка, когда одна кнопка «Проверить» должна перепроверить все выданные пользователю задания.
curl -X POST "https://www.paradisegram.ru/v1/tasks/verify-all" -H "Authorization: Bearer pg_live_..." -H "Content-Type: application/json" -d '{"user_id":123456789}'import httpx
async with httpx.AsyncClient(timeout=10) as client:
response = await client.post(
"https://www.paradisegram.ru/v1/tasks/verify-all",
headers={"Authorization": "Bearer pg_live_..."},
json={"user_id": 123456789},
)
response.raise_for_status()
print(response.json())// Node.js 18+ · выполняйте только на сервере
const response = await fetch("https://www.paradisegram.ru/v1/tasks/verify-all", {
method: "POST",
headers: { Authorization: "Bearer pg_live_...", "Content-Type": "application/json" },
body: JSON.stringify({ user_id: 123456789 }),
});
console.log(await response.json());<?php
$ch = curl_init("https://www.paradisegram.ru/v1/tasks/verify-all");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer pg_live_...", "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["user_id" => 123456789]),
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);{
"status": "checked",
"checked": 2,
"verified": 1,
"results": [
{
"status": "verified",
"task_id": "01J...",
"message": "Задание подтверждено",
"title": "Канал Alpha",
"action_type": "channel",
"url": "https://www.paradisegram.ru/r/SIGNED_TOKEN_ALPHA",
"rewardable": true,
"completed": true
},
{
"status": "incomplete",
"task_id": "01K...",
"message": "Действие пока не выполнено",
"title": "Канал Beta",
"action_type": "channel",
"url": "https://www.paradisegram.ru/r/SIGNED_TOKEN_BETA",
"rewardable": false,
"completed": false
}
],
"message": "Проверено: 2. Подтверждено: 1."
}Поля контракта
Resolve request
| Поле | Тип | Правило |
|---|---|---|
user_id | integer > 0 | Обязательно; Telegram ID. |
chat_id | integer | Обязательно; чат для managed-режима. |
username | string ≤ 64 | Необязательно. |
first_name | string ≤ 128 | Необязательно. |
language_code | string ≤ 12 | Необязательно; язык Telegram. |
is_premium | boolean | По умолчанию false. |
limit | integer 1–10 | По умолчанию 4; итог дополнительно ограничен настройкой бота и числом доступных спонсоров. |
Resolve response / Task item
Верхний уровень: status, массив tasks, ближайший expires_at или null и message. Элемент tasks: task_id, title, action_type, button_text, подписанный Smart Link в url, open_mode, price, expires_at, status.
Verify request / response
Оба метода принимают обязательный user_id. Одиночный ответ: status, task_id, message, rewardable. Начисляйте свою награду только при status=verified и rewardable=true. Групповой ответ содержит status, checked, verified, массив results и message. Каждый элемент results содержит task_id, title, action_type, url, completed, rewardable, точный status и пояснение message.
Статусы
| Статус | Действие интеграции |
|---|---|
tasks_required | Показать задания и проверку. |
delivered | Готовый блок уже отправлен ботом. |
no_tasks | Подходящих заданий сейчас нет. |
completed | Ранее выданные задания завершены. |
checked | Изучить каждый элемент results. |
verified | Разрешить продолжение. |
incomplete / pending | Предложить выполнить действие и повторить. |
expired | Вызвать resolve заново. |
not_found | Проверить ключ, task_id и user_id. |
blocked | Не обходить ограничение. |
configuration_error | Цель настроена неверно. |
verification_unavailable | Повторить позже без нового задания. |
Идемпотентность
Повторный или параллельный resolve для того же пользователя не создаёт двойной резерв одного заказа. Каждое активное назначение получает одну стабильную Smart Link. Повторный verify подтверждённого задания снова возвращает verified без второй выплаты; дополнительную награду на своей стороне защищайте уникальным task_id. После сетевого таймаута повторяйте тот же запрос с теми же идентификаторами.
Smart Link и защита трафика
Каждый спонсор выдаётся отдельным Smart Link. Владелец бота не может отключить проверку.
POST /v1/tasks/resolve возвращает до настройки «Макс. спонсоров» разных заданий. Каждое значение url является Smart Link, а action_type сообщает реальное условие (channel или bot). Если подходящих спонсоров меньше, массив tasks тоже будет короче; пустые ссылки не создаются. Каждая ссылка закреплена за своим назначением и после проверки сразу открывает именно его.
Ссылка работает в обычном браузере при open_mode=url; Telegram Mini App не требуется. При open_mode=webapp открывайте её как Web App: тогда сервис дополнительно проверяет Telegram initData. Один URL можно безопасно открыть повторно после сетевой ошибки — второе назначение и двойной резерв не появятся.
При проверке задания поле rewardable=true означает подтверждённое платное действие. Для старых ссылок без закреплённого спонсора либо при его отсутствии сервис возвращает rewardable=false, поэтому интеграция не должна начислять награду.
country — страна для текущего геотаргетинга. Обычно это страна выхода IP. При явном VPN/proxy применяется безопасная RU-политика; если GeoIP пропустил VPN, согласие любых двух сигналов — Telegram-языка, языка браузера и IANA timezone — восстанавливает соответствующую СНГ-страну. Такое значение помечается источником network_policy или locale_policy и уверенностью inferred, а не выдаётся за точную физическую геолокацию.
VPN/proxy — это флаг риска и сам по себе не скрывает кампании. Уже выполненные, активные или фактически оформленные подписки не выдаются повторно.
Безопасность и приватность
- Используйте HTTPS и храните ключ только на сервере.
- Не доверяйте username или имени как идентификатору: используйте связку ключа,
user_idиtask_id. - Сырые IP и отпечатки устройства не сохраняются; хранятся HMAC-хэши, агрегированные признаки, риск и причины.
- Не подменяйте подписанные URL и не обходите редиректы ParadiseGram.
- Передавайте поддержке
request_id, но никогда не API-ключ.
HTTP-ошибки и статусы
{"error":{"code":"invalid_request","message":"Проверьте параметры запроса.","hint":"Исправьте fields.","fields":[{"field":"user_id","message":"..."}]},"request_id":"8f5b..."}| HTTP / статус | Код | Действие |
|---|---|---|
| 200 | user_not_in_bot | Не показывать Smart Link или спонсоров: пользователь ещё не запускал подключённого бота. |
| 401 | missing_api_key, invalid_api_key | Добавить Bearer или заменить ключ. |
| 403 | publisher_blocked, publisher_not_approved, publisher_inactive, publisher_owner_blocked | Проверить статус бота. |
| 409 | managed_mode_requires_token | Вернуть Telegram-токен. |
| 422 | invalid_request | Исправить fields. |
| 429 | http_429 | Соблюсти Retry-After и повторить. |
| 500 | internal_error | Повторить позже, сохранить request_id. |
| 502 | managed_delivery_failed | Проверить подключённого бота. |