API pubbliche, di sola lettura, per integrare Racepulse con un applicativo esterno (web o desktop) che deve importare e gestire eventi, intermedi e tempi registrati.
https://racepulse.cc/api/export
Nessuna. Questi endpoint sono pubblici, come il resto dell'app. Sono pensati per dati di gara non sensibili (pettorali e orari di passaggio) — non vengono esposte informazioni personali.
JSON per integrazioni programmatiche, CSV per import diretto in fogli di calcolo o gestionali.
/api/export/eventsElenca gli eventi.
| Parametro | Valori | Default | Descrizione |
|---|---|---|---|
archived | 0 · 1 | 0 | 1 per ottenere gli eventi archiviati invece di quelli attivi |
Risposta 200 — array di eventi:
[
{
"id": 12,
"nome": "Maratona di Prova",
"creato_il": "2026-08-10T09:00:00.000Z",
"chiuso": false,
"archiviato": false,
"num_intermedi": "3"
}
]
num_intermedi arriva come stringa (limite del driver Postgres sui valori COUNT) — convertila a numero lato client se ti serve un tipo numerico.
/api/export/events/:idRestituisce un evento completo: anagrafica, intermedi (checkpoint) e tutti i tempi registrati in ciascuno, in un'unica chiamata.
{
"id": 12,
"nome": "Maratona di Prova",
"creato_il": "2026-08-10T09:00:00.000Z",
"chiuso": false,
"archiviato": false,
"intermedi": [
{
"id": 30,
"nome": "10km",
"ordine": 1,
"chiuso": false,
"tempi": [
{
"id": 501,
"sequenza": 1,
"giorno": 1,
"orario_ms": 605000,
"orario": "00:10:05.000",
"tipo": "atleta",
"pettorale": "101",
"nota": null,
"incerto": false,
"squalificato": false,
"nota_squalifica": null
}
]
}
]
}
Campi di un "tempo":
| Campo | Tipo | Descrizione |
|---|---|---|
id | numero | id univoco del tempo registrato |
sequenza | numero | posizione progressiva (1, 2, 3…), calcolata separatamente per i tempi gun e per tutti gli altri (atleta/custom) nello stesso intermedio |
giorno | numero | giorno reale in cui il tempo è stato registrato, relativo al primo giorno dell'evento (1 = giorno della primissima scansione, 2 = giorno successivo…). Garantisce l'ordine cronologico corretto anche a cavallo di mezzanotte |
orario_ms | numero | orario del passaggio, in millisecondi dal riferimento dell'intermedio (gun/orologio) |
orario | stringa | lo stesso orario, già formattato HH:MM:SS.mmm |
tipo | stringa | atleta (passaggio con pettorale), gun (sparo di partenza), custom (tasto personalizzato) |
pettorale | stringa · null | numero pettorale, se applicabile |
nota | stringa · null | nota libera sul passaggio |
incerto | booleano | tempo marcato come incerto dall'operatore |
squalificato | booleano | il pettorale è squalificato/DNF su questo passaggio |
nota_squalifica | stringa · null | motivo della squalifica, se presente |
Errori: 404 se l'evento non esiste.
/api/export/events/:id/csvCome sopra, ma come file CSV scaricabile con tutti i tempi dell'evento (tutti gli intermedi in un'unica tabella piatta).
Risposta 200 — Content-Type: text/csv, Content-Disposition: attachment; filename="<nome-evento>.csv"
Colonne: intermedio, sequenza, giorno, orario, millisecondi, tipo, pettorale, nota, incerto, squalificato, nota_squalifica
Errori: 404 se l'evento non esiste.
# elenco eventi attivi
curl https://racepulse.cc/api/export/events
# evento completo in JSON
curl https://racepulse.cc/api/export/events/12
# evento completo in CSV, salvato su file
curl -o evento.csv https://racepulse.cc/api/export/events/12/csv
// polling periodico da un'app esterna, per dati "quasi live"
async function pollEvento(eventoId) {
const res = await fetch(`https://racepulse.cc/api/export/events/${eventoId}`);
if (!res.ok) throw new Error(`Errore ${res.status}`);
return res.json();
}
I dati riflettono lo stato attuale del database: non c'è alcuna cache, ogni chiamata legge dal vivo. Va bene per il polling periodico, ma evita di interrogare più volte al secondo senza motivo.
Un intermedio chiuso non riceve più nuovi tempi, ma quelli già registrati restano interrogabili come sempre.
I campi id (di eventi/intermedi/tempi) sono stabili e possono essere usati come chiave per sincronizzare i dati con un sistema esterno.
Non è previsto alcun webhook/push: l'app esterna deve interrogare gli endpoint quando le servono dati aggiornati.