🎮 Coop Tracker — API

REST, risposte JSON, percorsi sotto /api. Documentazione aggiornata a mano insieme al codice.

Autenticazione

Due modi, equivalenti su quasi tutte le rotte:

1. Sessione browser — cookie tg_session (HttpOnly), creato da login o registrazione. È quello che usa l'app.
2. Chiave API — header Authorization: Bearer ct_…. Le chiavi si generano dal profilo nell'app (max 5 a testa), si vedono in chiaro solo alla creazione e agiscono con i permessi di chi le ha create.
Le rotte marcate solo sessione rifiutano le chiavi API (403): una chiave trafugata non può coniarne altre né auto-revocarsi. Anti-bruteforce: 20 chiavi sbagliate in 15 minuti per IP → 429.
# esempio: lo stato completo del gruppo
curl -H "Authorization: Bearer ct_LATUACHIAVE" https://pc-federico.tailb6c9bf.ts.net/api/data

# esempio: dichiara interesse per un gioco
curl -X POST -H "Authorization: Bearer ct_LATUACHIAVE" -H "Content-Type: application/json" \
     -d '{"v":true}' https://pc-federico.tailb6c9bf.ts.net/api/games/289650/interest
pubblica auth = sessione o chiave API solo sessione admin codice monouso

Accesso e account

GET/api/healthpubblicaping: {ok, name}
GET/api/auth/configpubblicacosa è attivo (login Steam, registrazione)
POST/api/auth/registerpubblica{username, password, inviteCode} → imposta il cookie. Rate-limited
POST/api/auth/loginpubblica{username, password} → imposta il cookie. Rate-limited
POST/api/auth/logoutauthbrucia la sessione corrente
GET/api/auth/steampubblicaredirect al login OpenID di Steam (solo browser; serve la whitelist)
GET/api/auth/steam/returnpubblicaritorno OpenID, verifica firma e audience

Dati

GET/api/dataauthlo stato completo: me, users (sanitizzati), games (con verdetti compat per macchina, gfn, cloudPlayers, players max giocatori), activity; settings solo se admin
GET/api/steam/search?q=…authricerca sullo store Steam (min 2 caratteri)

Giochi

POST/api/gamesauth{appid} — propone un gioco; notifica il gruppo
DEL/api/games/:appidauthsolo chi l'ha proposto o admin; finisce tra gli «ignorati» (niente re-import da wishlist)
POST/api/games/:appid/refreshauthriscarica prezzo/dati da Steam (e max giocatori da PCGamingWiki se stantio)
POST/api/games/:appid/watchauthtoggle «seguito»
POST/api/games/:appid/ownauthtoggle «ce l'ho»
POST/api/games/:appid/playableauth{v: true|false|null} — «mi gira» dichiarato, vince sulle stime
POST/api/games/:appid/voteauth{v: -1|0|1} — da comprare insieme?
POST/api/games/:appid/interestauth{v: true|false|null} — risposta a «Ti interessa?»; il sì notifica il gruppo
POST/api/games/:appid/playersauth{online: 1–128 | null} — tetto giocatori; null torna al dato automatico (PCGamingWiki)
POST/api/games/:appid/modmpauth{name, url?, maxPlayers?} — attiva una mod co-op su un single-player (entra nella logica serata); {off: true} disattiva. Le mod note arrivano in modMpKnown su /api/data
POST/api/games/:appid/feedsauth{url, label?} — segue un feed RSS/Atom pubblico (solo https, niente indirizzi interni). Il primo scaricamento fa da base: nessuna notifica per le voci già presenti. Max 5 per gioco
POST/api/games/:appid/feeds/:fid/checkauthcontrollo immediato (al massimo ogni 10 minuti per feed) → {game, fresh}
DEL/api/games/:appid/feeds/:fidauthsmette di seguire il feed: chi l'ha aggiunto o admin
POST/api/games/:appid/alertauth{priceEUR: number | null} — soglia prezzo personale
POST/api/games/:appid/commentsauth{text} — le @menzioni notificano
DEL/api/games/:appid/comments/:cidauthautore o admin
POST/api/games/:appid/videosauth{url} — YouTube / TikTok / Instagram
DEL/api/games/:appid/videos/:vidauthautore o admin

Macchine

POST/api/me/machinesauth{name, cpu, gpu, ramGB, os, notes} — crea (o aggiorna se il nome coincide)
PUT/api/me/machines/:idauthmodifica
DEL/api/me/machines/:idauthelimina
PUT/api/me/machines/orderauth{ids: […]} — l'ordine è la preferenza, la prima è la principale
POST/api/me/machines/:id/primaryauthporta in cima
GET/api/hw/check?gpu=…&cpu=…authriconoscimento componenti e punteggio (benchmark reale o stima)
GET/api/hw/knownauthcomponenti riconosciuti
POST/api/hw/pairauthgenera il codice monouso (10 min) per lo script di rilevamento
GET/api/hw/agent.ps1?code=…codice monousolo script PowerShell personalizzato
POST/api/hw/report?code=…codice monousoupsert della macchina rilevata (match sul nome). Rate-limited

Profilo, Steam e notifiche

PUT/api/me/profileauth{displayName?, oldPassword?, newPassword?}
POST/api/me/steamauth{profile} (url o vanity) — collega il profilo; non abilita il login Steam (serve l'OpenID)
DEL/api/me/steamauthscollega
POST/api/me/steam/syncauthsincronizza i posseduti dalla libreria (aggiunge, non toglie mai)
POST/api/me/steam/wishlist-importauthimporta la wishlist come proposte (salta DLC e ignorati)
PUT/api/me/notificationsauth{prefs: {serata?, price?, release?, newGame?, comments?, members?, mentions?, feeds?}} booleani

Chiavi API

GET/api/me/keyssolo sessionele tue chiavi: nome, prefix, creata, ultimo uso (mai l'hash)
POST/api/me/keyssolo sessione{name} → {key, meta} — la chiave in chiaro esiste solo in questa risposta. Max 5
DEL/api/me/keys/:idsolo sessionerevoca immediata

Notifiche push

GET/api/push/keyauthchiave VAPID pubblica
POST/api/push/subscribeauth{subscription: PushSubscription} — registra il dispositivo (sostituisce per endpoint), manda il benvenuto
POST/api/push/unsubscribeauth{endpoint}
POST/api/push/testauthnotifica di prova ai tuoi dispositivi

Admin

PUT/api/settingsadmin{steamApiKey?, inviteCode?, steamWhitelist?}
POST/api/users/steam-addadmin{profile} — pre-aggiunge un membro dal profilo Steam (entrerà col login Steam)
DEL/api/users/:idadminrimuove un membro e ne ripulisce le tracce

Errori

Sempre JSON: {"error": "messaggio leggibile"}. Codici usati: 400 input non valido, 401 non autenticato, 403 permessi insufficienti, 404 non trovato, 409 conflitto (duplicati), 429 rate limit.

Coop Tracker · il radar multiplayer del gruppo · torna all'app