API для владельцев: награды за голоса, виджеты, статистика
Игроки голосуют за ваш сервер на Онлайномере, а вы выдаёте им награду в игре. Это делается тремя способами на выбор: запросом к API при заходе игрока, периодическим опросом очереди или вебхуком, который мы вызываем в момент голоса.
Быстрый старт
- Добавьте сервер и подтвердите владение.
- В кабинете откройте «Голосование и API» и нажмите «Создать ключ» — он показывается один раз, в базе хранится только хэш.
- Дайте игрокам ссылку на голосование:
https://onlinomer.ru/vote/5/(команда/voteв игре, кнопка на сайте). - При заходе игрока вызовите
POST /api/v1/votes/claim— в ответе будет, сколько наград выдать.
Авторизация
Все методы для владельца требуют ключ сервера в заголовке. Ключ привязан к одному серверу, id сервера передавать не нужно.
Authorization: Bearer onl_0123456789abcdef0123456789abcdef01234567 # или X-Api-Key: onl_0123456789abcdef0123456789abcdef01234567
Ответы — JSON в UTF-8, у каждого есть поле ok. Ошибка: {"ok": false, "error": {"code": "...", "message": "..."}} с кодом HTTP 4xx. Лимит — 300 запросов в минуту на сервер (ответ 429). Время везде в ISO 8601, UTC; day — московские сутки голоса.
Награды за голоса
Голос засчитывается в сутки один раз на ник. Награда считается невыданной, пока вы её не заберёте через claim или ack. Невостребованные голоса хранятся в очереди 30 дней.
| Метод | Что делает |
|---|---|
GET /api/v1/votes/check?nick=Steve | Голосовал ли ник сегодня и сколько наград ждёт: voted_today, pending_rewards. Ничего не списывает — удобно для подсказки «проголосуй и получи приз». |
POST /api/v1/votes/claim nick=Steve | Главный метод. Атомарно забирает все невыданные награды ника и возвращает их. Повторный вызов вернёт claimed: 0 — выдать награду дважды нельзя. |
GET /api/v1/votes/pending?limit=100 | Очередь невыданных наград всех игроков — для плагина, который раз в минуту проверяет очередь. |
POST /api/v1/votes/ack ids=1,2,3 | Отметить голоса выданными (после pending). Можно JSON: {"ids":[1,2,3]}. |
GET /api/v1/votes?after_id=0&limit=100 | История голосов постранично (next_after_id — курсор). Фильтры: nick, pending=1. |
GET /api/v1/server | Данные вашего сервера: онлайн, голоса, место. |
Пример: выдача награды при заходе игрока
curl -X POST https://onlinomer.ru/api/v1/votes/claim \
-H "Authorization: Bearer $ONLINOMER_KEY" \
-d nick=Steve
{
"ok": true,
"nick": "Steve",
"claimed": 2,
"votes": [
{"id": 101, "nick": "Steve", "day": "2026-10-17", "voted_at": "2026-10-17T14:02:11+00:00", "claimed": true, "claimed_at": "2026-10-18T09:00:03+00:00"},
{"id": 118, "nick": "Steve", "day": "2026-10-18", "voted_at": "2026-10-18T08:44:50+00:00", "claimed": true, "claimed_at": "2026-10-18T09:00:03+00:00"}
]
}
Выдайте награду claimed раз.
Minecraft (Java-плагин, Bukkit/Paper)
@EventHandler
public void onJoin(PlayerJoinEvent e) {
String nick = e.getPlayer().getName();
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
HttpRequest req = HttpRequest.newBuilder(URI.create("https://onlinomer.ru/api/v1/votes/claim"))
.header("Authorization", "Bearer " + KEY)
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString("nick=" + URLEncoder.encode(nick, UTF_8))).build();
String json = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString()).body();
int n = JsonParser.parseString(json).getAsJsonObject().get("claimed").getAsInt();
if (n > 0) Bukkit.getScheduler().runTask(plugin, () -> giveRewards(e.getPlayer(), n));
});
}
GTA 5 RP (FiveM, Lua)
AddEventHandler('playerJoining', function()
local src, nick = source, GetPlayerName(source)
PerformHttpRequest('https://onlinomer.ru/api/v1/votes/claim', function(code, body)
if code == 200 then
local r = json.decode(body)
if r.claimed > 0 then GiveVoteReward(src, r.claimed) end
end
end, 'POST', 'nick=' .. nick, {
['Authorization'] = 'Bearer ' .. Config.OnlinomerKey,
['Content-Type'] = 'application/x-www-form-urlencoded'
})
end)
Опрос очереди (любой язык)
import requests, time
H = {"Authorization": "Bearer " + KEY}
while True:
votes = requests.get("https://onlinomer.ru/api/v1/votes/pending", headers=H).json()["votes"]
given = [v["id"] for v in votes if give_reward_if_online(v["nick"])]
if given:
requests.post("https://onlinomer.ru/api/v1/votes/ack", headers=H, json={"ids": given})
time.sleep(60)
Вебхук: мы звоним вам в момент голоса
Укажите адрес в кабинете — на каждый голос мы отправим POST с JSON:
{
"event": "vote",
"vote_id": 118,
"server_id": 5,
"nick": "Steve",
"day": "2026-10-18",
"voted_at": "2026-10-18T08:44:50+00:00",
"votes_month": 124,
"votes_total": 1860
}
Заголовки: X-Onlinomer-Event (vote или ping), X-Onlinomer-Timestamp (секунды) и X-Onlinomer-Signature: sha256=… — HMAC-SHA256 от строки timestamp + "." + тело с вашим секретом из кабинета. Проверяйте подпись и отклоняйте события старше 5 минут.
<?php // PHP
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_ONLINOMER_TIMESTAMP'];
$sig = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, SECRET);
if (!hash_equals($sig, $_SERVER['HTTP_X_ONLINOMER_SIGNATURE']) || abs(time() - $ts) > 300) { http_response_code(403); exit; }
$vote = json_decode($body, true); // выдайте награду $vote['nick'], запомните $vote['vote_id']
Ответьте кодом 2xx в течение 5 секунд. Иначе повторим через 1 минуту, 5 минут, 30 минут, 2 часа и 12 часов (всего 6 попыток), поэтому храните vote_id и не выдавайте награду дважды. Вебхук можно сочетать с claim: пришёл вебхук — выдали сразу, а при заходе игрока claim подберёт то, что не дошло. Адрес должен вести на публичный сервер (внутренние адреса и редиректы не поддерживаются).
Публичные данные (без ключа)
Открыты для запросов из браузера (CORS), кэшируются на 30 секунд.
GET https://onlinomer.ru/api/v1/servers/5GET https://onlinomer.ru/api/v1/servers/5/votes?period=month&limit=10 # лучшие голосующие (month | all) GET https://onlinomer.ru/api/v1/servers/5/reviews?page=1&limit=10 # отзывы игроков: оценки, тексты, ответы владельца
Подойдёт для таблицы лидеров на вашем сайте или в игре: онлайн, место по голосам, топ ников.
Статистика
В кабинете на странице «Статистика» видно, сколько раз сервер показали в каталоге, открыли страницу, скопировали IP, нажали «Играть», перешли по вашим ссылкам, откуда пришли люди и сколько проголосовало. Всё это же отдаёт GET /api/v1/stats?days=30 (1–90 дней): сводка totals, по дням daily, переходы по ссылкам links и источники referrers.
Как считаем: боты не учитываются; «уникальные» — по дневному хэшу без cookie и без хранения IP; копирование IP, «Играть» и переходы по каждой ссылке считаются раз в сутки на посетителя, чтобы клики нельзя было накрутить.
Виджеты и бейджи для вашего сайта
Карточка с онлайном, голосами и кнопкой «Проголосовать»:
<a href="…адрес страницы вашего сервера на Онлайномере…" data-onlinomer>Наш сервер — онлайн на Онлайномере</a> <script src="https://onlinomer.ru/embed.js" data-server="5" data-theme="auto" async></script> <!-- или без скрипта --> <iframe src="https://onlinomer.ru/widget/5/" width="320" height="200" style="border:0" loading="lazy"></iframe>
Ссылку <a data-onlinomer> оставьте: скрипт ставит виджет над ней, а сама ссылка остаётся подписью. Готовый код со ссылкой на страницу вашего сервера — в кабинете («Виджеты»).
Бейдж для README, форума, Discord: <a href="…страница сервера…"><img src="https://onlinomer.ru/badge/5.svg"></a>, Markdown: [](ссылка), BBCode: [url=ссылка][img]https://onlinomer.ru/badge/5.svg[/img][/url]. Параметр ?type=votes (по умолчанию), online или rank. Тема виджета: light, dark, auto.
Открытые данные и атрибуция
Публичные данные Онлайномера — онлайн, аптайм, рейтинг — можно использовать на своих сайтах, в ботах и исследованиях по лицензии CC BY 4.0: со ссылкой на Онлайномер (onlinomer.ru) рядом с данными. Список серверов игры: GET /api/v1/servers?game=mc&limit=50&page=1, сервер: GET /api/v1/servers/{id}, таблица топ-500: /data/top.csv.
Правила голосования
- Один ник — один голос за сервер в московские сутки; с одного IP — не больше 3 голосов за сервер и 20 за все серверы в сутки.
- Голосование защищено проверкой браузера (короткая задача и скрытое поле); просто слать запросы на форму не получится. Выдавайте награды только через API — подделать голос в обход сайта нельзя.
- Накрутка голосов (боты, обмен голосами, покупка) запрещена: мы вправе обнулить голоса и снять сервер с рейтинга по голосам.
- Ник игрока и время голоса видны публично в списке лучших голосующих. Адрес игрока мы храним только как необратимый хэш в течение 2 суток.
Вопросы по API — в поддержку.