Довідник API поки що доступний лише російською. Назви методів, шляхи й приклади однакові для всіх мов.
Client API
Содержание
Обзор#
- Адрес:
https://unixgram.com/api. Все запросы и ответы — JSON в UTF-8, кроме загрузки файлов. - Авторизация — cookie сессии, как у браузера. Любая HTTP-библиотека с хранилищем cookie (requests.Session, curl
-c/-b, OkHttp CookieJar) работает без доработок. - Каждый запрос, который что-то меняет (POST, PUT, PATCH, DELETE), несёт заголовок
x-csrf-token— как его получить. - Полный список — 349 методов с параметрами — в справочнике методов. События в реальном времени — в Realtime.
- Программа должна работать на сервере, компьютере или телефоне. Страница в браузере на другом сайте обратиться к API не сможет: cookie сессии выдаются с
SameSite=Lax, а CORS-заголовков API не отдаёт. Для сайта используйте свой сервер как посредника — или бота и мини-приложение.
Быстрый старт#
Python и requests: войти, прочитать ленту и написать человеку.
import uuid, requests
API = "https://unixgram.com/api"
s = requests.Session()
s.headers["User-Agent"] = "my-client/1.0"
def csrf():
return s.get(f"{API}/auth/csrf").json()["data"]["csrfToken"]
def call(method, path, **json):
headers = {} if method == "GET" else {"x-csrf-token": s.cookies.get("csrf_token") or csrf()}
r = s.request(method, API + path, json=json or None, headers=headers)
body = r.json()
if not body["success"]:
raise RuntimeError(body["error"])
return body["data"]
csrf()
me = call("POST", "/auth/login", email="me@example.com", password="••••••••")["account"]
print("Вошли как", me["username"])
for post in call("GET", "/social/feed?limit=10")["feed"]:
print(post["author"]["username"], post["content"][:60])
chat = call("POST", "/social/users/unixgram/message") # личный чат по нику
call("POST", f"/social/messages/{chat['conversationId']}",
content="Привет из API!", clientMessageId=str(uuid.uuid4()))То же на curl:
# 1. CSRF-токен и cookie
TOKEN=$(curl -s -c jar -b jar https://unixgram.com/api/auth/csrf | jq -r .data.csrfToken)
# 2. Вход
curl -s -c jar -b jar -H "x-csrf-token: $TOKEN" -H "content-type: application/json" \
-d '{"email":"me@example.com","password":"••••••••"}' https://unixgram.com/api/auth/login
# 3. Список чатов
curl -s -b jar https://unixgram.com/api/social/messagesВход и сессия#
Вход#
POST /api/auth/login с телом {"email", "password", "twoFactorCode"?}. Ответ — {account} и две cookie сессии. Если у аккаунта включена двухфакторная защита, первый вызов вернёт ошибку TWO_FACTOR_REQUIRED (или …_EMAIL_REQUIRED, …_TELEGRAM_REQUIRED — код отправлен туда) — повторите вход с twoFactorCode из шести цифр.
Аккаунт для программы создаётся обычной регистрацией в приложении: регистрация защищена капчей, которую сторонний клиент пройти не может. Вход капчу не спрашивает.
Сессия#
| Поле | Тип | Описание |
|---|---|---|
auth_access_token | cookie, httpOnly | Доступ на 15 минут |
auth_refresh_token | cookie, httpOnly | Продление на 30 дней |
csrf_token | cookie | Двойник заголовка x-csrf-token |
Продлевать сессию вручную не нужно: если access-токен истёк, а refresh жив, сервер выдаст новые cookie в ответ на любой запрос. Ошибка UNAUTHORIZED значит, что истёк и refresh, — войдите заново. Текущий аккаунт — GET /api/auth/me, выход — POST /api/auth/logout, список устройств — GET /api/auth/sessions.
Вход по QR#
Чтобы не хранить пароль в программе, войдите так же, как веб-версия входит по QR-коду с телефона:
POST /api/auth/qr/start→{"token", "expiresAt", "pollIntervalMs"}. Покажите QR-код со ссылкойhttps://unixgram.com/auth/link?t=<token>.- Человек сканирует его приложением Unixgram, в котором уже вошёл, и подтверждает вход.
- Программа опрашивает
GET /api/auth/qr/status?token=…(раз вpollIntervalMs); приAPPROVED— вызываетPOST /api/auth/qr/claimс{"token"}и получает cookie сессии.
CSRF#
GET /api/auth/csrf возвращает {"csrfToken": "…", "captchaRequired": false} и ставит cookie csrf_token с тем же значением. Передавайте его в заголовке x-csrf-token в каждом изменяющем запросе. Токен не одноразовый — берите его из cookie, пока она есть.
POST /api/social/posts HTTP/1.1
Host: unixgram.com
Cookie: auth_access_token=…; auth_refresh_token=…; csrf_token=Rk9…f0.9c1…
x-csrf-token: Rk9…f0.9c1…
content-type: application/json
{"content": "Первый пост из API"}Ответы и ошибки#
Любой ответ — один конверт. Разбирайте по полю success, а не по коду состояния:
{"success": true, "data": {"post": {"id": "cmh1x…", "content": "…"}}}
{"success": false, "error": {"code": "VALIDATION_ERROR", "message": "Validation failed",
"details": {"fieldErrors": {"content": ["Too big: expected string to have <=2000 characters"]}}}}| error.code | HTTP | Что значит |
|---|---|---|
VALIDATION_ERROR | 400 · 422 | Неверные параметры. В details — какое поле и почему (422 — ошибка схемы) |
UNAUTHORIZED | 401 | Сессии нет или refresh-токен истёк — войдите заново |
CSRF_TOKEN_INVALID | 403 | Нет заголовка x-csrf-token или он не совпадает с cookie |
FORBIDDEN · PERMISSION_DENIED | 403 | Действие запрещено этому аккаунту |
NOT_FOUND | 404 | Нет такого объекта или он вам недоступен |
RATE_LIMITED | 429 | Слишком часто — подождите (заголовок Retry-After) |
INVALID_CREDENTIALS | 401 | Неверная почта или пароль |
EMAIL_NOT_VERIFIED | 403 | Почта не подтверждена |
TWO_FACTOR_REQUIRED | 401 | Нужен код двухфакторной аутентификации (twoFactorCode) |
TWO_FACTOR_EMAIL_REQUIRED | 401 | Код отправлен на почту — повторите вход с ним |
TWO_FACTOR_TELEGRAM_REQUIRED | 401 | Код отправлен в Telegram-бот @unixgram_auth |
TWO_FACTOR_INVALID_CODE | 401 | Неверный код |
ACCOUNT_DISABLED · DEVICE_BANNED | 403 | Аккаунт или устройство заблокированы |
CAPTCHA_REQUIRED · CAPTCHA_FAILED | 400 | Нужна капча (регистрация) |
POSTING_TEMPORARILY_BLOCKED | 403 | Публикация временно ограничена |
CONTENT_REJECTED | 422 | Содержимое отклонено модерацией |
INTERNAL_ERROR | 500 | Ошибка сервера — повторите позже |
Идентификаторы объектов — строки (cuid), время — ISO 8601 в UTC.
Постраничная выдача#
Списки отдаются страницами с курсором: в ответе — элементы и курсор следующей страницы (pageInfo.nextCursor, nextCursor или pageInfo.oldestCursor); передайте его в ?cursor= (в истории сообщений — ?before=). Курсора нет — список закончился. Размер страницы — ?limit=, где метод его принимает.
Загрузка файлов#
Файл сначала загружается, потом его адрес передаётся в сообщение, пост или профиль. POST /api/account/upload, multipart/form-data с полями file и kind; ответ — {"url", "thumb", "posterUrl"}.
up = s.post(f"{API}/account/upload", files={"file": open("cat.jpg", "rb")},
data={"kind": "chat-image"}, headers={"x-csrf-token": s.cookies["csrf_token"]}).json()["data"]
call("POST", f"/social/messages/{chat_id}", clientMessageId=str(uuid.uuid4()),
media={"type": "image", "url": up["url"]})| kind | Предел | Для чего |
|---|---|---|
chat-image | 5 МБ | Изображение в чат |
chat-video | 25 МБ | Видео или кружок в чат |
chat-voice | 12 МБ | Голосовое в чат |
chat-file | 50 МБ | Любой файл в чат |
post | 5 МБ | Изображение к посту |
post-video | 120 МБ | Видео к посту |
post-file | 50 МБ | Файл к посту |
story · story-video · story-voice | 5 · 120 · 12 МБ | История |
comment-image · comment-video · comment-voice | 5 · 25 · 12 МБ | Вложение в комментарий |
avatar · cover · cover-video | 5 · 5 · 25 МБ | Аватар и обложка профиля |
Вложение сообщения — media: {type: "image"|"video"|"voice"|"file"|"sticker", url, name?, mime?, sizeBytes?, width?, height?, durationMs?, waveform?}. Кружок — type: "video" с name: "circle".
Повторы без дублей#
Сеть рвётся, запросы повторяются. Отправка сообщения принимает clientMessageId, публикация поста — clientPostId: случайная строка до 64 символов, одна на одно действие. Повтор с тем же ключом вернёт уже созданный объект, а не второй такой же.
Лимиты#
- Не больше 20 запросов в секунду с одного IP-адреса на всё API.
- Вход и восстановление пароля — 10 попыток за 10 минут с адреса; отправка кодов — строже.
- Публикации, комментарии и подписки ограничены по частоте на аккаунт, как в приложении.
- Превышение —
429с заголовкомRetry-After. Подождите и повторите; не долбите сервер в цикле — адрес попадёт под автоматическую защиту.
Примеры#
| Поле | Тип | Описание |
|---|---|---|
GET /api/social/feed | ?cursor ?limit ?following | Лента → feed, pageInfo |
POST /api/social/posts | content, imageUrls, poll, clientPostId… | Опубликовать пост |
POST /api/social/posts/{postId}/like | — | Лайк / снять лайк |
GET /api/social/users/{username} | — | Профиль |
POST /api/social/users/{username}/follow | — | Подписаться / отписаться |
GET /api/social/messages | — | Список чатов |
GET /api/social/messages/{conversationId} | ?before ?limit | Чат и сообщения |
POST /api/social/messages/{conversationId} | content, clientMessageId, replyToId, media… | Отправить сообщение |
POST /api/social/users/{username}/message | — | Открыть личный чат → conversationId |
GET /api/social/search | ?q ?type ?cursor | Поиск |
GET /api/social/notifications | — | Уведомления |
Это малая часть — остальные 338 методов, с полями тел запросов, в справочнике.
Правила#
- Программа действует от имени вашего аккаунта, и отвечаете за неё вы. Спам, накрутка и массовые рассылки блокируются так же, как у людей.
- Указывайте осмысленный User-Agent с названием программы — так проще помочь, если что-то пойдёт не так.
- Методы помечены в справочнике так, как их видит сервер; поля ответа могут дополняться без предупреждения — игнорируйте незнакомые. О несовместимых изменениях сообщаем в @unixgram.