Yoto Files API v1

Публичный API для интеграции заданий Yoto Files в ваше приложение, бота или сайт: получайте список заданий для пользователя и проверяйте их выполнение.

Скачать документацию (.md) — удобно сохранить или отправить разработчику

Содержание Авторизация Капча GET /api/v1/get_tasks — получение заданий POST /api/v1/check_task — проверка выполнения GET /api/v1/ping GET /api/v1/me Ошибки и лимиты Рекомендуемый сценарий интеграции

Алиасы адресов: GET /api/v1/tasks и POST /api/v1/tasks/check делают то же, что /api/v1/get_tasks и /api/v1/check_task.

Авторизация

Все запросы (кроме /api/v1/ping) требуют личный API-ключ. Ключ создаётся в боте Yoto Files: главное меню → кнопка API → «Создать ключ».

Можно создать до 5 ключей — каждому задаётся необязательное название, у каждого своя статистика (запросы, выданные и выполненные задания, заработок), доступная в мини-аппе прямо в боте. Ключ всегда можно посмотреть в боте (он показан скрытым — нажмите, чтобы раскрыть) и настроить для него ссылку возврата после капчи (см. ниже).

Передавайте ключ в заголовке X-Api-Key (поддерживается и Authorization: Bearer):

curl -H "X-Api-Key: yf_ВАШ_КЛЮЧ" "https://yotofiles.com/api/v1/get_tasks?user_id=123456789"
Команду копируйте одной строкой. Если разбивать её знаком \, следите, чтобы после \ не было пробела — иначе curl вернёт curl: (3) URL rejected: Malformed input to a URL function.
Храните ключ в секрете. Посмотреть его можно в любой момент в боте: меню → API → ключ (показан скрытым — нажмите, чтобы раскрыть). Если ключ скомпрометирован — удалите его там же: он перестанет работать сразу.

Капча

Задания выдаются только пользователям, прошедшим проверку «я не робот» в Yoto Files. Это то же самое окно, что видят пользователи бота: мини-апп с галочкой, где Telegram спрашивает разрешение отправлять сообщения. Именно это разрешение и нужно провайдерам заданий, чтобы человека стало видно.

/get_tasks и /check_task вернут status: "captcha_required", когда:

Покажите пользователю окно капчи — текст message, кнопку «Пройти проверку» со ссылкой captcha.link и кнопку «Готово», по которой вы повторяете запрос заданий. Ссылка открывает мини-апп внутри Telegram: из бота выходить не нужно, и нажимать «Start» тоже.

Возврат в ваше приложение. В настройках ключа (бот → API → ключ → ⚙️ Настройки) можно указать ссылку возврата. Тогда после проверки мини-апп покажет кнопку «Вернуться в приложение» на этот адрес. Id ключа автоматически вшивается в captcha.link (startapp=api<id>) — отдельно ничего передавать не нужно.
{
  "ok": true,
  "status": "captcha_required",
  "message": "Требуется проверка «я не робот».",
  "user_id": 123456789,
  "captcha": {
    "link": "https://t.me/YotoFilesBot/captcha?startapp=api12",
    "status": "not_passed"
  },
  "tasks": []
}
ПолеОписание
messageГотовый текст для показа пользователю.
captcha.linkСсылка на проверку — мини-апп «я не робот» в Telegram.
captcha.statusnot_passed — проверка ещё не пройдена. После прохождения повторный запрос вернёт status: "ok" и задания.

GET/api/v1/ping

Проверка доступности API. Авторизация не требуется.

{ "ok": true, "service": "yoto-files-api", "version": "v1" }

GET/api/v1/me

Сам ключ и его счётчики — те же, что видно в боте.

{
  "ok": true,
  "key_id": 12,
  "owner_id": 987654321,
  "name": "Мой бот",
  "key_prefix": "yf_AbCdEfGh…",
  "created_at": "2026-07-16T10:00:00+00:00",
  "requests_total": 1024,
  "tasks_issued": 380,
  "tasks_completed": 205,
  "earned_total": "12.40"
}

