Playbox Organizer API
Čitaj podatke o svojim utakmicama, ligama i mečevima iz svoje skripte ili sa servera: ko je igrao i kako je platio, tabele, strelci, golovi, kartoni i svetli trenuci. Samo za čitanje, samo tvoji podaci.
Osnovni URL: https://app.play-box.xyz/api/organizer/v1/
Prvi zahtev za 5 minuta
- Nabavi ključ. U aplikaciji Playbox otvori Podešavanja → Alati organizatora → API ključevi → Napravi ključ. Daj ključu naziv i označi „Slažem se sa API uslovima“. Ključ izgleda kao
pbo_xxxxxxxx.long-secreti prikazuje se samo jednom. Sačuvaj ga u promenljivim okruženja na svom serveru. - Proveri vezu.
curl -H "X-Api-Key: $PLAYBOX_KEY" https://app.play-box.xyz/api/organizer/v1/me/
Odgovor 200 vraća tvoje korisničko ime, naziv ključa i datum do kog ključ važi.
- Preuzmi svoje utakmice.
curl -H "X-Api-Key: $PLAYBOX_KEY" "https://app.play-box.xyz/api/organizer/v1/events/?from=2026-09-01&status=FINISHED"
Ključ
- Ključ je lični: deluje u tvoje ime i vidi samo tvoje podatke.
- Ključ važi 365 dana. Podsetnik dobijaš 14 i 3 dana pre isteka (push, Telegram, mejl). Posle toga API odgovara
key_expired: napravi novi ključ i zameni ga na svom serveru. - Možeš da imaš najviše 5 aktivnih ključeva. Ključ koji ne koristiš ili koji je procureo opozovi bilo kada, prestaje da radi odmah.
- Šalji ključ u zaglavlju
X-Api-Key: pbo_...(iliAuthorization: Api-Key pbo_...). Ključ u URL-u se ne prihvata, jer bi završio u logovima. - Samo sa servera. Zahtev iz pregledača (sa zaglavljem
Origin) dobija403 browser_not_allowed: ključ unutar veb stranice vidi svaki posetilac. - Ključ ne otvara aplikaciju, a sesija u aplikaciji ne otvara ovaj API.
Šta se računa kao tvoji podaci
- utakmice koje organizuješ, koje si kreirao, za koje primaš novac ili kojima upravljaš;
- lige koje si kreirao ili u kojima si administrator, i sve njihove utakmice;
- utakmice povezane sa zajednicom čiji si vlasnik ili administrator (uključujući utakmice koje je kreirao suorganizator).
Tuđa utakmica ili liga vraća 404, isto kao ona koja ne postoji. Kontakti i fotografije igrača se nikada ne vraćaju.
Ograničenja
60 zahteva u minuti po ključu. Zahtev je jedan poziv bilo kog URL-a API-ja sa važećim ključem, uključujući odgovore 404 i 400. Prozor se resetuje na početku svakog minuta.
| Zaglavlje odgovora | Značenje |
|---|---|
X-RateLimit-Limit | ograničenje po minutu |
X-RateLimit-Remaining | preostali zahtevi u tekućem minutu |
X-RateLimit-Reset | sekundi do resetovanja prozora |
Retry-After | samo kod 429: koliko sekundi da sačekaš pre ponovnog pokušaja |
Čuvaj podatke kod sebe i preuzimaj samo ono što je novo: skorašnje utakmice preko from i mečeve završenih utakmica. Ako svaki put kada se tvoj sajt otvori ponovo preuzimaš celu istoriju, ograničenje ćeš dostići za nekoliko sekundi.
Greške
Svaka greška ima isti oblik. Granaj logiku po code, a message upiši u svoj log.
{"error": {"code": "invalid_parameter", "message": "from: Use YYYY-MM-DD.", "fields": {"from": "Use YYYY-MM-DD."}}}
| HTTP | code | Šta da uradiš |
|---|---|---|
| 401 | not_authenticated | nedostaje zaglavlje sa ključem |
| 401 | invalid_key | ključ je pogrešan ili opozvan, napravi novi |
| 401 | key_expired | ključ je istekao, napravi novi |
| 403 | browser_not_allowed | zahtev je stigao iz pregledača, pozivaj API sa svog servera |
| 404 | not_found | objekat ne postoji ili nije tvoj |
| 400 | invalid_parameter | parametar je pogrešan, detalji su u fields |
| 405 | method_not_allowed | API je samo za čitanje, koristi GET |
| 429 | rate_limited | sačekaj retry_after sekundi |
Format podataka
- Vreme je uvek u UTC, ISO 8601. Novac stiže kao par:
{"amount": 800.0, "currency": "RSD"}. - Liste (
leagues/,events/) su podeljene na stranice:?limit=50&offset=0,limitdo 100. Odgovor je{"count", "limit", "offset", "next_offset", "results"}, anext_offset: nullznači poslednju stranicu. - Igrač:
{"id", "username", "is_guest", "url"}.is_guest: trueje zajednički gostujući nalog koji se koristi za golove igrača bez profila: oni se računaju u rezultat meča, ali ne i u ličnu statistiku. - Linkovi. Utakmice, mečevi, lige i igrači imaju
urlka svojoj stranici na Playboxu. Koristi ga kada prikazuješ podatke na svom sajtu: na stranici su kompletna statistika i video.
Endpointi
GET /me/
Čiji je ovo ključ: korisnik, naziv ključa, datum isteka, verzija uslova, ograničenja.
GET /leagues/
Tvoje lige: id, slug, name, status (active, finished, archived), format, city, date_start, date_end, teams_count, price, game_price, url.
GET /leagues/{id}/
Liga i njena pravila: tehnički poraz, disciplina (limit žutih kartona, suspenzije), veličina sastava.
GET /leagues/{id}/table/
Tabela u istom redosledu kao u aplikaciji: position, team, played, wins, draws, losses, goals_for, goals_against, goal_difference, points.
GET /leagues/{id}/players/
Tabela igrača: player, team, position, games, goals, assists, yellow_cards, red_cards, suspension_games_left. Sortirano po golovima, pa po asistencijama.
GET /leagues/{id}/rosters/
Sastavi timova: svaki tim sa svojim igračima i datumom kada su dodati.
GET /events/
Tvoje utakmice, od najnovije. Filteri: from, to (YYYY-MM-DD po datumu početka, UTC), status (NOT_STARTED, STARTED, FINISHED, CANCELLED), league (id), format (igrača po timu, na primer 8). Polja: id, league_id, starts_at, ends_at, status, results_status, format, venue, is_paid, price, price_per_player, capacity, players_count, teams_count, is_ranked, is_private, url.
GET /events/{id}/
Cela utakmica: timovi (boja, pobede, nerešeno, porazi, sastav), mečevi sa rezultatom i url, mvp_player_id, YouTube snimci, prenosi uživo.
GET /events/{id}/participants/
Ko se prijavio i kako je platio: player, status (In game, Late, Did not come, Invited), team_id, joined_at, payment_method (CASH, WALLET, CARD, STRIPE, APPLE_PAY, GOOGLE_PAY, TELEGRAM), paid, payment_confirmed, paid_by, amount, is_early_bird. Ovi podaci su samo za tebe: nemoj da ih objavljuješ.
GET /events/{id}/player-stats/
Rezultat svakog igrača na utakmici: wins, draws, losses, goals, assists, goals_conceded, yellow_cards, red_cards, rating, rating_change, is_confirmed. Dostupno kada se utakmica završi.
GET /matches/{id}/
Ceo meč: event_id, league_id, number, tour, starts_at, ends_at, state, teams, score, technical_defeat, referee, video_url, url, vremenska linija timeline, izvođenje penala penalty_shootout, postave lineups (ko je počeo, sekunde na terenu) i svetli trenuci highlights (kao YouTube linkovi).
"timeline": [
{"type": "period", "half": 1, "is_extra_time": false, "started_at": "...", "ended_at": "...", "duration_seconds": 1200},
{"type": "goal", "game_time_seconds": 305, "team_id": 1, "player": {}, "assistant": {}, "is_own_goal": false, "youtube_url": "..."},
{"type": "card", "game_time_seconds": 700, "team_id": 2, "player": {}, "card": "YELLOW", "reason": "Dissent"},
{"type": "substitution", "game_time_seconds": 900, "team_id": 2, "player_out": {}, "player_in": {}, "until_end": true}
]
- Tipovi događaja:
period,goal,card,substitution,player_added,player_removed. Poluvremena 3 i 4 su produžeci. - Autogol (
is_own_goal: true) se upisuje timu kome se računa. - Kod tehničkog poraza
scoreje dosuđeni rezultat, a razlog i rezultat su utechnical_defeat.
Primeri
Python
import os, requests
API = "https://app.play-box.xyz/api/organizer/v1"
session = requests.Session()
session.headers["X-Api-Key"] = os.environ["PLAYBOX_KEY"]
def fetch_all(path, **params):
offset = 0
while offset is not None:
page = session.get(f"{API}/{path}", params={**params, "offset": offset, "limit": 100}).json()
yield from page["results"]
offset = page["next_offset"]
for event in fetch_all("events/", status="FINISHED", **{"from": "2026-09-01"}):
detail = session.get(f"{API}/events/{event['id']}/").json()
for match in detail["matches"]:
print(event["starts_at"], match["score"], match["url"])
JavaScript (Node 18+, na serveru)
const API = "https://app.play-box.xyz/api/organizer/v1";
const headers = { "X-Api-Key": process.env.PLAYBOX_KEY };
const res = await fetch(`${API}/leagues/8/players/`, { headers });
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${error.code}: ${error.message}`);
}
const { results } = await res.json();
console.log(results.slice(0, 10).map(r => `${r.player.username}: ${r.goals}`));
Uslovi korišćenja (verzija 2026-10-01)
- Koristi podatke iz API-ja samo za vođenje svojih utakmica, liga i zajednice.
- Ne objavljuj plaćanja, iznose, načine plaćanja, statuse dolazaka ni fotografije igrača. Sportsku statistiku (rezultate, golove, asistencije, tabele) možeš javno da prikazuješ.
- Ne deli i ne prodaj podatke trećim licima.
- Ne primaj rezervacije ni plaćanja za utakmice van Playboxa.
- Kada javno prikazuješ podatke, navedi izvor kao „Data by Playbox“ sa linkom ka Playboxu.
- Čuvaj ključ na svom serveru i nikada ga ne deli. Ako procuri, odmah ga opozovi.
- Ako prekršiš ove uslove, ključ ti se opoziva. Posle opoziva izbriši sve sačuvane lične podatke igrača.
Verzije
Verzija je u URL-u (v1). Nova polja mogu da se pojave u odgovorima bez promene verzije, zato nemoj da prijavljuješ grešku na nepoznata polja. Uklanjanje ili preimenovanje polja desiće se samo u v2, a v1 će nastaviti da radi.
- 2026-10-02, v1. Prvo izdanje: lige, utakmice, učesnici, mečevi, linkovi ka Playboxu, trajanje ključa, uslovi, zaglavlja za ograničenje broja zahteva, jedinstven format grešaka.