Developer Platform

Open Scoreboard API

Technical documentation for the current v1 REST API, with copyable examples, route-by-route notes, and authenticated personal API key management.

Public developer docs

Broadcasts

Create and manage reusable broadcast workspaces, their managed courts, linked rosters, and scoreboard outputs.

Available in v1

Broadcast endpoints use the same account-owned model as the management app. Creating a broadcast creates its courts and hidden output routing records; callers work with court names and scoreboard IDs rather than dynamic URLs.

Scopesbroadcasts.read / broadcasts.write
CollectionGET / POST /broadcasts
ResourceGET / PATCH / DELETE /broadcasts/{id}

Implementation notes

  • Each create request must include at least one court in tables.
  • scoreboardIDs must reference scoreboards owned by the connected account; omit them to use the default output.
  • Deleting a broadcast removes broadcast-managed courts and output routing records but does not delete reusable scoreboards or player lists.

Endpoints

OpenAPI
GET/broadcasts

List broadcasts

List account-owned broadcasts with optional cursor pagination.

broadcasts.read
Response

An array of broadcast resources. Paginated responses expose OpenScoreboard-Next-Cursor.

curl
curl "https://your-domain.example/api/v1/broadcasts?limit=25" \
  -H "Authorization: Bearer osb_test_your_key_here"
POST/broadcasts

Create a broadcast

Create a reusable broadcast and its broadcast-managed courts.

broadcasts.write
Response

The new broadcast, including generated broadcast and court IDs.

  • Court and scoreboard output records are created atomically behind the public model.
curl
curl -X POST https://your-domain.example/api/v1/broadcasts \
  -H "Authorization: Bearer osb_test_your_key_here" \
  -H "Content-Type: application/json" \
  -H "OpenScoreboard-Request-ID: demo-request-001" \
  -d '{"name":"Center Court","description":"Main stream","scoreboardIDs":["scoreboard-id"],"tables":[{"label":"Court 1"}]}'
GET/broadcasts/{broadcastID}

Read a broadcast

Read one account-owned broadcast and its court/output configuration.

broadcasts.read
Response

A broadcast resource or a 404 error.

JavaScript
const baseURL = "https://your-domain.example/api/v1";
const apiKey = "osb_test_your_key_here";

async function api(path, init = {}) {
  const response = await fetch(`${baseURL}${path}`, {
    ...init,
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json",
      "OpenScoreboard-Request-ID": "demo-request-001",
      ...(init.headers || {})
    }
  });

  const body = await response.json();
  if (!response.ok) {
    throw new Error(body.error?.message || "Request failed");
  }

  return body.data;
}

const broadcast = await api("/broadcasts/broadcast-id");
PATCH/broadcasts/{broadcastID}

Update a broadcast

Replace persistent broadcast settings and reconcile its managed courts and outputs.

broadcasts.write
Response

The updated broadcast resource.

JavaScript
const baseURL = "https://your-domain.example/api/v1";
const apiKey = "osb_test_your_key_here";

async function api(path, init = {}) {
  const response = await fetch(`${baseURL}${path}`, {
    ...init,
    headers: {
      "Authorization": `Bearer ${apiKey}`,
      "Content-Type": "application/json",
      "OpenScoreboard-Request-ID": "demo-request-001",
      ...(init.headers || {})
    }
  });

  const body = await response.json();
  if (!response.ok) {
    throw new Error(body.error?.message || "Request failed");
  }

  return body.data;
}

const broadcast = await api("/broadcasts/broadcast-id", {
  method: "PATCH",
  body: JSON.stringify({ name: "Main Arena", tables: [{ label: "Court 1" }, { label: "Court 2" }] })
});
DELETE/broadcasts/{broadcastID}

Delete a broadcast

Remove a broadcast and its managed courts and output links.

broadcasts.write
Response

A deletion confirmation.

curl
curl -X DELETE https://your-domain.example/api/v1/broadcasts/broadcast-id \
  -H "Authorization: Bearer osb_test_your_key_here"