Strona Główna

Wiki » API w praktyce: przykłady użycia

API w praktyce: przykłady użycia

Gotowe scenariusze wykorzystania publicznego API: co chcesz zbudować, które endpointy wywołać i w jakiej kolejności, na co uważać - oraz działający kod do skopiowania. Każdy przykład korzysta z prawdziwego adresu API gry.

Pełna dokumentacja wszystkich endpointów Parametry, przykładowe odpowiedzi, token gildii, limity i kody błędów.

Strona z rankingiem i buildami najlepszych graczy

Dla kogo Strony fanowskie, blogi z poradnikami, serwisy społeczności.

Cel Pokazać aktualny top graczy serwera, a po kliknięciu w gracza jego pełny build: ekwipunek z ulepszeniami, CP i klasę.

Krok po kroku

  1. 1 Pobierz ranking - od razu dostajesz nick, poziom, avatar, gildię i broń każdego gracza. GET /api/v1/servers/s1/rankings/characters/level?limit=100
  2. 2 Po kliknięciu w gracza pobierz jego profil z buildem. GET /api/v1/servers/s1/characters/{characterRef}

Wskazówki

  • Ranking odświeża się co minutę - trzymaj go w pamięci swojej strony co najmniej tyle samo.
  • Profil prywatny ma profile_public: false i build: null - pokaż wtedy samą kartę gracza.
  • Profile pobieraj dopiero po kliknięciu, a nie wszystkie naraz - limit to 60 zapytań na minutę.

