APEXON API PLATFORM
LineSnap API documentation
Near-real-time multi-sport live scores and in-play board odds. Poll the REST endpoints or hold open an SSE stream that sends one full frame and then deltas.
live.apexon.dev is not serving traffic yet — subscribe to be told when it is.
https://live.apexon.dev
- Multi-sport board — soccer, tennis, basketball and the rest of the in-play board, with clock, status, and last incident.
- Board odds — mainlines or the full board, in your choice of odds format.
- Forward history — a change log per event from the moment it is first seen.
Quickstart
Every /v1 route needs a key. Health is public.
curl "https://live.apexon.dev/v1/live?sport=soccer&limit=5" \ -H "X-API-Key: $LINESNAP_KEY"
curl "https://live.apexon.dev/v1/odds?mainlines_only=true&odds_format=decimal&limit=5" \ -H "X-API-Key: $LINESNAP_KEY"
Authentication
LineSnap issues its own keys, prefixed ls_. A FinMarkets key will not work here, and vice versa — the products are metered separately.
| Method | How | Use when |
|---|---|---|
X-API-Key header | X-API-Key: <key> | The recommended default. |
| Bearer token | Authorization: Bearer <key> | Clients that standardize on Authorization. |
| Query param | ?api_key=<key> | Quick tests only — keys in URLs end up in logs. |
/health, /docs and /redoc are public; everything under /v1 requires a key.
Streaming
GET /v1/stream is a Server-Sent Events endpoint. It sends one full frame on connect, then deltas — so a long-lived connection stays KB-scale rather than re-sending the board every tick. Pass kinds to choose feeds and delta=true to enable delta frames; full_every forces a periodic resync frame.
curl -N "https://live.apexon.dev/v1/stream?kinds=live,odds&delta=true" \ -H "X-API-Key: $LINESNAP_KEY"
Stream connections are budgeted separately from ordinary requests, so a reconnect loop cannot exhaust your whole per-minute allowance.
Errors & limits
Errors return JSON with a stable error code. Rate limiting is per key, per minute, and every response carries your position against it.
| Status | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing or invalid key. |
| 403 | plan_upgrade_required | Endpoint not included in your plan — see required_plan. |
| 429 | rate_limited | Per-minute limit exceeded — honor Retry-After. |
| 429 | quota_exceeded | Monthly/daily plan quota exhausted — honor Retry-After. |
| 503 | — | Collector cache missing/unavailable; retry shortly. Stale data is not a 503 — see below. |
Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-Plan; a 429 adds Retry-After. Per-minute allowances scale with your plan. Stale data is served as a normal 200 with a top-level stale boolean and data_age_s (seconds since the last real feed activity), not a 503.
Scope & freshness
What this data is, stated plainly, so you can judge whether it fits your product:
- Public in-play board — not official league data, and not an official bookmaker feed.
- Board markets — mainlines and what the board publishes, not a full coupon.
- Forward-only history — the change log starts at first sighting; there is no multi-year backfill.
- Lineups are best-effort — XI and play-by-play appear only when the feed publishes them.
GET /health reports cache age plus data_age_s and a stale flag (based on real feed receipt, not the collector heartbeat), and GET /v1/meta/latency reports process-wide emit-to-serve percentiles (operator telemetry across all keys, not a per-key measurement), so freshness is measurable rather than claimed. Nothing here is betting advice.
Endpoint reference
Path parameters are shown in braces; query parameters list their defaults where one exists.
Meta
| Endpoint | Query params | Notes |
|---|---|---|
GET/health | — | Liveness, cache age, and per-sport event counts. Public. |
GET/v1/sports | — | Sports currently present on the board. |
GET/v1/fields | — | Field dictionary for live and odds payloads. |
GET/ | — | Service descriptor. |
Live scores
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/live | sport · q · limit=200 · raw=True | In-play board across all sports. |
GET/v1/live/{sport} | q · limit=200 · raw=True | In-play board for one sport (soccer, tennis, basketball, …). |
Odds
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/odds | q · fi · limit=100 · mainlines_only=False · odds_format=all | Board odds across fixtures; mainlines or full board. |
GET/v1/odds/{key} | mainlines_only=False · odds_format=all | Board odds for a single fixture key. |
Events
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/event/{event_id} | raw=True · odds=True | One event with optional raw payload and odds. |
History & archive
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/archive/stats | — | Archive size and coverage counters. |
GET/v1/archive/events | sport · status · q · limit=50 · offset=0 | Archived events, filterable by sport and status. |
GET/v1/history/{event_id} | since · kind · limit=500 | Change log for one event, forward from first sighting. |
GET/v1/archive/recent | sport · kind · limit=50 | Most recent archived changes. |
Streaming
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/stream | sport · interval_ms=50 · raw=False · kinds=live · delta=True · full_every=60 | SSE stream: one full frame, then deltas. |
Diagnostics
| Endpoint | Query params | Notes |
|---|---|---|
GET/v1/meta/latency | — | Emit→serve latency percentiles, process-wide (all keys). |