Документация
API для ботов
Показывайте задания рекламодателей своим пользователям и ставьте обязательную подписку — 60% цены каждого выполнения ваши. Проверку выполнения в Telegram биржа делает сама: вам — два запроса.
Быстрый старт
- Войдите в кабинет через Telegram → «Боты и API» → «Подключить бота». Сохраните ключ — он показывается один раз.
- Все запросы — на
https://lifeseo.ru/api/v1/…с заголовкомAuthorization: Bearer lseo_…, тело — JSON. - Покажите человеку задания (
POST /tasks); когда он нажмёт «Проверить» — вызовитеPOST /tasks/check. - Засчитанное выполнение — в холде 72 часа, потом деньги переходят на счёт к выводу. События приходят вебхуком.
Основное
- Суммы — целые копейки:
"reward": 30— это 0,30 ₽. - Ответ —
{"ok": true, …}или{"ok": false, "error": "код", "message": "текст"}. - Лимит — 30 запросов в секунду на ключ; сверх — ответ 429 с заголовком
Retry-After. user_id— Telegram ID человека в вашем боте.- Один человек выполняет задание один раз во всей сети: если он уже сделал его в другом боте, у вас его не будет.
- Засчитать выполнение может только бот, который показал задание этому человеку: сначала
/tasks, потом/tasks/check. Без своего показа ответ —unavailable.
POST /tasks — задания для человека
Поля запроса: user_id — обязательно, limit — сколько заданий вернуть (1–20, по умолчанию 5). Дорогие задания — первыми.
POST https://lifeseo.ru/api/v1/tasks
Authorization: Bearer lseo_…
Content-Type: application/json
{"user_id": 123456789, "limit": 5}{
"ok": true,
"tasks": [
{
"task_id": "6718a2c4e1f0a93b2c5d7e10",
"type": "channel",
"title": "Подпишитесь на канал о крипте",
"description": "Новости и разборы каждый день",
"link": "https://t.me/example_channel",
"reward": 30,
"check": "auto"
},
{
"task_id": "6718a2c4e1f0a93b2c5d7e11",
"type": "link",
"title": "Откройте сайт партнёра",
"description": "",
"link": "https://lifeseo.ru/go/6718a2c4…",
"reward": 12,
"check": "auto"
}
]
}| Поле | Что это |
|---|---|
task_id | Id задания — для /tasks/check |
type | channel — подписка на канал, group — вступление в группу, bot — запуск бота, link — переход по ссылке, report — задание с отчётом |
title, description | Текст для человека (без разметки и угловых скобок) |
link | Куда вести человека. Для link — ссылка на бота биржи: он выдаст человеку личную ссылку перехода — так переход засчитывается только тому, кто реально перешёл |
reward | Ваша доля за выполнение, копейки |
check | auto — проверяем сами по /tasks/check; report — нужен отчёт со скриншотом (ниже) |
instructions, criteria | Только у report: что сделать и что должно быть на скриншоте |
Каналы, где человек уже был до показа задания, и боты, которые он уже запускал, не возвращаются: за старых подписчиков рекламодатель не платит.
POST /tasks/check — проверить выполнение
POST https://lifeseo.ru/api/v1/tasks/check
{"user_id": 123456789, "task_id": "6718a2c4e1f0a93b2c5d7e10"}{ "ok": true, "status": "completed", "reward": 30, "hold_until": "2026-10-24T12:00:00.000Z" }
{ "ok": true, "status": "incomplete" }
{ "ok": true, "status": "unavailable" }| status | Что делать |
|---|---|
completed | Засчитано. reward — ваша доля, hold_until — когда она станет доступна к выводу. Повторный запрос снова вернёт completed |
incomplete | Ещё не выполнено: не подписался, не запустил бота, не перешёл по ссылке. Для ссылки переход засчитывается через 5 секунд после открытия личной ссылки из бота биржи |
unavailable | Задание закончилось, остановлено или выполнено через другой бот — уберите его из списка |
waiting | Только у report: отчёт на проверке. Для отказа приходят reason и attempts_left |
Задания с отчётом
Задание вне Telegram (отзыв, регистрация, действие на сайте): человек делает его и присылает скриншот и текст — вы передаёте их нам. Отчёт проверяет ИИ по критериям рекламодателя. Если ИИ не уверен — решает рекламодатель (72 часа, потом отчёт засчитывается); обжалованный отказ ИИ решает рекламодатель или админ, без автоприёма. Итог — вебхуком report.reviewed и через /tasks/check.
POST https://lifeseo.ru/api/v1/tasks/report
{
"user_id": 123456789,
"task_id": "6718a2c4e1f0a93b2c5d7e30",
"text": "Оставил отзыв, ник Иван П.",
"image": "data:image/jpeg;base64,/9j/4AAQSkZJRg…"
}
{ "ok": true, "status": "review", "report_id": "6718c0aa…", "attempts_left": 2 }image— скриншот в base64 (можноdata:image/…;base64,): JPEG, PNG или WebP, до 4 МБ. Тело запроса — до 6 МБ.- До 3 отчётов на задание; пока один на проверке, второй не принимается (409).
- Не согласен с отказом ИИ —
POST /tasks/report/appeal {"user_id", "task_id"}: решит человек. Один раз на отчёт. - Скриншоты видят только рекламодатель и админ, хранятся 30 дней.
POST /op/check — обязательная подписка
Вызывайте перед тем, как пустить человека дальше. passed: false — покажите каналы кнопками и кнопку «Я подписался», которая снова вызывает /op/check. Каждая подписка — оплаченное выполнение. После прохождения человек час не видит новых каналов, а запрос отвечает сразу — его можно звать хоть на каждое сообщение.
POST https://lifeseo.ru/api/v1/op/check
{"user_id": 123456789}{
"ok": true,
"passed": false,
"channels": [
{
"task_id": "6718a2c4e1f0a93b2c5d7e20",
"title": "Подпишитесь, чтобы продолжить",
"channel": "Крипто-новости",
"link": "https://t.me/example_news",
"reward": 24
}
]
}Если Telegram не ответил, канал в этот раз не показывается: ОП никогда не запирает человека в вашем боте из-за сбоя.
GET /me и GET /stats
{
"ok": true,
"bot": { "id": "6718…", "title": "Мой бот", "username": "my_bot" },
"share_percent": 60,
"hold_hours": 72,
"balances": { "hold": 1800, "earn": 12400 }
}GET https://lifeseo.ru/api/v1/stats?days=7
{
"ok": true,
"days": [
{ "date": "2026-10-21", "completed": 140, "confirmed": 0, "penalized": 3, "earned": 4110 }
]
}Вебхуки
Адрес задаётся в кабинете (только https). Ответьте 2xx за 10 секунд — иначе повторим через 1 мин, 5 мин, 30 мин, 2 ч, 6 ч и 24 ч. Один и тот же id может прийти дважды — обрабатывайте идемпотентно.
POST https://ваш-адрес/lifeseo-hook
X-LifeSEO-Event: task.completed
X-LifeSEO-Delivery: 6718b0d2e1f0a93b2c5d7f01
X-LifeSEO-Signature: sha256=5f1c…
{
"event": "task.completed",
"id": "6718b0d2e1f0a93b2c5d7f01",
"created_at": "2026-10-21T12:00:00.000Z",
"data": {
"user_id": 123456789,
"task_id": "6718a2c4e1f0a93b2c5d7e10",
"source": "task",
"reward": 30,
"hold_until": "2026-10-24T12:00:00.000Z"
}
}| Событие | Когда |
|---|---|
task.completed | Выполнение засчитано (через /tasks/check или ОП); деньги — в холде |
task.confirmed | Холд прошёл — доля перешла на счёт к выводу |
task.penalty | Человек отписался в холде — доля списана; можно забрать награду у пользователя |
report.reviewed | Отчёт проверен: verdict — approved (с reward) или rejected (с reason) |
Подпись — X-LifeSEO-Signature: sha256=<hex>, HMAC-SHA256 тела запроса как оно пришло; ключ — «секрет подписи» бота из кабинета.
const crypto = require('node:crypto');
// raw — тело запроса как пришло (Buffer), до JSON.parse
function verifyLifeseo(raw, signatureHeader, secret) {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(raw).digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(String(signatureHeader || ''));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}import hashlib, hmac
def verify_lifeseo(raw: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header or "")<?php
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_LIFESEO_SIGNATURE'] ?? '')) {
http_response_code(401);
exit;
}
$event = json_decode($raw, true);Холд и штрафы
Бот биржи — админ каналов рекламодателей, поэтому подписку видно сразу. Выход из канала в течение 72 часов отменяет выполнение: ваша доля списывается из холда, рекламодателю возвращаются деньги, вам приходит task.penalty. Ещё мы перепроверяем подписку через сутки и в конце холда. Если рекламодатель убрал бота биржи из админов, перепроверить нельзя — такие выполнения засчитываются без штрафа.
Примеры кода
// npm i telegraf
const { Telegraf, Markup } = require('telegraf');
const bot = new Telegraf(process.env.BOT_TOKEN);
const KEY = process.env.LIFESEO_KEY; // ключ из кабинета LifeSEO
async function lifeseo(path, body) {
const res = await fetch(`https://lifeseo.ru/api/v1${path}`, {
method: 'POST',
headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
return res.json();
}
bot.command('tasks', async (ctx) => {
const { tasks = [] } = await lifeseo('/tasks', { user_id: ctx.from.id, limit: 5 });
if (!tasks.length) return ctx.reply('Заданий пока нет — загляните позже.');
for (const t of tasks) {
await ctx.reply(`${t.title}\nНаграда: ${(t.reward / 100).toFixed(2)} ₽`, Markup.inlineKeyboard([
[Markup.button.url('Выполнить', t.link)],
[Markup.button.callback('Проверить', `check:${t.task_id}`)],
]));
}
});
bot.action(/^check:(\w{24})$/, async (ctx) => {
const r = await lifeseo('/tasks/check', { user_id: ctx.from.id, task_id: ctx.match[1] });
if (r.status === 'completed') return ctx.answerCbQuery('Засчитано!', { show_alert: true });
if (r.status === 'incomplete') return ctx.answerCbQuery('Ещё не выполнено', { show_alert: true });
return ctx.answerCbQuery('Задание уже недоступно', { show_alert: true });
});
// Обязательная подписка перед любым действием
bot.use(async (ctx, next) => {
if (!ctx.from || ctx.callbackQuery?.data === 'op') return next();
const op = await lifeseo('/op/check', { user_id: ctx.from.id });
if (!op.ok || op.passed) return next();
const rows = op.channels.map((c) => [Markup.button.url(c.channel || c.title, c.link)]);
rows.push([Markup.button.callback('Я подписался', 'op')]);
return ctx.reply('Чтобы продолжить, подпишитесь:', Markup.inlineKeyboard(rows));
});
bot.action('op', async (ctx) => {
const op = await lifeseo('/op/check', { user_id: ctx.from.id });
await ctx.answerCbQuery(op.passed ? 'Готово, спасибо!' : 'Подписка ещё не найдена', { show_alert: !op.passed });
});
bot.launch();# pip install aiogram aiohttp
import os, aiohttp
from aiogram import Bot, Dispatcher, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
KEY = os.environ["LIFESEO_KEY"]
bot = Bot(os.environ["BOT_TOKEN"])
dp = Dispatcher()
async def lifeseo(path: str, body: dict) -> dict:
async with aiohttp.ClientSession() as s:
async with s.post(f"https://lifeseo.ru/api/v1{path}", json=body,
headers={"Authorization": f"Bearer {KEY}"}) as r:
return await r.json()
@dp.message(Command("tasks"))
async def tasks(m: Message):
data = await lifeseo("/tasks", {"user_id": m.from_user.id, "limit": 5})
for t in data.get("tasks", []):
kb = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text="Выполнить", url=t["link"])],
[InlineKeyboardButton(text="Проверить", callback_data=f"check:{t['task_id']}")],
])
await m.answer(f"{t['title']}\nНаграда: {t['reward'] / 100:.2f} ₽", reply_markup=kb)
@dp.callback_query(F.data.startswith("check:"))
async def check(c: CallbackQuery):
r = await lifeseo("/tasks/check", {"user_id": c.from_user.id, "task_id": c.data.split(":", 1)[1]})
text = {"completed": "Засчитано!", "incomplete": "Ещё не выполнено"}.get(r.get("status"), "Задание недоступно")
await c.answer(text, show_alert=True)
dp.run_polling(bot)<?php
function lifeseo(string $path, array $body): array {
$ch = curl_init('https://lifeseo.ru/api/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('LIFESEO_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
return $result ?: ['ok' => false];
}
$tasks = lifeseo('/tasks', ['user_id' => $userId, 'limit' => 5]);
$check = lifeseo('/tasks/check', ['user_id' => $userId, 'task_id' => $taskId]);Ошибки
| HTTP | error | Что значит |
|---|---|---|
| 400 | bad_input, bad_json | Неверные поля — текст в message |
| 401 | unauthorized | Нет ключа, ключ перевыпущен или бот заблокирован |
| 404, 405 | not_found, method | Нет такого метода или не тот HTTP-метод |
| 409 | unavailable, already_open, no_attempts, bad_state | Отчёт сейчас не принять: задание недоступно, предыдущий на проверке, попытки кончились, обжаловать нельзя |
| 413 | too_large | Тело больше 16 КБ (у отчёта — 6 МБ) |
| 429 | rate_limited | Слишком часто — подождите Retry-After секунд |
| 500, 503 | internal, telegram_unavailable | Сбой у нас или в Telegram — повторите позже |