Справочник API
Публичный REST API WardenCore — аутентификация, ошибки и соглашения.
API WardenCore позволяет вашим инструментам, ботам и скриптам управлять сервером программно — читать игроков, выполнять команды, управлять экономикой и не только.
Базовый URL
Все запросы идут на https://api.wardencore.ru/v1. Только по HTTPS.
Премиум-функция
API доступен на серверах с активным премиум-планом. Создание ключа или
вызов /v1 на не-премиум сервере возвращает 403 premium_required, а если
премиум сервера истёк — его существующие ключи перестают работать до продления.
Аутентификация
API аутентифицируется по API-ключу, привязанному к серверу. Создайте его в панели: Настройки → API (см. API-ключи) — ключ показывается один раз, скопируйте его сразу.
Передавайте его как bearer-токен:
Authorization: Bearer wc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxКлюч привязан ровно к одному серверу и несёт фиксированный набор скоупов (прав). Запрос, которому не хватает скоупа, возвращает 403 insufficient_scope.
Ключ также можно ограничить конкретными IP-адресами или CIDR-диапазонами (IPv4/IPv6) в панели. Запрос с IP вне списка возвращает 403 ip_not_allowed.
Формат ответа и ошибки
Успешные ответы — JSON с полями в snake_case. Ошибки всегда в одном стабильном конверте:
{
"error": {
"code": "insufficient_scope",
"message": "The API key lacks the required scope: players:write.",
"details": { "missing_scope": "players:write" },
"request_id": "req_9f2c…"
}
}Всегда ветвитесь по машиночитаемому code, а не по тексту message. Указывайте request_id при обращении в поддержку.
Форма ответа
- Одиночный ресурс возвращается «голым» JSON-объектом (без обёртки).
- Коллекция возвращается как
{ "data": [...], "has_more": boolean, "next_cursor": string | null }(см. Пагинацию). - Мутация возвращает затронутый ресурс (голым) либо
204 No Content, когда возвращать нечего; только что созданный ресурс приходит с201 Created. - Поля никогда не опускаются. Отсутствующее значение — это
null, а не пропущенный ключ, поэтому форма ответа стабильна. Внутриv1поля могут только добавляться — игнорируйте незнакомые.
Числа
Целочисленные поля — это JSON-числа. Значение, которое может превысить 2⁵³−1 (крупные идентификаторы и накопительные счётчики), передаётся десятичной строкой (помечается для каждого поля) — считайте такие непрозрачными. Координаты и прочие дробные значения — обычные JSON-числа.
Размер тела запроса
Тело запроса должно передаваться с Content-Type: application/json и ограничено 1 МБ. Большее тело даёт 413 payload_too_large; любой другой тип содержимого — 415 unsupported_media_type.
| Код | Статус | Значение |
|---|---|---|
unauthorized | 401 | Ключ отсутствует или неверный. |
premium_required | 403 | У сервера нет активного премиум-плана. |
insufficient_scope | 403 | У ключа нет нужного скоупа. |
ip_not_allowed | 403 | Ключ ограничен другими IP-адресами. |
validation_error | 400 | Тело или параметры запроса не прошли валидацию. |
not_found | 404 | Ресурс (или маршрут) не существует. |
rate_limited | 429 | Слишком много запросов — см. лимиты. |
idempotency_conflict | 409 | Idempotency-Key переиспользован с другим телом. |
conflict | 409 | Запрос конфликтует с текущим состоянием ресурса. |
precondition_failed | 412 | Не прошло условие If-Match — ресурс изменился. |
payload_too_large | 413 | Тело запроса превышает лимит размера. |
unsupported_media_type | 415 | Тело запроса должно быть в формате application/json. |
server_unavailable | 503 | Игровой сервер офлайн или недоступен. Повторите позже. |
gateway_timeout | 504 | Сервер не ответил вовремя. |
Лимиты запросов
Лимиты — на ключ. Каждый ответ несёт заголовки чернового стандарта IETF:
RateLimit-Limit: 120
RateLimit-Remaining: 118
RateLimit-Reset: 42
RateLimit-Policy: 120;w=60При превышении — 429 rate_limited с заголовком Retry-After (в секундах), в стандартном конверте ошибки.
Два слоя 429
Лимит на ключ, описанный выше, применяется на уровне приложения и всегда
возвращает JSON-конверт rate_limited вместе с заголовками RateLimit-* и
Retry-After. Отдельный грубый per-IP лимит на границе (nginx) защищает от
флуда ещё до приложения — когда отклоняет он, 429 может прийти голым:
без JSON-конверта и без Retry-After. Считайте любой 429 сигналом
«подожди и повтори»; ветвитесь по коду статуса, а на конверт/заголовки
полагайтесь только когда они есть.
Пагинация
Списочные эндпоинты используют курсорную пагинацию. В ответе есть has_more и next_cursor; передавайте непрозрачный next_cursor обратно в query-параметре cursor, чтобы получить следующую страницу. Не собирайте курсоры вручную — курсор это непрозрачный токен, кодирующий только вашу позицию в выборке, так что его подмена может лишь сдвинуть вас в пределах ваших же результатов и никогда не расширит доступ.
Идемпотентность
Передавайте заголовок Idempotency-Key в запросах POST/PUT, чтобы ретраи были безопасны. Повтор с тем же ключом воспроизводит исходный ответ вместо повторного выполнения; повтор с другим телом даёт 409 idempotency_conflict.
Idempotency-Key: 3f9a1c7e-…Кэширование
Read-эндпоинты, которые безопасно кэшировать, возвращают strong-ETag и заголовок Cache-Control (напр. private, max-age=30). Для условного запроса пришлите этот ETag обратно в If-None-Match на следующем вызове — если ничего не изменилось, API ответит 304 Not Modified с пустым телом, и вы переиспользуете свою кэш-копию, экономя трафик:
GET /v1/… HTTP/1.1
Authorization: Bearer wc_live_…
If-None-Match: "9f2c8ab1…"Cache-Control: private— ответ привязан к вашему ключу, никогда не кладите его в общий/CDN-кэш. Директиваstale-while-revalidate(если есть) говорит, сколько ваш кэш может отдавать устаревшую копию, пока обновляет её в фоне.- Принимается weak-валидатор (
If-None-Match: W/"…") — слабое сравнение по RFC 9110. - Эндпоинты живого статуса (напр.
GET /v1/server) намеренно не кэшируются — всегда отдают текущее состояние.
Контроль конкурентности
Чтобы не терять обновления, когда один ресурс пишут несколько клиентов, используйте оптимистичную блокировку. GET возвращает текущий ETag ресурса; отправьте его обратно в If-Match на следующей записи:
PUT /v1/… HTTP/1.1
Authorization: Bearer wc_live_…
If-Match: "9f2c8ab1…"Если ресурс изменился с момента этого ETag, запись отклоняется с 412 precondition_failed и ничего не меняется — перечитайте, согласуйте и повторите. If-Match использует строгое сравнение (RFC 9110), поэтому weak-валидатор его не удовлетворяет. Без If-Match проверка пропускается (последняя запись побеждает).
Версионирование и устаревание
API версионируется в пути (/v1). Ломающие изменения выходят под новой версией; внутри версии мы только добавляем поля — парсите ответы устойчиво и игнорируйте незнакомые. Каждый ответ несёт заголовок API-Version.
Когда эндпоинт или целая версия объявлены устаревшими, их ответы несут заголовок Deprecation — дату по RFC 9745 в форме Structured-Field (@<unix-секунды>), отмечающую момент устаревания. Когда назначена дата удаления, добавляется и Sunset (HTTP-дата, RFC 8594). Следите за обоими и мигрируйте до даты Sunset.
Доступность сервера
API проксирует запросы к моду WardenCore на вашем сервере по живому соединению. Если сервер офлайн, запросы, которым он нужен, возвращают 503 server_unavailable с заголовком Retry-After — повторите, когда сервер вернётся в онлайн.
API выключен, пока его не включит оператор
Публичный API поставляется выключенным. Пока оператор сервера его не включит, любой запрос к /v1
отвечает 404 not_found — одинаково для всех эндпоинтов и любого ключа.
Со стороны это похоже на обычное «не найдено», поэтому смотрите на охват: выключенный API отдаёт 404 на заведомо существующие пути, а настоящий not-found — например, неизвестный реф игрока — приходит от эндпоинта, который на другие запросы отвечает нормально.
Эндпоинты
Полный справочник эндпоинтов публикуется по мере их выката. Эта страница описывает соглашения, которым следует каждый эндпоинт.