Запрашиваете до 10 спонсоров одним списком, показываете их пользователю, затем проверяете сессию через /api/v1/check.
Интеграция без догадок
Два независимых режима: обязательная подписка списком и последовательные задания. Ниже — контракт запросов, ответы и рабочие примеры на cURL, Python и JavaScript.
Быстрый старт
Запрашиваете ровно одно текущее задание. После check или skip сразу можно получать следующее — без cooldown между заданиями.
Auth.import os
import aiohttp
BASE_URL = "https://darkboosts.com"
API_KEY = os.environ["DARKBOOST_API_KEY"]
async def post_json(path, payload):
headers = {"Auth": API_KEY, "Content-Type": "application/json"}
async with aiohttp.ClientSession(headers=headers) as session:
async with session.post(BASE_URL + path, json=payload) as response:
response.raise_for_status()
return await response.json()Получить список обязательных спонсоров
Передавайте Telegram-профиль пользователя, который уже известен вашему боту. DarkBoost создаёт или возвращает активную сессию и выдаёт максимум max_sponsors элементов.
curl -X POST https://darkboosts.com/api/v1/sponsors \
-H 'Content-Type: application/json' \
-H 'Auth: YOUR_API_KEY' \
-d '{
"user_id": 123456789,
"chat_id": 123456789,
"username": "weitov",
"first_name": "User",
"last_name": "Example",
"language_code": "ru",
"is_premium": true,
"max_sponsors": 5
}'import aiohttp
async def get_sponsors(tg_user):
payload = {
"user_id": tg_user.id,
"chat_id": tg_user.id,
"username": tg_user.username or "",
"first_name": tg_user.first_name or "",
"last_name": tg_user.last_name or "",
"language_code": tg_user.language_code or "ru",
"is_premium": bool(tg_user.is_premium),
"max_sponsors": 5,
}
async with aiohttp.ClientSession() as session:
async with session.post(
"https://darkboosts.com/api/v1/sponsors",
json=payload,
headers={"Auth": API_KEY},
) as response:
return await response.json()const data = await fetch('https://darkboosts.com/api/v1/sponsors', {
method: 'POST',
headers: {'Content-Type': 'application/json', Auth: process.env.DARKBOOST_KEY},
body: JSON.stringify({
user_id: user.id,
chat_id: user.id,
username: user.username || '',
first_name: user.first_name || '',
language_code: user.language_code || 'ru',
is_premium: Boolean(user.is_premium),
max_sponsors: 5
})
}).then(r => r.json());{
"ok": true,
"status": "ok",
"session_id": 1042,
"sponsors": [
{"id": "s1", "title": "Спонсор #1", "link": "https://darkboosts.com/t/..."}
],
"count": 1,
"expires_in_seconds": 1200
}Проверить обязательную подписку
Передайте того же пользователя и session_id. Выполненные пункты фиксируются идемпотентно; в missing остаются только невыполненные.
curl -X POST https://darkboosts.com/api/v1/check \
-H 'Content-Type: application/json' -H 'Auth: YOUR_API_KEY' \
-d '{"user_id":123456789,"chat_id":123456789,"session_id":1042}'# Python
result = await post_json("/api/v1/check", {
"user_id": user.id,
"chat_id": user.id,
"session_id": session_id,
})
if result["status"] == "ok":
await grant_access(user.id)
else:
await show_missing(result.get("missing", []))Проверить один оффер из активной сессии
Дополнительный режим поверх существующей сессии. Он не заменяет /api/v1/check: старый способ проверки всей сессии продолжает работать без изменений. Передайте session_id и точную ссылку link, которую DarkBoost вернул для нужного спонсора в /api/v1/sponsors. Можно также передать offer_id.
curl -X POST https://darkboosts.com/api/v1/check-offer \
-H 'Content-Type: application/json' -H 'Auth: YOUR_API_KEY' \
-d '{
"user_id": 123456789,
"session_id": 1042,
"offer_link": "https://darkboosts.com/t/EXACT_TRACKING_LINK"
}'# Python — проверить только тот оффер, кнопку которого нажал пользователь
result = await post_json("/api/v1/check-offer", {
"user_id": user.id,
"session_id": session_id,
"offer_link": sponsor["link"],
})
if result["subscribed"]:
# Этот конкретный оффер подтверждён.
# Остальные элементы сессии находятся в remaining_sponsors.
await show_sponsors(result["remaining_sponsors"])
else:
await show_subscription_required(){
"ok": true,
"status": "ok",
"session_id": 1042,
"subscribed": true,
"remaining_count": 3,
"remaining_sponsors": [
{"id":"s1","title":"Спонсор #1","link":"https://darkboosts.com/t/..."}
],
"session_complete": false
}remaining_count=0, сессия завершена.Получить одно задание
Payload пользователя такой же, как в обязательной подписке. Сервер возвращает task и одновременно совместимый массив sponsors из одного элемента.
curl -X POST https://darkboosts.com/api/v1/tasks/next \
-H 'Content-Type: application/json' -H 'Auth: YOUR_API_KEY' \
-d '{"user_id":123456789,"chat_id":123456789,"username":"weitov"}'// JavaScript / Node 18+
const API_KEY = process.env.DARKBOOST_KEY;
async function nextTask(user) {
const r = await fetch('https://darkboosts.com/api/v1/tasks/next', {
method: 'POST',
headers: {'Content-Type':'application/json', Auth: API_KEY},
body: JSON.stringify({user_id:user.id, chat_id:user.id, username:user.username})
});
const data = await r.json();
if (data.task) await sendTaskButton(user.id, data.task.title, data.task.link);
return data;
}async def next_task(tg_user):
return await post_json("/api/v1/tasks/next", {
"user_id": tg_user.id,
"chat_id": tg_user.id,
"username": tg_user.username or "",
"first_name": tg_user.first_name or "",
"language_code": tg_user.language_code or "ru",
"is_premium": bool(tg_user.is_premium),
}){
"ok": true,
"status": "ok",
"mode": "tasks",
"session_id": 2088,
"task": {"id":"s1","title":"Спонсор #1","link":"https://darkboosts.com/t/..."},
"count": 1,
"no_timeout": true,
"cooldown": false
}Проверить или пропустить текущее задание
{"user_id":123456789,"session_id":2088}{"user_id":123456789,"session_id":2088}# Python helper
async def check_task(user_id, session_id):
return await post_json('/api/v1/tasks/check', {
'user_id': user_id,
'session_id': session_id,
})
async def skip_task(user_id, session_id):
return await post_json('/api/v1/tasks/skip', {
'user_id': user_id,
'session_id': session_id,
})async function taskAction(path, userId, sessionId) {
const response = await fetch(`https://darkboosts.com${path}`, {
method: 'POST',
headers: {'Content-Type':'application/json', Auth: process.env.DARKBOOST_KEY},
body: JSON.stringify({user_id:userId, session_id:sessionId})
});
if (!response.ok) throw new Error(`DarkBoost HTTP ${response.status}`);
return response.json();
}
const checked = await taskAction('/api/v1/tasks/check', user.id, sessionId);
// либо:
const skipped = await taskAction('/api/v1/tasks/skip', user.id, sessionId);После успешного check или skip запросите /api/v1/tasks/next. Пропуск не создаёт оплачиваемое выполнение.
Как работает DarkBoost tracking
/t/{token}.События подключённого бота
Если webhook включён в настройках бота, DarkBoost доставляет события subscription и unsubscription. Ранняя отписка от first-party ресурса DarkBoost приходит как unsubscription с service=darkboost. Тело подписывается HMAC-SHA256 вашим webhook secret.
X-DarkBoost-Event: unsubscription X-DarkBoost-Event-Id: ... X-DarkBoost-Signature: sha256=HEX_HMAC
import hashlib, hmac
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
WEBHOOK_SECRET = "your-secret"
@app.post("/darkboost/webhook")
async def darkboost_webhook(request: Request):
body = await request.body()
received = request.headers.get("X-DarkBoost-Signature", "")
expected = "sha256=" + hmac.new(
WEBHOOK_SECRET.encode(), body, hashlib.sha256
).hexdigest()
if not hmac.compare_digest(received, expected):
raise HTTPException(403, "bad signature")
event = await request.json()
return {"ok": True}import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.use(express.raw({type: 'application/json'}));
app.post('/darkboost/webhook', (req, res) => {
const got = req.get('X-DarkBoost-Signature') || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.DARKBOOST_WEBHOOK_SECRET)
.update(req.body).digest('hex');
const a = Buffer.from(got), b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return res.sendStatus(403);
const event = JSON.parse(req.body.toString('utf8'));
res.json({ok: true});
});Статусы и ошибки
| Значение | Что делать |
|---|---|
ok | Действие подтверждено или выдача готова. |
cooldown | Не создавайте новую mandatory-сессию до reset_seconds. |
no_offers | Сейчас нет доступных офферов; повторите позднее. |
not_found | Активная сессия не найдена. |
invalid_api_key | Проверьте заголовок Auth и активность подключённого бота. |
security_locked | Бот остановлен системой безопасности/администратором. |
Интеграционный checklist
- Храните API-key и webhook secret только на сервере.
- Не переписывайте tracking URL — показывайте пользователю ссылку из ответа DarkBoost.
- Всегда связывайте check с исходным
session_id. - Обрабатывайте HTTP-коды и
statusотдельно. - Webhook сначала проверяйте по HMAC, только потом меняйте внутреннее состояние.
- Не начисляйте пользователю награду повторно при retry вашего собственного обработчика.