GET/api/v1/get_tasks

Получение списка заданий для пользователя — тот же набор, что бот показывает при получении материалов. Задания бывают двух типов: внешние (external) — задания платформы; и личные (personal) — ваши личные каналы-задания (те же, что в боте: Медиахаб → Личные задания). Поле provider у внешних заданий уточняет источник: op — ваши собственные задания; YotoFiles — задания платформы Yoto Files.

Задания платформы (provider: "YotoFiles") показываются, только если у вас включена монетизация и настройка «Использовать внешние задания». Когда пользователь выполняет такое задание и вы подтверждаете его через /check_task, вознаграждение начисляется вам — так же, как в боте.

Параметры query

ПараметрТипОписание
user_idint, обязателенTelegram ID пользователя, которому показываются задания.
limitint, 1–10Максимум внешних заданий в блоке (личные каналы включаются всегда). По умолчанию 5.

Что подставить

Key    : yf_ВАШ_КЛЮЧ    → заголовок X-Api-Key (обязательно)
UserID : 123456789      → параметр user_id  (обязательно)
limit  : 5              → параметр limit    (необязательно, 1–10)

Пример запроса

# curl (одной строкой)
curl -H "X-Api-Key: yf_ВАШ_КЛЮЧ" "https://yotofiles.com/api/v1/get_tasks?user_id=123456789&limit=5"
# HTTP
GET /api/v1/get_tasks?user_id=123456789&limit=5 HTTP/1.1
Host: yotofiles.com
X-Api-Key: yf_ВАШ_КЛЮЧ
# Python (requests)
import requests

resp = requests.get(
    "https://yotofiles.com/api/v1/get_tasks",
    headers={"X-Api-Key": "yf_ВАШ_КЛЮЧ"},
    params={"user_id": 123456789, "limit": 5},
)
print(resp.json())

Ответ

{
  "ok": true,
  "status": "ok",
  "user_id": 123456789,
  "tasks": [
    {
      "id": "ext_42",
      "number": 1,
      "type": "external",
      "provider": "op",
      "title": "Подписаться на канал",
      "link": "https://t.me/example_channel",
      "date": "2026-07-01T12:00:00+00:00",
      "status": "not_completed",
      "action": "subscribe"
    },
    {
      "id": "fl_AbC123",
      "number": 2,
      "type": "external",
      "provider": "YotoFiles",
      "title": "Подписаться на канал",
      "link": "https://t.me/+AbCdEfGhIjK",
      "date": null,
      "status": "not_completed",
      "action": "subscribe"
    },
    {
      "id": "pers_7",
      "number": 3,
      "type": "personal",
      "provider": null,
      "title": "Мой канал",
      "link": "https://t.me/my_channel",
      "date": "2026-06-20T18:05:00+00:00",
      "status": "completed",
      "action": "subscribe"
    }
  ],
  "count": 3,
  "all_completed": false
}
Поле заданияОписание
idID задания для /api/v1/check_task. Разные префиксы соответствуют разным внутренним источникам задания. Передавайте id как есть, без разбора префикса.
numberНомер задания в блоке (с 1) — для показа пользователю («Задание 1», «Задание 2»…).
typeТип задания: personal — личное (ваш канал), external — внешнее (задание платформы).
providerИсточник внешнего задания: op — ваши собственные задания; YotoFiles — задания платформы (для личных каналов — null).
titleНазвание задания для показа пользователю.
linkСсылка, которую нужно открыть пользователю.
dateДата создания задания (ISO 8601).
statuscompleted — выполнено, not_completed — не выполнено. Зачёт выполнения происходит в /api/v1/check_task.
actionЧто должен сделать пользователь: subscribe — подписаться; join_request — подать заявку на вступление по ссылке.
Для заданий с action: "join_request" пользователь должен перейти именно по ссылке из ответа — заявка, поданная по другой ссылке, не засчитывается. Внешние задания, уже засчитанные пользователю, в блок повторно не попадают.

POST/api/v1/check_task

