Quickstart
Create a SETTO API token in the dashboard and make your first three requests to the External API with curl, JavaScript or Python.
This page takes you from nothing to a tournament payload in five minutes: create
a token in the SETTO organizer dashboard, confirm it with GET /v1/external/me,
list your tournaments, then fetch one tournament with its categories embedded.
Every request is a plain GET with an Authorization: Bearer header — no SDK,
no OAuth dance, no client secret.
Before you start
You need a SETTO account. A personal token reaches every tournament you manage; to give a system only one organization's tournaments, create an organization token — see Two kinds of token. Connecting an AI assistant instead? claude.ai, ChatGPT, Codex and Claude Code can sign in with your SETTO account, no token needed.
Create an API token
In app.setto.io, open Configuración → Tokens de
API, keep the scope on Personal (or pick an organization), and choose
Crear token. Give it a name you will recognise later (Website widget,
Season export, …), optionally pick an expiry of 30, 90 or 365 days, and
confirm.
The secret is shown exactly once
SETTO stores only a hash of the token. The full setto_live_… value appears
in the dialog immediately after creation and never again — copy it into your
secret manager before closing. If you lose it, revoke the token and create a
new one.
You can hold up to 10 active personal tokens, and an organization up to 10
active organization tokens. A token reads (scopes: ["read"]) unless you tick
more under Permisos: «Gestionar torneos» adds the tournament setup
writes — creating tournaments and categories, registering teams, «Sustitución»,
«Baja», the format, the groups and the knockout draw — as manage,
«Cargar resultados» adds recording and clearing results as results,
«Programar partidos» adds setting game times and courts as schedule
(scopes: ["read", "schedule"]), and
the other permissions are listed in
What a token can change. Any
token can be revoked at any time from the same list.
Confirm the token
GET /v1/external/me is the cheapest way to prove a token works. It tells you
who the token belongs to (owner), when it was created, when it expires, and
what your rate limit is.
export SETTO_API_TOKEN="setto_live_YOUR_TOKEN_HERE"
curl -s https://api.setto.io/v1/external/me \
-H "Authorization: Bearer $SETTO_API_TOKEN"{
"owner": {
"type": "user",
"idx": "2a7e4c91-0b3d-4f58-9e16-c5d8a2f4b073",
"name": "Ana López"
},
"organization": null,
"token": {
"idx": "b8e3f107-5c92-4d6a-8e71-0a4c9d2b3f65",
"name": "Website widget",
"prefix": "setto_live_9f2ca",
"scopes": ["read"],
"createdAt": "2026-09-01T16:04:22.113Z",
"expiresAt": null,
"lastUsedAt": "2026-09-17T09:12:44.005Z"
},
"rateLimit": { "limit": 120, "windowSeconds": 60 }
}That is a personal token: owner.type is "user" and organization is
null. An organization token answers owner.type: "organization" and fills
organization with the organization's idx, name, slug, avatar and
website.
A 401 here means the header is missing or the token is wrong — see
Errors.
List your tournaments
GET /v1/external/tournaments returns a page of tournaments ordered by
startDate descending, newest first.
curl -s -G https://api.setto.io/v1/external/tournaments \
-H "Authorization: Bearer $SETTO_API_TOKEN" \
-d status=IN_PROGRESS \
-d sport=PADEL \
-d limit=5{
"data": [
{
"idx": "3c9b7f52-6d41-4a8e-b1f0-2e7d5c9a4b18",
"slug": "torneo-apertura-2026",
"name": "Torneo Apertura 2026",
"type": "TOURNAMENT",
"sport": "PADEL",
"status": "IN_PROGRESS",
"startDate": "2026-09-18T00:00:00.000Z",
"endDate": "2026-09-20T00:00:00.000Z",
"timezone": "America/Monterrey",
"publicUrl": "https://www.setto.io/t/torneo-apertura-2026",
"organization": {
"idx": "6f1d9c2e-4a7b-4f3d-9d2c-8b5e1a0f7c43",
"name": "Club Padel Monterrey",
"slug": "club-padel-monterrey"
}
}
],
"meta": { "limit": 5, "offset": 0, "total": 1 }
}Keep the idx — it is the identifier every other endpoint takes.
Fetch one tournament with its categories
Relations are opt-in. Ask for them with populate, a comma-separated list.
GET /v1/external/tournaments/{idx} defaults to club,divisions; asking for
divisions alone keeps the payload small.
curl -s -G \
https://api.setto.io/v1/external/tournaments/3c9b7f52-6d41-4a8e-b1f0-2e7d5c9a4b18 \
-H "Authorization: Bearer $SETTO_API_TOKEN" \
-d populate=divisions{
"idx": "3c9b7f52-6d41-4a8e-b1f0-2e7d5c9a4b18",
"slug": "torneo-apertura-2026",
"name": "Torneo Apertura 2026",
"type": "TOURNAMENT",
"sport": "PADEL",
"status": "IN_PROGRESS",
"publicUrl": "https://www.setto.io/t/torneo-apertura-2026",
"divisions": [
{
"idx": "7b2f4d16-9c83-4e50-a7d1-3f6c8b204e59",
"name": "Cuarta Fuerza Varonil",
"number": 1,
"color": "#2563eb",
"isDoubles": true,
"isVisible": true,
"price": 900,
"tournament": { "idx": "3c9b7f52-6d41-4a8e-b1f0-2e7d5c9a4b18" }
}
]
}Next steps
- Populate — the exact relation list per endpoint, and why a nested path needs its parents.
- Get a round — groups, standings, games and brackets in a single request. This is the endpoint most integrations spend their time in.
- Rate limits — 120 requests per minute per token, and a second per-IP ceiling of 300 requests per minute.
- API reference — every parameter, with a Try it panel you can paste a token into.