# 🔌 API сайта

Публичное API только для чтения: игроки, дуэли, города, путеводитель, форум. Лимиты и API-ключи.

Публичное API сайта PfauMC отдаёт данные об игроках, дуэлях, городах, путеводителе и форуме в виде JSON. Оно только для чтения: через него нельзя ничего изменить. Статья рассчитана на тех, кто пишет Discord- и Telegram-ботов, сайты и инструменты вокруг сервера.

## Основы

Базовый адрес: **https://auth.pfaumc.io/api/v1**

- Все запросы – **GET**, ответы – JSON в UTF-8.
- Имена полей в **snake_case**, игрок везде определяется по **uuid** (с дефисами), поле называется id.
- Даты – ISO 8601 в UTC, например 2026-11-04T10:00:00Z.
- Мы не отдаём IP-адреса, способы входа и любые данные, которых нет на самом сайте. Данные те же, что видит гость.
- Онлайн и графики посещаемости сервера в целом смотрите на [mcwatch.online](https://mcwatch.online/servers/pfaumc).

## Ошибки

Любая ошибка приходит с подходящим HTTP-кодом и телом такого вида:

*{"error": "not found", "code": "not_found"}*

Поле **code** стабильно и предназначено для программ, **error** – текст для человека, его формулировка может меняться.

- **bad_request** (400) – неверные или недостающие параметры.
- **not_found** (404) – игрок, город или страница не найдены.
- **invalid_api_key** (401) – ключ неверный или отозван.
- **rate_limited** (429) – превышен лимит без ключа.
- **quota_exceeded** (429) – исчерпана квота вашего ключа.
- **internal** (500) – ошибка на нашей стороне, повторите позже.

## Доступ без ключа

Для разовых запросов и экспериментов ключ не нужен: лимиты рассчитаны на обычного человека с браузером. Они считаются отдельно для каждого адреса, с которого идут запросы.

- JSON-ответы API в целом: 60 запросов в минуту, короткий всплеск до 40 запросов подряд.
- Профили игроков и их статистика: 120 в минуту, всплеск до 120.
- Страницы форума и вики (HTML): 30 в минуту, всплеск до 20.
- Машинные копии (/llms.txt, /llms-full.txt, адреса с .md, /sitemap.xml): 30 в минуту, всплеск до 30.

Бот, который опрашивает API с общего хостинга или чаще раза в секунду, быстро упрётся в эти лимиты. Для такого случая существуют ключи.

## API-ключи

Ключ даёт отдельную квоту под ваше приложение. Данные он не расширяет: ответы те же, что и у гостя, а личность владельца ключа не передаётся.

**Где получить.** Войдите на сайт и откройте [настройки форума, вкладка API](/forum/settings?tab=api). Нажмите создание ключа, задайте имя (до 64 символов, например название бота). Ключ вида pfau_ и 43 символа показывается **один раз**: скопируйте его сразу. Потерянный ключ не восстановить, создайте новый. Там же видны префикс ключа, время последнего использования и число запросов за сегодня, а график по часам и группам методов – в разделе использования.

**Как передавать.** Только в заголовке:

*Authorization: Bearer pfau_...*

- Передавайте ключ **только с сервера**. Не кладите его в адрес запроса (в query он не принимается), в код сайта, мобильное приложение или репозиторий.
- Из браузера ключ не работает: CORS не разрешает заголовок Authorization. Если страница сайта должна показывать данные, ходите за ними через свой сервер.
- Скомпрометированный ключ отзовите на той же вкладке. Отзыв действует сразу, запросы с ним получат 401.

**Лимиты по рангу.** Количество ключей и квота зависят от вашего ранга на сервере. Квота действует на каждый ключ отдельно.

- Без подписки: 1 ключ, 120 запросов в минуту, 20 000 в сутки.
- Подписка Фанат: 2 ключа, 180 в минуту, 30 000 в сутки.
- Подписка Меценат: 3 ключа, 300 в минуту, 50 000 в сутки.
- Подписка Спонсор: 5 ключей, 600 в минуту, 125 000 в сутки.
- Персонал сервера: 10 ключей, 1200 в минуту, 500 000 в сутки.

Окно минуты – календарная минута, окно суток – сутки по UTC, после 00:00 UTC счётчик обнуляется. Отклонённые запросы в квоту не засчитываются. Если ранг понизился, существующие ключи продолжают работать с новыми лимитами, а новые можно создать, только когда ключей меньше допустимого числа.

Ключ работает на всех публичных адресах API, а также на страницах форума и вики, /llms.txt, адресах с .md и /sitemap.xml.

## Заголовки лимитов

Каждый ответ на запрос с ключом содержит:

- **X-RateLimit-Limit** – квота в минуту.
- **X-RateLimit-Remaining** – сколько запросов осталось в текущей минуте.
- **X-RateLimit-Reset** – через сколько секунд минута закончится.
- **X-RateLimit-Daily-Limit** – квота в сутки.
- **X-RateLimit-Daily-Remaining** – сколько запросов осталось в сутках.

При ответе 429 добавляется заголовок **Retry-After** – число секунд, через которое можно повторить запрос. Дождитесь его и не повторяйте запрос в цикле.

## Ответы 429 и 401

Лимит без ключа, код 429:

*{"error": "Слишком много запросов. Для автоматического доступа нужен API-ключ: https://pfaumc.io/forum/settings?tab=api", "code": "rate_limited", "retry_after": 30, "api_key_url": "https://pfaumc.io/forum/settings?tab=api", "docs": "https://pfaumc.io/wiki/api"}*

На HTML-страницах вместо JSON показывается короткая страница с тем же текстом и ссылкой.

Квота ключа исчерпана, код 429. Поле **window** – minute или day:

*{"error": "Квота ключа исчерпана: 120 запросов в минуту", "code": "quota_exceeded", "window": "minute", "retry_after": 30}*

Неверный или отозванный ключ, код 401. Запрос с таким ключом не обслуживается, даже если без ключа он бы прошёл:

*{"error": "Неверный или отозванный API-ключ", "code": "invalid_api_key"}*

## Кеширование

Данные меняются с разной скоростью, поэтому кеш настроен по-разному, а нужные заголовки приходят в каждом ответе.

- Ответы содержат **Cache-Control** с max-age: профиль игрока живёт 60 секунд, список игроков 15 секунд, рейтинг дуэлей и статистика игрока 60 секунд. Повторный запрос в этот срок отправлять не нужно: берите ответ из своего кеша.
- Профиль и ряд других ответов содержат **ETag**. Когда срок истёк, отправьте его обратно в заголовке **If-None-Match**: если данные не изменились, придёт код **304** без тела.
- Ответ зависит от заголовка Accept: браузеру, который просит text/html, JSON отдаётся с отступами, остальным – сжатым. Для бота ставьте Accept: application/json.

Хороший клиент кеширует ответы по max-age и не тратит квоту на то, что не изменилось.

## Эндпоинты

Все пути ниже – относительно базового адреса.

### Игроки

**GET /players?online=true&q=&limit=** – список игроков. Параметры: online=true – только те, кто сейчас в игре; q – начало ника (короче двух символов вернёт пустой список); limit – не больше 25 при поиске. Без единого фильтра придёт 400: полный список всех игроков не отдаётся. В ответе items, у каждого игрока: id, name, online, server (на каком сервере сидит, например survival), session_started_at, skin (url и model) и roles (key, title, color, priority). Кеш 15 секунд.

**GET /players/{key}** – профиль игрока. Вместо key ник или uuid. Формат совместим с профилями Mojang: id, name и properties (textures с подписью), поэтому сторонние отрисовщики скинов работают без правок, в том числе для игроков без лицензии. Наши данные лежат во вложенном объекте pfaumc: skin (готовая ссылка на PNG скина 64×64), roles (все действующие роли от старшей к младшей), first_seen_at, city (id, slug, name или null), ban (действующий бан: reason и expires_at, null – навсегда; либо null, если бана нет) и violations (история банов и мутов от новых к старым: kind, reason, created_at, expires_at, status). Статус бывает active, expired или lifted. Если игрок неизвестен, придёт 404. Кеш 60 секунд, есть ETag.

**GET /players/{key}/stats** – то, что растёт, пока человек играет. Поля: online, last_seen_at, playtime (online_seconds, active_seconds, session_count), activity (посуточная активность за последний год в секундах, дни без игры опущены) и duels.tiers (тир по каждому киту с хотя бы одним рейтинговым матчем). Кеш 60 секунд.

### Дуэли

**GET /duels/leaderboard?kit=** – 100 лучших игроков кита по рейтингу среди прошедших калибровку. Параметр kit – идентификатор кита (например mace или sword). Некорректный идентификатор вернёт 400, неизвестный кит – пустой список. В ответе kit и items: place, id, name, tier (от LT5 до HT1), step (от 0 до 14, для сравнения китов), tr (рейтинг внутри тира, от 0 до 100; на самом верху больше), games, placements_left. Место определяется рейтингом, а не только тиром. Кеш 60 секунд.

### Города

**GET /cities** – список городов.

**GET /cities/{slug}** – страница города: описание, координаты, глава и жители.

### Путеводитель

**GET /guide/places** – все места на карте мира: сначала продвигаемые, затем по рейтингу.

**GET /guide/places/{slug}** – место и последние 20 отзывов. Анонимные отзывы приходят с author равным null.

### Медиа

**GET /media?ids=a,b** – описание до 50 файлов форума для показа: kind, status, width, height, duration_ms, loop.

**GET /media/{id}** – состояние одного файла: uploading, processing, ready или failed.

### Мониторинг

**GET /monitor** – сводка онлайна сервера за текущую и прошлую неделю: средний и максимальный онлайн. Кеш 5 минут.

### Форум

**GET /forum/categories** – разделы форума, **GET /forum/categories/{key}/topics** – темы раздела, **GET /forum/topics/{id}/posts** – сообщения темы. Видны только открытые разделы, то есть то, что доступно гостю.

## Машинные копии для LLM-агентов

Для нейросетевых агентов и поисковых роботов вики и форум доступны в виде Markdown без вёрстки:

- **/llms.txt** – оглавление сайта: вики, форум, ссылки на копии.
- **/llms-full.txt** – вся вики одним файлом.
- Добавьте **.md** к адресу статьи вики или темы форума: например /wiki/rules.md или /forum/t/1.md.
- **/sitemap.xml** – карта сайта.

Адреса работают без ключа в пределах анонимных лимитов, с ключом – в пределах его квоты. Именно эта статья в Markdown: /wiki/api.md.

## Правила хорошего тона

- Кешируйте ответы и учитывайте max-age.
- Не опрашивайте API чаще, чем нужно вашему приложению: для онлайна хватит раза в 15 секунд.
- Указывайте в User-Agent название и контакт вашего проекта.
- Не передавайте ключ третьим лицам. За запросы с вашим ключом отвечаете вы; если ключ утёк, отзовите его в настройках и выпустите новый.

**Нужен лимит выше или метод, которого нет?** Напишите в [Discord](https://discord.gg/BPmxWwdChY).

---
Источник: https://pfaumc.io/wiki/api
Обновлено: 2026-11-04
