Все пути API этой версии — из /v1/openapi.json. У каждого:
право ключа, поля, пример ответа и пример запроса на curl и Python. Ключ в примерах берётся из переменной
окружения API_KEY.
Служебное
Проверка ключа и учёт вызовов. Эти пути не тратят кредиты.
GET/v1/me
Мой ключ
любой ключответ 200
Что может этот ключ: права, лимиты, расход за сегодня, тариф и остаток кредитов. Удобно проверять ключ: вызов не тратит ни лимит в минуту, ни кредиты.
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.get(f"{API}/v1/tg/media/Zm9vYmFyLmpwZw", headers=headers, timeout=60)
r.raise_for_status()
with open("media.jpg", "wb") as f:
f.write(r.content)
Telegram: подписки на события
Новые посты и сообщения из списка каналов — потоком, страницами или вебхуком.
GET/v1/tg/subscriptions
Список подписок
tg:streamответ 200
Подписки ключа, от новых к старым, страницами по курсору.
поле
где
тип
смысл
limit
запрос
integer
сколько записей вернуть · по умолчанию 50
cursor
запрос
string
курсор следующей страницы из next_cursor прошлого ответа
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.delete(
f"{API}/v1/tg/subscriptions/5b0c7e1a-3c2f-4e8a-9d61-0f2b7a4c9e13/chats/-1005678901234",
headers=headers,
timeout=60,
)
r.raise_for_status()
print(r.json())
Ответ 200
{
"removed": 1
}
GET/v1/tg/subscriptions/{sub_id}/stream
Поток событий (SSE)
tg:streamответ 200
События подписки потоком text/event-stream. При обрыве — переподключиться с Last-Event-ID: пропусков не будет (события хранятся 7 дней). Раз в 15 секунд приходит : ping.
Один поток на подписку: второй — 409 conflict, code=stream_busy.
поле
где
тип
смысл
sub_id*
путь
string
subscription_id подписки
after
запрос
integer
id последнего полученного события
Last-Event-ID
заголовок
string
id последнего полученного события — продолжить с него
import os
import json
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
headers["Accept"] = "text/event-stream"
with httpx.stream("GET", f"{API}/v1/tg/subscriptions/5b0c7e1a-3c2f-4e8a-9d61-0f2b7a4c9e13/stream", headers=headers, timeout=None) as r:
r.raise_for_status()
for line in r.iter_lines(): # при обрыве — снова с заголовком Last-Event-ID
if line.startswith("data:"):
event = json.loads(line[5:])
print(event["id"], event["kind"])
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.get(
f"{API}/v1/vk/page",
headers=headers,
params={"url": "https://vk.com/club1"},
timeout=60,
)
r.raise_for_status()
with open("page.html", "wb") as f:
f.write(r.content)
POST/v1/vk/{method}
Метод ВКонтакте
vk:readответ 200
Метод API ВКонтакте на чтение: тело — параметры метода. Ответ — как у ВКонтакте ({"response": …}), ошибка ВКонтакте — ошибкой API с полем vk_error и code=vk_<номер>.
Токен и версию API подставляем мы. Списки в параметрах уходят через запятую, true/false — 1/0.
поле
где
тип
смысл
method*
путь
string
метод API ВКонтакте: раздел.метод, например wall.get, groups.getById, newsfeed.search
Долгий сбор целиком: посты канала за период, поиск, карточки. Ответ приходит сразу, задача идёт в очереди; готовый результат — файлом. Список видов сбора — в «Основах».
Нужно ещё право источника: tg:read для Telegram, vk:read для ВКонтакте. В ref — до 20 каналов через пробел или запятую.
Ещё виды: tg.history ({chat, since?, until?, media?, limit?}) и tg.participants ({chat, limit?}, нужно tg:people).
поле
где
тип
смысл
kind*
тело
string
parser.preset — сбор по готовому шаблону · до 40 симв.
{
"unit": "tg_post",
"unit_title": "пост канала",
"credits_per_unit": 0.5,
"records": {
"min": 0,
"max": 300
},
"credits": {
"min": 0,
"max": 150
},
"balance": 28749.5,
"enough": true,
"note": "пустой результат и наши ошибки не списываются"
}
GET/v1/jobs/{job_id}
Карточка задачи
jobsответ 200
Статус и ход задачи: queued → running → done (или failed, cancelled). В result_summary.credits — сколько кредитов списано (числом, может быть дробным: 1.5).
import os
import uuid
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
headers["Idempotency-Key"] = str(uuid.uuid4()) # тот же ключ при повторе того же запроса
r = httpx.post(
f"{API}/v1/tg/send",
headers=headers,
json={"chat": "@SpamBot", "text": "/start"},
timeout=60,
)
r.raise_for_status()
print(r.json())
Ответ 200
{
"ok": true,
"msg_id": 17
}
Telegram: вступления и членство
Вступление в чаты через очередь и сведения о членстве.
POST/v1/tg/join
Вступить в чат
tg:joinнужен Idempotency-Keyответ 200
Заявка на вступление в очередь; wait — подождать итога до N секунд.
import os
import uuid
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
headers["Idempotency-Key"] = str(uuid.uuid4()) # тот же ключ при повторе того же запроса
r = httpx.post(
f"{API}/v1/tg/join",
headers=headers,
json={"ref": "https://t.me/+AbCdEf", "wait": 10},
timeout=60,
)
r.raise_for_status()
print(r.json())
import os
import uuid
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
headers["Idempotency-Key"] = str(uuid.uuid4()) # тот же ключ при повторе того же запроса
r = httpx.post(f"{API}/v1/tg/leave", headers=headers, json={"chat": -1001234567890}, timeout=60)
r.raise_for_status()
print(r.json())
Ответ 200
{
"left": true,
"accounts": [
"acc_017"
]
}
GET/v1/tg/membership
Членство в чате
tg:readответ 200
Есть ли доступ к чату и как он слушается.
поле
где
тип
смысл
ref*
запрос
string
канал, чат или сообщество: @name, ссылка t.me/… или peer_id
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.get(f"{API}/v1/proxy/pool", headers=headers, params={"target": "sudrf"}, timeout=60)
r.raise_for_status()
print(r.json())
Ответ 200
{
"alive": 40,
"cooldown": 3,
"total": 44
}
Вебхуки событий
Адреса, на которые приходят события организации: задачи, расход кредитов, счета, совпадения мониторингов, сроки ключей. Эти пути не тратят кредиты.
GET/v1/webhooks
Адреса вебхуков
webhooksответ 200
Все живые адреса организации, от новых к старым. Секрета в ответе нет никогда.
status: active — работает, failing — последние попытки неудачны, disabled — выключен (disabled_reason: failures — после неудач подряд, user — вручную).
Новый адрес для событий организации. Секрет whs_… для проверки подписи приходит в ответе один раз — сохраните его сразу. Idempotency-Key здесь не действует: повтор создаёт второй адрес.
Ошибки: 400 с codebad_args, unknown_event или webhook_url_forbidden; 409 с code=webhook_limit, если живых адресов у организации уже 10.
поле
где
тип
смысл
url*
тело
string
https-адрес вашего сервера, куда присылать события · до 2000 симв.
events*
тело
array of string
события: task.done, task.partial, task.failed, quota.threshold, invoice.issued, monitor.hit, key.expiring или ["*"] — все, включая будущие · до 50 элементов
Любые из полей url, events, description, enabled; rotate_secret: true — новый секрет (в ответе один раз, сутки события подписываются обоими секретами).
поле
где
тип
смысл
webhook_id*
путь
string
id адреса вебхука
url
тело
string
https-адрес вашего сервера, куда присылать события · до 2000 симв.
events
тело
array of string
события: task.done, task.partial, task.failed, quota.threshold, invoice.issued, monitor.hit, key.expiring или ["*"] — все, включая будущие · до 50 элементов
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.delete(
f"{API}/v1/webhooks/8d2e4f1a-6b3c-4a7e-9f10-2c5d8e7b1a93",
headers=headers,
timeout=60,
)
r.raise_for_status()
print(r.json())
Ответ 200
{
"ok": true
}
POST/v1/webhooks/{webhook_id}/test
Тестовое событие
webhooksответ 200
Отправляет webhook.test сразу — и на выключенный адрес, чтобы проверить его перед включением. В ответе — доставка с итогом попытки. Неудача теста адрес не выключает.
поле
где
тип
смысл
webhook_id*
путь
string
id адреса вебхука
curl
curl -s -X POST "https://soroka.tools/v1/webhooks/8d2e4f1a-6b3c-4a7e-9f10-2c5d8e7b1a93/test" \
-H "Authorization: Bearer $API_KEY"
Python
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.post(
f"{API}/v1/webhooks/8d2e4f1a-6b3c-4a7e-9f10-2c5d8e7b1a93/test",
headers=headers,
timeout=60,
)
r.raise_for_status()
print(r.json())
Ещё одна попытка сейчас: тот же X-Webhook-Id и тело, новые отметка времени и подпись. Уже доставленное событие отправится ещё раз — отсеивайте повторы по id. Выключенный адрес — 409, code=webhook_disabled.
поле
где
тип
смысл
webhook_id*
путь
string
id адреса вебхука
delivery_id*
путь
string
id доставки из журнала
curl
curl -s -X POST "https://soroka.tools/v1/webhooks/8d2e4f1a-6b3c-4a7e-9f10-2c5d8e7b1a93/deliveries/48213/retry" \
-H "Authorization: Bearer $API_KEY"
Python
import os
import httpx
API = "https://soroka.tools"
headers = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = httpx.post(
f"{API}/v1/webhooks/8d2e4f1a-6b3c-4a7e-9f10-2c5d8e7b1a93/deliveries/48213/retry",
headers=headers,
timeout=60,
)
r.raise_for_status()
print(r.json())