Gotowa strona HTML + JavaScript (zapisz jako top10.html i otwórz w przeglądarce)

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Berserk Rush - Top 10</title>
<style>
  body { font-family: sans-serif; background: #111; color: #eee; }
  li { margin: 6px 0; cursor: pointer; }
  img { width: 32px; height: 32px; vertical-align: middle; border-radius: 4px; }
</style>
<ol id="top"></ol>
<pre id="build"></pre>
<p><small>Data: Berserk Rush</small></p>
<script>
const API = 'https://berserkrush.pl/api/v1/servers/s1';

async function api(path) {
  const response = await fetch(API + path + (path.includes('?') ? '&' : '?') + 'lang=en');
  const body = await response.json();
  if (!response.ok) throw new Error(body.error.code);
  return body.data;
}

async function showBuild(id) {
  const hero = await api('/characters/' + id);
  const out = document.getElementById('build');
  if (!hero.profile_public) {
    out.textContent = hero.name + ' keeps the profile private.';
    return;
  }
  const gear = hero.build.equipment.map(e => `${e.slot}: ${e.item.name} +${e.upgrade_level} (${e.rarity})`);
  out.textContent = `${hero.name} - CP ${hero.combat_power}\n` + gear.join('\n');
}

api('/rankings/characters/level?limit=10').then(top => {
  const list = document.getElementById('top');
  for (const hero of top) {
    const li = document.createElement('li');
    const avatar = Object.assign(document.createElement('img'), { src: hero.avatar_url, alt: '' });
    li.append(avatar, ` ${hero.name} - lvl ${hero.level_label} (${hero.weapon_type})`); // text node, safe
    li.onclick = () => showBuild(hero.id);
    list.appendChild(li);
  }
});
</script>
</html>

Bot na Discorda z komendami o graczach i gildiach

Dla kogo Serwery Discord gildii i społeczności graczy.

Cel Odpowiadać na komendy !top, !hero i !guild aktualnymi danymi z gry, bez wychodzenia z Discorda.

Krok po kroku

  1. 1 !top - pierwsza piątka rankingu poziomów. GET /api/v1/servers/s1/rankings/characters/level?limit=5
  2. 2 !hero Nick - poziom, gildia, ELO i CP gracza. GET /api/v1/servers/s1/characters/{characterRef}
  3. 3 !guild Nazwa - poziom, liczba członków i lider gildii. GET /api/v1/servers/s1/guilds/{guildRef}

Wskazówki

  • Nieznany nick albo gildia to odpowiedź 404 z kodem character_not_found albo guild_not_found - odpowiedz wtedy krótkim komunikatem.
  • Nicki i nazwy gildii przepuszczaj przez encodeURIComponent - mogą zawierać spacje i polskie znaki.
  • Na anglojęzycznym serwerze dodaj ?lang=en, żeby tytuły i nazwy przedmiotów były po angielsku.

Bot w Node.js (discord.js v14)

// Minimal Discord bot (discord.js v14, Node 18+): !top, !hero <name>, !guild <name>
import { Client, GatewayIntentBits } from 'discord.js';

const API = 'https://berserkrush.pl/api/v1/servers/s1';
const client = new Client({
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
});

async function api(path) {
  const response = await fetch(API + path);
  return response.ok ? (await response.json()).data : null; // 404 = character_not_found / guild_not_found
}

client.on('messageCreate', async (message) => {
  const [command, ...args] = message.content.trim().split(/\s+/);
  const name = encodeURIComponent(args.join(' '));

  if (command === '!top') {
    const top = await api('/rankings/characters/level?limit=5');
    if (!top) return message.reply('The game API is not available right now.');
    await message.reply(top.map(h => `#${h.rank} ${h.name} (${h.level_label}, ${h.weapon_type})`).join('\n'));
  }

  if (command === '!hero' && name) {
    const hero = await api(`/characters/${name}`);
    if (!hero) return message.reply('No such character.');
    const guild = hero.guild ? ` [${hero.guild.name}]` : '';
    const power = hero.profile_public ? `, CP ${hero.combat_power}` : ' (private profile)';
    await message.reply(`${hero.name}${guild}: level ${hero.level_label}, ELO ${hero.arena.elo}${power}`);
  }

  if (command === '!guild' && name) {
    const guild = await api(`/guilds/${name}`);
    if (!guild) return message.reply('No such guild.');
    await message.reply(`${guild.name}: level ${guild.level}, ${guild.members}/${guild.max_members} members, leader ${guild.leader?.name ?? '-'}`);
  }
});

client.login(process.env.DISCORD_TOKEN);

Tygodniowy raport skarbnika gildii

Dla kogo Liderzy i skarbnicy gildii (wymaga tokena gildii).

Cel Raz w tygodniu wysłać na kanał gildii stan skarbca, najhojniejszych członków i listę osób, które nic nie wpłaciły.

Krok po kroku

  1. 1 Pobierz stan skarbca razem z limitami. GET /api/v1/servers/s1/guild
  2. 2 Pobierz sumy wpłat z ostatnich 7 dni - lista zawiera też członków z samymi zerami. GET /api/v1/servers/s1/guild/donations/summary?days=7&sort=gold

Wskazówki

  • Skrypt uruchamiaj na swoim serwerze (np. cron raz w tygodniu), a token trzymaj w zmiennej środowiskowej.
  • Członkowie, którzy odeszli, a wpłacali w tym tygodniu, są w osobnej liście former_members.
  • Po przekazaniu przywództwa token przestaje działać (token_invalid) - nowy lider musi wygenerować nowy.

Skrypt w Pythonie wysyłający raport na webhook Discorda

# Weekly treasury report for the guild Discord channel - run it once a week (cron) on YOUR server.
# pip install requests; env: BERSERK_GUILD_TOKEN (brk_s1_...), DISCORD_WEBHOOK_URL
import os
import requests

API = "https://berserkrush.pl/api/v1/servers/s1"
HEADERS = {"Authorization": f"Bearer {os.environ['BERSERK_GUILD_TOKEN']}"}

guild = requests.get(f"{API}/guild", headers=HEADERS, timeout=10).json()["data"]
summary = requests.get(f"{API}/guild/donations/summary", params={"days": 7, "sort": "gold"},
                       headers=HEADERS, timeout=10).json()["data"]

treasury = guild["treasury"]
lines = [
    f"**{guild['name']}** - {summary['period']['from']} .. {summary['period']['to']}",
    f"Treasury: {treasury['gold']:,} / {treasury['gold_cap']:,} gold, {treasury['gems']} / {treasury['gems_cap']} gems",
    f"Donated: {summary['totals']['gold']:,} gold, {summary['totals']['exp']:,} EXP",
    "",
    "Top donors:",
]
for row in summary["members"][:5]:
    lines.append(f"- {row['character']['name']}: {row['gold']:,} gold, {row['exp']:,} EXP")

idle = [row["character"]["name"] for row in summary["members"] if row["donations"] == 0]
if idle:
    lines += ["", "No donations this week: " + ", ".join(idle)]

requests.post(os.environ["DISCORD_WEBHOOK_URL"], json={"content": "\n".join(lines)}, timeout=10)

Synchronizacja wpłat do własnej bazy lub arkusza

Dla kogo Twórcy paneli do zarządzania gildią (wymaga tokena gildii).

Cel Co kilka minut dociągać tylko nowe wpłaty i trzymać pełną historię u siebie - pod własne statystyki, rangi albo nagrody dla członków.

Krok po kroku

  1. 1 Pobieraj wpłaty z parametrem since ustawionym na najnowsze updated_at z poprzedniej synchronizacji, strona po stronie do meta.last_page. GET /api/v1/servers/s1/guild/donations?since=2026-09-21T12:00:00Z&per_page=100
  2. 2 Opcjonalnie odśwież skład gildii, żeby przypisać wpłaty do obecnych członków i ról. GET /api/v1/servers/s1/guild/members

Wskazówki

  • Zapisuj wpłaty po polu id (upsert) - automatyczna dotacja EXP to jeden wpis na dobę, który rośnie do północy.
  • Cofnij since o minutę względem ostatniej synchronizacji - nakładające się okna są niegroźne, bo robisz upsert.
  • Odpowiedź 401 token_invalid oznacza unieważniony token - zatrzymaj synchronizację i poproś lidera o nowy.

Skrypt w Node.js zapisujący wpłaty do pliku JSON

// sync-donations.mjs - keeps every guild donation in donations.json (Node 18+, run on YOUR server).
// Auto EXP donations are one row per player per day that keeps growing - always upsert by id.
import { readFile, writeFile } from 'node:fs/promises';

const API = 'https://berserkrush.pl/api/v1/servers/s1';
const headers = { Authorization: `Bearer ${process.env.BERSERK_GUILD_TOKEN}` };

async function sync() {
  const store = JSON.parse(await readFile('donations.json', 'utf8').catch(() => '{"since":null,"rows":{}}'));
  let newest = store.since;
  let page = 1;
  let lastPage = 1;

  do {
    const query = new URLSearchParams({ per_page: '100', page: String(page) });
    if (store.since) {
      // Go back one minute - overlapping windows are harmless because rows are upserted.
      query.set('since', new Date(Date.parse(store.since) - 60_000).toISOString());
    }

    const response = await fetch(`${API}/guild/donations?${query}`, { headers });
    const body = await response.json();
    if (!response.ok) throw new Error(body.error.code); // token_invalid = token revoked or leader changed

    for (const row of body.data) {
      store.rows[row.id] = row;
      if (!newest || Date.parse(row.updated_at) > Date.parse(newest)) newest = row.updated_at;
    }
    lastPage = body.meta.last_page;
    page++;
  } while (page <= lastPage);

  store.since = newest;
  await writeFile('donations.json', JSON.stringify(store, null, 2));
}

await sync();
setInterval(() => sync().catch(console.error), 10 * 60 * 1000);

Analiza mety: popularne klasy i bronie w czołówce

Dla kogo Autorzy poradników, teoretycy buildów, twórcy statystyk.

Cel Sprawdzić, jakimi broniami grają najlepsi i jakie przedmioty dominują w buildach czołówki.

Krok po kroku

  1. 1 Pobierz top 100 - pole weapon_type w każdym wpisie wystarcza do policzenia rozkładu klas bez dodatkowych zapytań. GET /api/v1/servers/s1/rankings/characters/arena?limit=100
  2. 2 Dla wybranych graczy pobierz profile i policz przedmioty w poszczególnych slotach. GET /api/v1/servers/s1/characters/{characterRef}

Wskazówki

  • Między profilami rób około sekundy przerwy, żeby zmieścić się w limicie 60 zapytań na minutę.
  • Profile prywatne i ukryte sekcje (hidden_sections) pomijaj w statystykach, zamiast traktować je jak zera.
  • Ranking arena pokazuje najlepszych w PvP, ranking level najdalej rozwinięte postacie - porównanie obu to ciekawy materiał.

Skrypt w Pythonie liczący rozkład klas i najpopularniejsze bronie

# Weapon types of the top 100 PvP players and the most popular weapons among the top 20 builds.
import collections
import time
import requests

API = "https://berserkrush.pl/api/v1/servers/s1"

top = requests.get(f"{API}/rankings/characters/arena", params={"limit": 100}, timeout=10).json()["data"]
print("Weapon types in top 100:", collections.Counter(hero["weapon_type"] for hero in top).most_common())

weapons = collections.Counter()
for hero in top[:20]:
    profile = requests.get(f"{API}/characters/{hero['id']}", params={"lang": "en"}, timeout=10).json()["data"]
    time.sleep(1.1)  # stay under 60 requests per minute
    if profile["build"] is None:  # private profile
        continue
    for piece in profile["build"]["equipment"]:
        if piece["slot"] == "main_hand":
            weapons[piece["item"]["name"]] += 1

print("Most popular weapons in top 20:", weapons.most_common(5))

Wyszukiwarka łupów: gdzie zdobyć przedmiot

Dla kogo Strony z poradnikami, boty, nakładki dla graczy.

Cel Po wpisaniu nazwy przedmiotu pokazać potwory i mapy, z których wypada.

Krok po kroku

  1. 1 Znajdź przedmiot po fragmencie polskiej nazwy. GET /api/v1/servers/s1/items?search=wilcza&per_page=1
  2. 2 Pobierz szczegóły przedmiotu - pole dropped_by zawiera potwory i ich mapy. GET /api/v1/servers/s1/items/{itemId}
  3. 3 Opcjonalnie pokaż całą mapę z potworami i najcenniejszymi łupami. GET /api/v1/servers/s1/maps/{mapId}

Wskazówki

  • Wyszukiwarka porównuje polskie nazwy (pole name_pl), a pole name zwraca nazwę w języku z parametru lang.
  • Pusta lista dropped_by oznacza, że przedmiotu nie upuszczają potwory - pochodzi np. ze skrzyń, od Kowala albo z handlu.
  • Dane katalogowe zmieniają się rzadko - możesz trzymać je u siebie nawet przez kilka godzin.

Funkcja w JavaScript

// "Where does it drop?" - finds an item by (Polish) name and lists the monsters and maps that drop it.
const API = 'https://berserkrush.pl/api/v1/servers/s1';

async function whereDoesItDrop(query) {
  const found = await fetch(`${API}/items?per_page=1&lang=en&search=${encodeURIComponent(query)}`).then(r => r.json());
  const item = found.data[0];
  if (!item) return `Nothing matches "${query}".`;

  const { data } = await fetch(`${API}/items/${item.id}?lang=en`).then(r => r.json());
  if (data.dropped_by.length === 0) return `${data.name}: not dropped by monsters (chests, crafting or trade).`;

  const sources = data.dropped_by.map(m => `${m.monster} (lvl ${m.level}${m.map ? ', ' + m.map.name : ''})`);
  return `${data.name}: ${sources.join('; ')}`;
}

whereDoesItDrop('wilcza').then(console.log);

Więcej pomysłów

  • Nakładka na stream (OBS): top 5 rankingu tygodniowego z odliczaniem do resetu z meta.resets_at.
  • Strona rekrutacyjna: lista gildii z trybem rekrutacji, minimalnym poziomem i liczbą wolnych miejsc.
  • Porównywarka postaci: dwa profile obok siebie, slot po slocie.
  • Automatyczne role na Discordzie gildii według ról ze składu gildii (endpoint z tokenem).
  • Przewodnik po mapach: mapa, jej potwory, bossowie i najcenniejsze łupy w jednym widoku.

Zbudowałeś coś ciekawego albo brakuje Ci danych w API? Napisz na naszym Discordzie.

Twoja Prywatność w Grze

Używamy plików cookie i narzędzi analitycznych (Google Analytics), aby analizować ruch, poprawiać działanie gry oraz zapewniać bezpieczną rozgrywkę.

Więcej informacji znajdziesz w naszej Polityce Prywatności .

Gra otwarta w przeglądarce

Wbudowana przeglądarka aplikacji ma ograniczoną pamięć i może powodować częstsze zacięcia oraz większe zużycie RAM. Dla płynnej rozgrywki otwórz grę w swojej normalnej przeglądarce.