Проверка выполнения заданий пользователем. Выполненные внешние задания фиксируются и повторно в /get_tasks не возвращаются. Можно проверить одно задание (task_id) или несколько сразу (task_ids).

Что подставить

Key     : yf_ВАШ_КЛЮЧ         → заголовок X-Api-Key (обязательно)
UserID  : 123456789           → поле user_id       (обязательно)
task_id : ext_42              → одно задание, ИЛИ
task_ids: ["ext_42","pers_7"] → несколько заданий

Тело запроса (application/json)

// несколько заданий
{
  "user_id": 123456789,
  "task_ids": ["ext_42", "ext_57", "pers_7"]
}

// одно задание
{
  "user_id": 123456789,
  "task_id": "ext_42"
}

Пример запроса (curl, одной строкой)

curl -X POST "https://yotofiles.com/api/v1/check_task" -H "X-Api-Key: yf_ВАШ_КЛЮЧ" -H "Content-Type: application/json" -d "{\"user_id\": 123456789, \"task_id\": \"ext_42\"}"

Ответ

{
  "ok": true,
  "status": "ok",
  "user_id": 123456789,
  "results": [
    { "id": "ext_42",  "completed": true,  "state": "completed" },
    { "id": "ext_57",  "completed": false, "state": "not_completed" },
    { "id": "pers_7",  "completed": true,  "state": "completed" }
  ],
  "all_completed": false
}
stateЗначение
completedЗадание выполнено и засчитано.
not_completedЗадание не выполнено (нет подписки/заявки).
unknownНе удалось проверить (временная ошибка Telegram) — повторите позже.
not_foundЗадание с таким id не существует или уже недоступно.
Не более 20 заданий за один запрос. state: "unknown" — это не отказ: повторите проверку через несколько секунд.

Ошибки и лимиты

Все ошибки возвращаются в едином формате:

{
  "ok": false,
  "error": { "code": "unauthorized", "message": "Неверный или отозванный API-ключ." }
}
HTTPcodeОписание
400bad_requestНекорректные параметры или JSON.
401unauthorizedКлюч не передан, неверен или отозван.
429rate_limitedПревышен лимит запросов. Повторите через error.retry_after секунд (см. также заголовок Retry-After).
500internal_errorВнутренняя ошибка сервиса.
503unavailableСервис временно недоступен — повторите запрос.
503provider_unavailableПровайдер заданий не отвечает — повторите запрос позже.

Базовый лимит — 300 запросов в секунду на ключ (кратковременные всплески до 600 допускаются). Лимит считается по каждому ключу отдельно. Если вам нужен ещё больший лимит — напишите в поддержку.

Рекомендуемый сценарий интеграции

  1. Пользователь запрашивает контент в вашем приложении.
  2. Вы вызываете GET /api/v1/get_tasks?user_id=….
  3. Если status = "captcha_required" — покажите кнопку «Пройти проверку» (captcha.link) и кнопку «Готово», по которой повторяете шаг 2. Этот же ответ может прийти и позже, у пользователя с историей: значит, проверку надо пройти заново.
  4. Покажите пользователю задания: кнопка с title и ссылкой link + кнопка «Проверить».
  5. По кнопке «Проверить» вызовите POST /api/v1/check_task со списком показанных task_ids.
  6. Когда all_completed = true — выдайте пользователю контент.
# Пример на Python (aiohttp)
import aiohttp

API = "https://yotofiles.com/api/v1"
HEADERS = {"X-Api-Key": "yf_ВАШ_КЛЮЧ"}

async def get_tasks(session: aiohttp.ClientSession, user_id: int) -> dict:
    async with session.get(f"{API}/get_tasks", params={"user_id": user_id},
                           headers=HEADERS) as resp:
        return await resp.json()

async def check_tasks(session: aiohttp.ClientSession, user_id: int,
                      task_ids: list[str]) -> dict:  # ["ext_42", "pers_7"]
    async with session.post(f"{API}/check_task", headers=HEADERS,
                            json={"user_id": user_id, "task_ids": task_ids}) as resp:
        return await resp.json()