Оформление
Ключи и лимиты
Авторизация
Каждый запрос к API несёт заголовок с ключом приложения:
http
Authorization: Bot emb_2878fed6c91a4b7e…Схема — именно Bot, а не Bearer. С Bearer ключ приложения не сработает: эта схема зарезервирована под токены пользователей.
js
const headers = { Authorization: `Bot ${process.env.BOT_TOKEN}` }Держите ключ в переменных окружения. Не коммитьте его в репозиторий и не вставляйте в код фронтенда — ключ даёт право говорить от имени вашего бота во всех каналах, где он установлен.
Что открывает ключ
Выпуская ключ, вы отмечаете, чем ваше приложение будет пользоваться. Запрос к маршруту, не входящему в этот список, получает 403 — даже если роль бота на канале такое действие разрешает.
| Scope | Что открывает | Маршруты |
|---|---|---|
channel:read | сведения о канале, комнаты, участники | GET /channels/* |
messages:read | история текстовых комнат | GET /rooms/{id}/messages |
messages:write | отправка, правка, удаление своих сообщений, реакции | POST/PATCH/DELETE сообщений и реакций |
voice | вход и выход из голосовых комнат | POST/DELETE /rooms/{id}/voice |
events | подписка на поток событий и настройка вебхука | GET /events/token, GET/PUT/DELETE /webhook |
moderation | закрепление, мут, кик, перенос участников | /channels/{id}/members/*, /rooms/{id}/messages/{id}/pin |
commands | объявление списка команд бота | GET/PUT /commands |
Какой scope нужен каждому маршруту — указано в справочнике. Маршрут GET /me открыт любому ключу.
Отмечайте только нужное
events — самый широкий доступ на чтение: поток несёт все сообщения всех каналов, где стоит бот. Боту-уведомителю, который только пишет, он не нужен — снимите его, и утёкший ключ не даст читать переписку.
moderation — самый опасный на запись: кик лишает человека канала целиком. Отмечайте его только боту-модератору.
Отказ по scope называет недостающее имя:
json
{
"error": "Forbidden",
"status": "error",
"message": "Ключу не выдан scope «messages:write». Перевыпустите ключ в кабинете приложений, отметив этот доступ",
"requiredScope": "messages:write"
}Чтобы изменить набор, перевыпустите ключ — там же отмечаются нужные пункты. moderation и commands появились позже остальных, поэтому у ключей, выпущенных раньше, их нет: перевыпустите ключ, если собираетесь ими пользоваться.
Ключ и роль — два разных ограничения
Работает то, что разрешила и роль бота на канале, и ключ. Роль настраивает администратор канала, ключ — вы. Подробнее: права на канале.
Коды ответов
| Код | Значение | Что делать |
|---|---|---|
200 / 201 / 204 | успех | — |
400 | неверные параметры запроса | текст ошибки указывает поле |
401 | ключ не принят: отсутствует, неверен, отозван | проверить ключ; перевыпуск в кабинете |
403 | действие запрещено: не выдан scope ключа либо не хватает права роли | поле requiredScope в ответе называет недостающий scope; если его нет — см. права на канале |
422 | запрос корректен, но выполнить нельзя (комната не того типа, чужой канал) | проверить идентификаторы |
429 | превышена квота | подождать Retry-After секунд |
504 | портал не ответил вовремя | повторить запрос |
Тело ошибки всегда одной формы:
json
{ "error": "Forbidden", "status": "error", "message": "Недостаточно прав" }401 и 403 — разные проблемы
401 — проблема с ключом: он не принят вовсе.
У 403 две причины, и различает их поле requiredScope:
- оно есть — ключу не выдан нужный scope. Перевыпустите ключ, отметив этот доступ;
- его нет — не хватает права роли бота на канале. Перевыпуск не поможет, попросите администратора канала дать боту роль с нужным правом.
Квоты
| Квота | Лимит |
|---|---|
| Все запросы | 60 в минуту на приложение |
| Отправка сообщений | 20 в минуту на приложение |
Квота считается на приложение, а не на IP: несколько ваших серверов делят одну.
Остаток виден в каждом ответе:
http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57При превышении приходит 429:
http
HTTP/1.1 429 Too Many Requests
Retry-After: 23json
{
"error": "Too Many Requests",
"status": "error",
"message": "Превышена квота запросов: 60 в минуту",
"retryAfterSec": 23
}Простейшая обработка:
js
async function api(path, options = {}) {
const res = await fetch(`https://emotify.ru/api/v1${path}`, {
...options,
headers: {
Authorization: `Bot ${process.env.BOT_TOKEN}`,
'Content-Type': 'application/json',
...options.headers
}
})
if (res.status === 429) {
const wait = Number(res.headers.get('Retry-After') ?? 5)
await new Promise((r) => setTimeout(r, wait * 1000))
return api(path, options) // одна повторная попытка после паузы
}
return res
}Окно квоты скользящее: оно освобождается постепенно, а не разом в начале минуты.
Перевыпуск ключа
Настройки → Приложения → «Перевыпустить ключ».
- Новый ключ показывается один раз — как и при создании.
- Старый перестаёт работать сразу, промежутка с двумя рабочими ключами нет.
- Обновите ключ в окружении бота до нажатия кнопки или сразу после — иначе бот будет получать
401до перезапуска с новым ключом. - Набор scope задаётся заново. Поля подставлены текущими — снимите лишнее, если сужаете доступ, или отметьте новое, если расширяете.
Это же единственный способ изменить набор scope у работающего приложения.
Что гасит доступ
| Действие | Ключ | Доступ к каналу |
|---|---|---|
| Перевыпуск ключа | старый умирает | не меняется |
| Снятие scope при перевыпуске | работает | маршруты этого scope отвечают 403 |
| Снятие бота с канала | работает | пропадает на этом канале |
| Удаление приложения | умирает | пропадает везде |
Сообщения, написанные ботом, во всех случаях остаются в истории.