Концепции
Ошибки
Ошибки используют стандартные коды состояния HTTP и всегда имеют одинаковую JSON-структуру.
Формат ошибки#
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This API key does not have the scope posts:write"
}
}
codeстабилен: используйте его в своём коде.messageпредназначен для людей и может меняться.- Некоторые ошибки добавляют дополнительные поля рядом с
codeиmessage(например, некорректное поле в ошибке валидации).
Коды ошибок#
| Статус | Код | Значение · что делать |
|---|---|---|
| 400 | VALIDATION_ERROR | Параметр или поле тела отсутствует либо некорректно. Исправьте запрос; не повторяйте его без изменений. |
| 400 | INVALID_JSON | Тело не является корректным JSON. Отправляйте Content-Type: application/json и корректное тело. |
| 401 | INVALID_API_KEY | Ключ отсутствует, имеет неверный формат или отозван. Проверьте заголовок Authorization. |
| 403 | INSUFFICIENT_SCOPE | У ключа нет scope, необходимого для этого endpoint. Создайте ключ с нужными scopes. |
| 403 | DEVELOPER_ACCESS_REVOKED | Доступ разработчика для этого аккаунта приостановлен или отозван. Напишите на developers@linework.app. |
| 403 | PROFILE_INCOMPLETE | Добавьте в аккаунт фото профиля и обложку, прежде чем использовать endpoint записи. |
| 403 | CHAT_NOT_ALLOWED | Правило антиспама не разрешает это сообщение: человек вам не писал и не подписан на вас. |
| 403 | CHAT_BLOCKED | Один из вас заблокировал другого. Не повторяйте запрос. |
| 403 | STORE_BLOCKED | Этот магазин заблокировал вас. |
| 403 | USER_UNAVAILABLE | Пользователь недоступен (заблокирован, закрыт или приостановлен). |
| 403 | FORBIDDEN | Действие не разрешено для этого аккаунта (например, редактирование чужого поста). |
| 404 | NOT_FOUND | Ресурс не существует или вы не можете его видеть. |
| 409 | CONFLICT | Запрос конфликтует с текущим состоянием (например, повторная отправка уже отправленного заказа). |
| 413 | PAYLOAD_TOO_LARGE | Тело запроса или загружаемый файл слишком велики. См. ограничения на медиафайлы в разделе Пост с медиафайлами. |
| 429 | RATE_LIMITED | Слишком много запросов или исчерпана дневная квота. Подождите Retry-After. См. Ограничения частоты. |
| 500 | INTERNAL_ERROR | Что-то пошло не так на нашей стороне. Повторите попытку позже с экспоненциальной задержкой. |
Со временем могут добавляться новые коды: трактуйте неизвестный код в общем значении его HTTP-статуса.
Повторять или нет?#
| Статус | Повторять? |
|---|---|
| 400, 401, 403, 404, 409, 413 | Нет. Сначала исправьте запрос, ключ или аккаунт. |
| 429 | Да, после Retry-After. |
| 500, 502, 503, 504 | Да, с экспоненциальной задержкой. Для неидемпотентных операций записи (например, POST /posts) сначала убедитесь, что действие ещё не было выполнено. |
Пример обработчика#
const res = await fetch(url, options);
if (!res.ok) {
const { error } = await res.json().catch(() => ({ error: { code: "UNKNOWN" } }));
switch (error.code) {
case "RATE_LIMITED": /* wait Retry-After, then retry */ break;
case "INVALID_API_KEY":
case "DEVELOPER_ACCESS_REVOKED": /* stop the bot and alert someone */ break;
case "CHAT_NOT_ALLOWED": /* skip this user */ break;
default: throw new Error(`${res.status} ${error.code}: ${error.message}`);
}
}
r = s.post(url, json=body, timeout=30) # s = requests.Session() with the Authorization header
if not r.ok:
err = r.json().get("error", {})
code = err.get("code")
if code == "RATE_LIMITED":
... # wait Retry-After, then retry
elif code in ("INVALID_API_KEY", "DEVELOPER_ACCESS_REVOKED"):
... # stop the bot and alert someone
elif code == "CHAT_NOT_ALLOWED":
... # skip this user
else:
raise RuntimeError(f"{r.status_code} {code}: {err.get('message')}")