WardenCoredocs
API

Справочник 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.

КодСтатусЗначение
unauthorized401Ключ отсутствует или неверный.
premium_required403У сервера нет активного премиум-плана.
insufficient_scope403У ключа нет нужного скоупа.
ip_not_allowed403Ключ ограничен другими IP-адресами.
validation_error400Тело или параметры запроса не прошли валидацию.
not_found404Ресурс (или маршрут) не существует.
rate_limited429Слишком много запросов — см. лимиты.
idempotency_conflict409Idempotency-Key переиспользован с другим телом.
conflict409Запрос конфликтует с текущим состоянием ресурса.
precondition_failed412Не прошло условие If-Match — ресурс изменился.
payload_too_large413Тело запроса превышает лимит размера.
unsupported_media_type415Тело запроса должно быть в формате application/json.
server_unavailable503Игровой сервер офлайн или недоступен. Повторите позже.
gateway_timeout504Сервер не ответил вовремя.

Лимиты запросов

Лимиты — на ключ. Каждый ответ несёт заголовки чернового стандарта 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 — например, неизвестный реф игрока — приходит от эндпоинта, который на другие запросы отвечает нормально.

Эндпоинты

Полный справочник эндпоинтов публикуется по мере их выката. Эта страница описывает соглашения, которым следует каждый эндпоинт.

Содержание