api.lite.fi · v1
Lite.fi-tunnus pelikehittäjille
Näin peli liittyy yhteiseen kirjautumiseen ja Top 100 -listoihin. Pelit pysyvät staattisina: ne eivät koskaan näe OIDC-tokeneita, vain krypta_sid-evästeen, jonka selain lähettää automaattisesti.
Pikaohje
- Kopioi
krypta-id.jspelisi repoon (esim.js/krypta-id.js) — pelien CSP onscript-src 'self'. - Lisää CSP:hen
connect-src 'self' https://api.lite.fi(jaimg-src https://api.lite.fi, jos näytät avatarit). - Kirjautumislinkki:
https://api.lite.fi/login?return=https://mato.lite.fi/— ei popupeja. - Pelin lopuksi
KryptaID.submitScore('matopeli', 'klassikko', 1234).
Kirjasto krypta-id.js
<script src="js/krypta-id.js"></script>
const me = await KryptaID.me(); // null = ei kirjautunut
if (!me) loginLink.href = KryptaID.loginUrl(); // palaa tälle sivulle
else nameEl.textContent = me.nickname;
const r = await KryptaID.submitScore('tetris', 'klassikko', 48200, { level: 12 });
// r = { saved: true, best: 48200, previousBest: 30100, rank: 7, pending: false, ... }
const top = await KryptaID.leaderboard('tetris', 'klassikko', 10);
// top.entries = [{ rank: 1, nickname: 'Kalmo', avatar: 'kallo', score: 99100, at: 1761550000000 }, ...]
await KryptaID.myRank('tetris', 'klassikko'); // { score, rank, pending } tai null
KryptaID.avatarUrl(me.avatar); // https://api.lite.fi/avatars/kallo.svg
await KryptaID.logout();
Virheissä lupaus hylätään Error-oliolla, jolla on status ja data.error (esim. 401 unauthorized, 403 nickname_required, 429 too_frequent, 422 score_out_of_range). Devissä voit asettaa ennen kirjastoa window.KRYPTA_ID_BASE = 'https://krypta-api.dev.empor.fi'.
API
| Kutsu | Kuvaus |
|---|---|
GET /login?return=URL | Aloittaa Empor ID -kirjautumisen (myös tilin luonti). return hyväksytään vain sivustodomaineille (lite.fi,krypta.gg) ja niiden alidomaineille. Ensikertalainen valitsee nimimerkin ennen paluuta. |
GET /logout?return=URL | Uloskirjautumissivu (tai POST /api/logout). |
GET /api/me | { id, nickname, avatar, avatarUrl, needsNickname } tai 401. id on pysyvä julkinen tunniste (ei Empor ID:n sub). |
POST /api/scores | Runko { game, board?, score, meta? }. Säilyttää paras-tuloksen per (pelaaja, peli, lista). 201 = uusi ennätys, 200 = ei parantunut. Vaatii nimimerkin. meta ≤ 1 kt JSON-olio. |
GET /api/leaderboard?game=&board=&limit=100 | Julkinen, välimuisti 30 s. board puuttuu → pelin oletuslista. |
GET /api/leaderboard/me?game=&board= | Oma tulos ja sijoitus (kirjautunut). |
GET /api/users/:nickname | Julkinen profiili: { nickname, avatar, joined, scores: [{ game, board, score, rank, at }] }. |
GET /api/games | Pelit ja niiden listat, järjestys (desc/asc) ja muoto. |
GET /api/boards?game= | Pelin listat pelaajamäärineen (myös päivän listat). |
GET /api/daily?date=&limit=3 | Kaikkien pelien päivän kärki, ks. Päivän listat. |
/api/ideas | Ideat ja äänestys, ks. Ideat. |
/api/leagues | Liigat, ks. Liigat. |
wss://api.lite.fi/party | Bilemoodin huonevälitys, ks. Bilemoodi. |
POST /api/internal/verify-session | Palvelinten välinen, ks. Backend. |
Listat (board): pienet kirjaimet, numerot ja -, max 40 merkkiä, pelikohtainen regex. Päivän haaste: daily-YYYY-MM-DD (Suomen aikaa) — vastaanotetaan vain tänään ja eilen.
Päivän listat
- Jokaisella pelillä on päivän lista
daily-YYYY-MM-DD(Suomen aika). Lähetäboard: 'daily'(tai tarkka nimi):KryptaID.submitScore('maki', 'daily', 118.5). - Lista lukitaan vuorokauden vaihtuessa: vain kuluvan päivän listalle voi lähettää (muuten
422 board_closed). Pelaajalta säilyy päivän paras tulos. GET /api/daily?date=YYYY-MM-DD&limit=1..10(oletus tänään, 3) →{ date, board, open, games: [{ game, name, url, order, format, upcoming, players, entries: [{ rank, nickname, avatar, score, at }] }] }. Julkinen, välimuisti 30 s.
Ideat
GET /api/ideas?sort=votes|new&status=&limit=50&offset=0 | Julkinen. { ideas: [{ id, title, body, status, votes, author: { nickname, avatar } | null, createdAt, voted? }] }. voted vain kirjautuneelle. Hylätyt näkyvät vain status=hylatty-suodattimella. |
POST /api/ideas | Kirjautunut + nimimerkki. { title (3–80), body? (≤ 1000) }. Kirosana- ja linkkisuodatin (sivuston omat domainit saa mainita), 3 ideaa / vrk / käyttäjä (429 idea_limit). |
POST /api/ideas/:id/vote · DELETE …/vote | Yksi ääni per käyttäjä, peruttavissa. → { id, voted, votes } |
DELETE /api/ideas/:id | Tekijä voi poistaa oman idean, kun tila on vielä uusi. |
Tilat: uusi, tyon-alla, julkaistu, hylatty — ylläpito vaihtaa (myös piilotus/poisto).
Liigat
GET /api/leagues | Omat liigat { leagues: [{ id, name, code, isOwner, members }] } |
POST /api/leagues | { name (3–40) } → perustaja on omistaja ja jäsen. Max 20 liigaa / käyttäjä. |
POST /api/leagues/join | { code } (8 merkkiä, kirjainkoolla ei väliä). Max 500 jäsentä. 10 väärää koodia / 10 min → 429. |
GET /api/leagues/:id | Vain jäsenille (muille 404): nimi, koodi, jäsenet. |
GET /api/leagues/:id/leaderboard?game=&board=&week=YYYY-Www | Jäsenten viikon paras (ISO-viikko Suomen aikaa, oletus kuluva). Jokainen POST /api/scores päivittää viikon parhaan, vaikka kaikkien aikojen paras ei parantuisi. |
POST /api/leagues/:id/leave | Poistu. Omistajan lähtiessä omistajuus siirtyy vanhimmalle jäsenelle; viimeisen lähtiessä liiga poistuu. |
PATCH /api/leagues/:id · POST …/code · DELETE … · DELETE …/members/:nickname | Vain omistaja: nimeä, uusi koodi (vanha lakkaa toimimasta), poista liiga, poista jäsen. |
Bilemoodi (TV + puhelimet ohjaimina)
WebSocket wss://api.lite.fi/party. Palvelin vain välittää viestejä, mitään ei tallenneta eikä kirjautumista tarvita. Selaimen Origin pitää olla sallittu (ks. CORS). Kaikki viestit ovat JSON-tekstikehyksiä.
TV (host)
const ws = new WebSocket('wss://api.lite.fi/party?role=host&game=sirkus'
+ '&controller=' + encodeURIComponent('https://sirkus.lite.fi/ohjain'));
// ← { t: 'room', code: 'KXRT', key, game, joinUrl: 'https://sirkus.lite.fi/ohjain?room=KXRT',
// qr: 'https://api.lite.fi/api/party/qr/KXRT.svg', maxPlayers: 8, players: [] }
// ← { t: 'join', id: 'p1', name: 'Matti', rejoin? } ← { t: 'leave', id, reason }
// ← { t: 'msg', from: 'p1', d: { …ohjaimen data… } }
ws.send(JSON.stringify({ t: 'send', to: 'p1' /* tai 'all' */, d: { vibrate: 40 } }));
ws.send(JSON.stringify({ t: 'kick', id: 'p1' }));
ws.send(JSON.stringify({ t: 'close' })); // sulkee huoneen kaikilta
// Yhteys katkesi? Palaa samaan huoneeseen: ?role=host&code=KXRT&key=<key>
controller = pelin ohjainsivu (sallitulla domainilla); joinUrl ja QR-koodi osoittavat sinne ?room=-parametrilla. QR on SVG (<img src="…qr…">, lisää img-src https://api.lite.fi CSP:hen).
Puhelin (player)
const ws = new WebSocket('wss://api.lite.fi/party?role=player&code=KXRT&name=Matti');
// ← { t: 'welcome', id: 'p1', key, name, game, hostConnected } (tallenna id + key sessionStorageen)
ws.send(JSON.stringify({ x: 0.42, btn: 'A' })); // mikä tahansa JSON ≤ 256 tavua → TV:lle
// ← { t: 'msg', from: 'host', d } ← { t: 'host-away' } / { t: 'host-back' } ← { t: 'error', error: 'too_large' }
// Palaa samaksi pelaajaksi: ?role=player&code=KXRT&id=p1&key=<key>
- Rajat: max 8 pelaajaa, pelaajan viesti ≤ 256 t ja ≤ 30 viestiä/s (ylimenevät pudotetaan, jatkuva tulva katkaisee), huone vanhenee 2 h toimettomana. Nimi ≤ 16 merkkiä, kirosanat korvataan ("Pelaaja N").
- Sulkemiskoodit:
4000vanhentui,4001host sulki,4002korvattu uudella yhteydellä,4003potkittu,4400virheellinen pyyntö,4401väärä avain,4404huonetta ei ole,4409täynnä,4429liikaa. - Palvelin pingaa 25 s välein; selain vastaa automaattisesti.
CORS & CSRF
- Sallitut originit:
https://<domain>jahttps://<alidomain>.<domain>, domainitlite.fi,krypta.gg(tasan yksi alidomain-taso, vain https, ei porttia) + palvelun omat osoitteet. VastauksessaAccess-Control-Allow-Credentials: true. - Kirjoittavat kutsut (
POST/PATCH/DELETE) vaativat sallitunOrigin-otsakkeen ja otsakkeenX-Krypta: 1(pakottaa preflightin). Kirjasto hoitaa tämän. - Eväste
krypta_sid:Domain=.lite.fi; Path=/; HttpOnly; Secure; SameSite=Lax, 30 pv liukuva. Pelien fetchit ovat samaa sivustoa (same-site), joten eväste kulkeecredentials: 'include'-asetuksella. - Rate limit: 30 tulosta / min / pelaaja + pelikohtainen vähimmäisväli ja tuntiraja.
Huijaussuoja — rehellisesti
Selaimesta lähetetty tulos on aina väärennettävissä. Palvelin tekee sen minkä voi: pelikohtaiset ylä- ja alarajat (yli → 422), lähetystiheyden rajat, ja epäilyttävän suuret (tai miinaharavassa pienet) tulokset liputetaan: ne piilotetaan listoilta, kunnes ylläpito hyväksyy ne. Pelaaja näkee oman tuloksensa merkinnällä "tarkistettavana". Rajat ovat tiedostossa games.config.json — uusi peli tarvitsee sinne rivin.
Pelin oma backend (esim. roguelike)
POST https://api.lite.fi/api/internal/verify-session
X-Krypta-Service-Key: <avain .env.krypta-api:n SERVICE_KEYS-listalta>
Content-Type: application/json
{ "sid": "<krypta_sid-evästeen arvo>" }
→ { "valid": true, "user": { "id": "k3x9…", "nickname": "Kalmo", "avatar": "kallo" } }
→ { "valid": false }
Backend lukee krypta_sid-evästeen omasta pyynnöstään (eväste on koko .lite.fi:lle) ja varmistaa sen tällä. Tallenna linkiksi user.id. Avain annetaan ylläpidolta, eikä sitä koskaan laiteta selaimeen.