HTTP API
Basics
- Base URL
https://api.ocheso.com. JSON in, JSON out, UTF-8. - Your server authenticates with an organisation secret key:
Authorization: Bearer ochs_…. Make one in Studio → Developers, with only the scopes it needs:players,tournaments,invites,read. - A request that carries an
Originheader is refused with 400: it came from a browser, which means the key is in a web page. Rotate any key that ever was. - Times are ISO 8601 in UTC. Clocks are in seconds.
Keys and tokens
| Token | Who holds it | Lives | Used for |
|---|---|---|---|
| ochs_… | Your server | Until revoked | Everything on this page. |
| ochp_… | Your page, for a moment | 10 minutes | Signing one of your users into a widget. |
| oche_… | The widget | 12 h or 7 days | The player's actions inside the frame. You never handle it. |
| whsec_… | Your server | Until rotated | Checking webhook signatures. |
Ocheso stores only a fingerprint of each, so a lost key can't be shown again: revoke it and make another.
Platform routes
Everything under /v1/platform takes a secret key and acts as your organisation.
| Route | Does |
|---|---|
| POST /v1/platform/player-tokens | A 10-minute player token for one of your users; optionally limited to one tournament and entering them. |
| GET /v1/platform/tournaments | Your organisation's tournaments. |
| POST /v1/platform/tournaments | Create one. The reply carries its hosted page and ready-made embed snippets. |
| GET · PATCH /v1/platform/tournaments/{slug} | Read or change one. |
| POST /v1/platform/tournaments/{slug}/publish | Open entries. Also start, finish and archive. |
| POST /v1/platform/tournaments/{slug}/players | Add up to 500: by email (invited) or by external_id (entered). |
| DELETE /v1/platform/tournaments/{slug}/players/{external_id} | Take one of your users out. |
| GET /v1/platform/tournaments/{slug}/roster | Who is in or waiting, with external_id for your users. Also rounds and standings. |
| DELETE /v1/platform/players/{external_id} | Erase one of your users: anonymised in past results, your id forgotten. |
Create a tournament
curl -s https://api.ocheso.com/v1/platform/tournaments \
-H "Authorization: Bearer $OCHESO_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: friday-blitz-2026-11-06" \
-d '{
"title": "Friday Blitz",
"game": "chess", "variant": "standard",
"format": "arena", "arena_minutes": 60,
"clock_base_s": 180, "clock_increment_s": 2,
"starts_at": "2026-11-06T18:00:00Z",
"autopilot": true, "min_players": 4
}'
# 201 -> the tournament, plus hosted_url and embed: {script, iframe, link}Formats are swiss (with rounds_count), round_robin, knockout and arena (with arena_minutes). Games are chess (standard) and checkers (international or brazilian). Your organisation's events are unrated and off Ocheso's public list unless you say otherwise.
Add players
curl -s https://api.ocheso.com/v1/platform/tournaments/friday-blitz/players \
-H "Authorization: Bearer $OCHESO_SECRET_KEY" -H "Content-Type: application/json" \
-d '{"players": [
{"email": "amina@example.com", "name": "Amina N."},
{"external_id": "user-42", "name": "Jean-Paul M."}
]}'
# Emails are invited (and entered when they sign in with that address);
# your own users, by external_id, are entered at once.The rest of the API
| Group | Who calls it | What's in it |
|---|---|---|
| Platform | Your server, with ochs_ | The routes above. |
| Embed | The widget itself | Tournament bundles, schedules, games and the widget's own sessions. Public reads are open to any origin and cached for a few seconds; you may read GET /v1/embed/t/{slug} to build your own display. |
| Studio | Studio, as a signed-in organiser | Organisations, team, keys, webhooks, brand, players, installs and autopilot controls. Everything Studio does is here, under /v1/orgs. |
| Internal | Ocheso's autopilot | The scheduler's tick. Not callable from outside. |
Errors
Errors are JSON with a sentence you can show and a code you can branch on.
HTTP/1.1 409 Conflict
Content-Type: application/json
{"detail": "Entries are closed: the tournament has started.", "code": "conflict"}| Status | Means |
|---|---|
| 400 | Malformed, or a secret key sent from a browser (server_only). |
| 401 | Missing, unknown or revoked key; an expired token or session. |
| 403 | The key lacks the scope, or the organisation is suspended. |
| 404 | No such tournament for your organisation (others' events look the same as missing). |
| 409 | The state doesn't allow it: entries closed, a round already paired, full. |
| 422 | A field is wrong; detail names it. Unknown fields are refused, not ignored. |
| 429 | Too many requests (rate_limited). Retry after the seconds in Retry-After. |
| 503 | Ocheso can't reach its database for a moment. Retry with backoff. |
Retries and idempotency
Send Idempotency-Keyon a POST (any 1–255 visible characters, unique per action) and a retry within 24 hours gets the first reply instead of acting twice. Entering a player is an upsert and inviting an address twice answers "already", so those are safe to repeat even without one.
Limits
| Community | Club | Federation | |
|---|---|---|---|
| Player tokens a minute | 60 | 600 | 3,000 |
| Players per event | 64 | 4,096 | 4,096 |
| Live secret keys | 2 | 10 | 50 |
| Webhook endpoints | – | 5 | 20 |
| Email invites a day | 500 | 5,000 | 50,000 |
Every route, field and response is in the API reference.