The Data API: Public Read-Only Access
What the public Data API is, the resources it exposes, and how it differs from the tournament-management endpoints described elsewhere in these docs.
Everywhere else in these docs, "the API" means the tournament-management surface — the endpoints organizers and players use to run check-in, seed brackets, and report results, authenticated with a user's access token. The Data API is a separate, narrower surface: a licensed, read-only feed of the same underlying esports data, meant for integrations that consume tournament activity rather than manage it.
If you're building a stats site, a spectator dashboard, or an internal reporting tool, this is the surface you want.
What it is
The Data API is mounted at /api/v1/data/* and covers exactly these resources:
- Tournaments — list, retrieve by id or slug, and fetch a tournament's bracket
- Matches — retrieve a match, list matches within a tournament, and pull a match's normalized event feed
- Player stats — a player's per-game statistics
- Teams — retrieve a team by id
There is no create, update, or delete operation anywhere on this surface. Tournament creation, participant registration, check-in, seeding, and match result reporting all remain organizer- or player-authenticated actions performed through the dashboard or the tournament-management API — never through a Data API key. If you're looking for those flows, see Tournaments, Participants, and Matches.
Authentication and scopes
Like the rest of the public API, the Data API is authenticated with a project-scoped API key sent in the X-API-Key header — never a user access token:
curl https://api.tournamentsuite.com/api/v1/data/tournaments \
-H "X-API-Key: YOUR_API_KEY"Each endpoint requires one specific read scope:
| Scope | Grants |
|---|---|
read:tournaments | Tournaments and brackets |
read:matches | Matches and the match-event feed |
read:player_stats | Player per-game stats |
read:teams | Team details |
Grant a key only the scopes your integration actually uses. See Scopes for the full scope catalog, including the separate write-scoped anti-cheat surface covered in Anti-Cheat Integration API.
Plan entitlement gate
Beyond authentication and scopes, every Data API request is gated on your project's subscription plan: the plan must include the Developer API capability. A key with the correct scope on a plan without that capability still receives a 403 Forbidden — check your plan tier in the organizer dashboard before assuming a key or its scopes are misconfigured.
Its own rate-limit tier
The Data API is metered on its own per-minute request budget, separate from the platform's general request throttle and separate from any per-key rate limit an organizer configures manually. All three checks apply independently — hitting any one of them returns 429 Too Many Requests. See Rate Limits for the general throttle and per-key override behavior.
Response envelope
Every Data API response — success or list — uses the same envelope:
{
"success": true,
"data": { },
"message": "Tournaments retrieved successfully"
}data holds the resource or list payload; its shape varies by endpoint, but success and message are always present. See Endpoint Catalog for the full request/response reference per endpoint.
Realtime stream: the live complement to webhooks
Polling the Data API works, but for lower-latency updates you can instead open a Socket.IO connection to the /data-stream namespace using the same API key — this is the realtime counterpart to Webhooks, not a replacement for them. Use webhooks when you want your own endpoint notified server-side; use the data stream when a connected client needs updates pushed to it directly.
Opening a subscription requires the stream:match_events scope on the key:
import { io } from "socket.io-client";
const socket = io("https://api.tournamentsuite.com/data-stream", {
auth: { apiKey: "YOUR_API_KEY" },
});
socket.emit("subscribe", { matchId: "match-uuid" });
// or: socket.emit("subscribe", { tournamentId: "tournament-uuid" });
socket.on("data:event", (event) => {
// event.matchId, event.tournamentId, event type and payload
});You can subscribe to a specific match, a specific tournament, or both on the same connection. A connection without the required scope is rejected with an unauthorized error at handshake time; a subscribe call missing the scope receives an error event instead of joining the room.
First-party TypeScript SDK
TournamentSuite publishes a lightweight, dependency-light TypeScript SDK that wraps both the REST endpoints and the realtime stream, so you don't have to hand-roll request headers or socket auth:
import { DataApiClient, DataStreamClient } from "@tournamentsuite/data-api-sdk";
const api = new DataApiClient("https://api.tournamentsuite.com", "YOUR_API_KEY");
const { data } = await api.getTournaments({ gameId: "cs2", limit: 20 });
const stream = new DataStreamClient("https://api.tournamentsuite.com", "YOUR_API_KEY");
stream.subscribe({ matchId: "match-uuid" }, (event) => {
console.log(event.matchId, event.tournamentId);
});DataApiClient covers every Data API endpoint (tournaments, brackets, matches, match events, player stats, teams) using the global fetch, and throws a typed error carrying the response status and parsed error body on any non-2xx response. DataStreamClient wraps the /data-stream namespace connection and subscription handling shown above.
Where to go next
- Quick Start — make your first Data API request
- Endpoint Catalog — full endpoint reference
- Scopes — the complete scope catalog
- Webhooks — the server-side alternative to the realtime stream
- Anti-Cheat Integration API — the one write-capable part of the public API