DerbiDerbi

Client API · v1

Your league's data, on your site or in your app

A read-only REST API with the standings, fixtures, results, top scorers and every team's page of any league with its public site switched on. JSON and iCal, computed on the spot.

Base URLhttps://derbiapp.com/client-api/v1

Introduction

The API reads the same data anyone can see on each league's public site, in a format made for programs: show the table on your club's website, push results to a screen at the sports hall or put the fixtures in your own app.

Every answer is computed by the same engine the Derbi app uses: tie-breakers, walkovers and each league's rulebook sanctions are already applied.

  • Read-only, published leagues only
  • UTF-8 JSON; dates in UTC milliseconds
  • iCal fixtures to subscribe to
  • Always with a key, billed by usage

Start in a minute

Make your first call with the demo key. It returns the whole league: teams, standings, matches and top scorers.

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7 \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"

Authentication

Every call needs a key. Send it in the Authorization header as a Bearer token (or in X-Api-Key if your client can't set Authorization).

Authorization: Bearer dk_live_…

Demo key

Public on purpose: it only reads the four demo leagues, is limited to 30 calls a minute and is never billed.

dk_demo_derbi_client_api_v1
  • demo-futbol-sala
  • demo-futbol-7
  • demo-futbol-11
  • demo-basquet

Your key

  1. Sign in to the Derbi admin with your organiser account.
  2. Go to Account › API and activate the API with your card.
  3. Create a key and copy it: it's only shown once.
Get a key

Don't put your key in a public web page's code: anyone could copy it and spend on your account. Call the API from your server and keep the answer there.

Console

Try any endpoint right here. By default it uses the demo key and the demo leagues; with your own key you can read any published league.

curl command

Headers

Response

Endpoints

All of them are GET and share the same base URL. {slug} is the league's public address (the same as /lliga/{slug} on the site).

GET/leagues/{slug}

Whole league

League details, teams, standings, every match and the top scorers in one answer. The most useful call: one request is enough to draw a whole league site.

Parameters

slugstring · path · requiredThe league's public address.

Returns: LeagueView

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7 \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"
Example response
{
  "league": {
    "name": "Lliga Demo Futbol 7",
    "season": "2026/27",
    "sport": "football7",
    "rounds": 18,
    "currentRound": 10,
    "championSlots": 1,
    "playoffSlots": 3,
    "columns": [
      "pos",
      "team",
      "played",
      "won",
      "drawn",
      "lost",
      "for",
      "diff",
      "points"
    ],
    "scoreUnit": "goals",
    "players": true,
    "brand": {
      "mode": "dark",
      "color": "#2f6fd6",
      "intro": "La lliga de futbol 7 dels dissabtes al matí."
    }
  },
  "teams": [
    {
      "id": "demo-futbol-7-sal",
      "name": "CF Saltiró",
      "short": "SAL",
      "color": "#7B4FD6",
      "homeVenue": "Camp del Saltiró"
    },
    {
      "id": "demo-futbol-7-mon",
      "name": "Club Montalt",
      "short": "MON",
      "color": "#D6458F",
      "homeVenue": "Camp de Montalt"
    },
    {
      "id": "demo-futbol-7-roc",
      "name": "FC Rocafort",
      "short": "ROC",
      "color": "#1F9D55",
      "homeVenue": "Camp Municipal Rocafort"
    }
  ],
  "standings": [
    {
      "teamId": "demo-futbol-7-sal",
      "played": 10,
      "won": 5,
      "drawn": 4,
      "lost": 1,
      "for": 19,
      "against": 6,
      "diff": 13,
      "points": 19,
      "form": [
        "W",
        "W",
        "W",
        "D",
        "D"
      ],
      "pos": 1,
      "zone": "champion"
    },
    {
      "teamId": "demo-futbol-7-mon",
      "played": 10,
      "won": 4,
      "drawn": 5,
      "lost": 1,
      "for": 10,
      "against": 3,
      "diff": 7,
      "points": 17,
      "form": [
        "W",
        "W",
        "W",
        "D",
        "L"
      ],
      "pos": 2,
      "zone": "playoff"
    },
    {
      "teamId": "demo-futbol-7-roc",
      "played": 10,
      "won": 5,
      "drawn": 1,
      "lost": 4,
      "for": 17,
      "against": 11,
      "diff": 6,
      "points": 16,
      "form": [
        "W",
        "L",
        "W",
        "W",
        "W"
      ],
      "pos": 3,
      "zone": "playoff"
    }
  ],
  "matches": [
    {
      "id": "demo-futbol-7-j10-48",
      "round": 10,
      "homeId": "demo-futbol-7-vil",
      "awayId": "demo-futbol-7-est",
      "startsAt": 1792828800000,
      "venue": "Camp de Vilanoveta",
      "status": "finished",
      "homeScore": 3,
      "awayScore": 1
    },
    {
      "id": "demo-futbol-7-j10-49",
      "round": 10,
      "homeId": "demo-futbol-7-can",
      "awayId": "demo-futbol-7-sal",
      "startsAt": 1792828800000,
      "venue": "Camp de Canyet",
      "status": "finished",
      "homeScore": 1,
      "awayScore": 1
    },
    {
      "id": "demo-futbol-7-j11-50",
      "round": 11,
      "homeId": "demo-futbol-7-gav",
      "awayId": "demo-futbol-7-bel",
      "startsAt": 1793437200000,
      "venue": "Camp de les Gavarres",
      "status": "scheduled"
    }
  ],
  "scorers": [
    {
      "pos": 1,
      "playerId": "demo-futbol-7-sal-5",
      "teamId": "demo-futbol-7-sal",
      "name": "Roger Vilaró",
      "value": 5,
      "matches": 10
    },
    {
      "pos": 2,
      "playerId": "demo-futbol-7-vil-4",
      "teamId": "demo-futbol-7-vil",
      "name": "Arnau Xirau",
      "value": 4,
      "matches": 10
    },
    {
      "pos": 3,
      "playerId": "demo-futbol-7-bel-5",
      "teamId": "demo-futbol-7-bel",
      "name": "Eloi Gual",
      "value": 4,
      "matches": 10
    }
  ],
  "live": false
}

GET/leagues/{slug}/matches

Matches

Every match of the season, by round and kick-off, with the teams to resolve their names. Matches not played yet carry no score.

Parameters

slugstring · path · requiredThe league's public address.

Returns: { matches: Match[], teams: Team[] }

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7/matches \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"
Example response
{
  "matches": [
    {
      "id": "demo-futbol-7-j10-48",
      "round": 10,
      "homeId": "demo-futbol-7-vil",
      "awayId": "demo-futbol-7-est",
      "startsAt": 1792828800000,
      "venue": "Camp de Vilanoveta",
      "status": "finished",
      "homeScore": 3,
      "awayScore": 1
    },
    {
      "id": "demo-futbol-7-j10-49",
      "round": 10,
      "homeId": "demo-futbol-7-can",
      "awayId": "demo-futbol-7-sal",
      "startsAt": 1792828800000,
      "venue": "Camp de Canyet",
      "status": "finished",
      "homeScore": 1,
      "awayScore": 1
    },
    {
      "id": "demo-futbol-7-j11-50",
      "round": 11,
      "homeId": "demo-futbol-7-gav",
      "awayId": "demo-futbol-7-bel",
      "startsAt": 1793437200000,
      "venue": "Camp de les Gavarres",
      "status": "scheduled"
    }
  ],
  "teams": [
    {
      "id": "demo-futbol-7-sal",
      "name": "CF Saltiró",
      "short": "SAL",
      "color": "#7B4FD6",
      "homeVenue": "Camp del Saltiró"
    },
    {
      "id": "demo-futbol-7-mon",
      "name": "Club Montalt",
      "short": "MON",
      "color": "#D6458F",
      "homeVenue": "Camp de Montalt"
    },
    {
      "id": "demo-futbol-7-roc",
      "name": "FC Rocafort",
      "short": "ROC",
      "color": "#1F9D55",
      "homeVenue": "Camp Municipal Rocafort"
    }
  ]
}

GET/leagues/{slug}/scorers

Top scorers

The top scorers table (points in basketball). Returns 404 when the league chose not to publish player names.

Parameters

slugstring · path · requiredThe league's public address.

Returns: { scorers: Scorer[], teams: Team[] }

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7/scorers \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"
Example response
{
  "scorers": [
    {
      "pos": 1,
      "playerId": "demo-futbol-7-sal-5",
      "teamId": "demo-futbol-7-sal",
      "name": "Roger Vilaró",
      "value": 5,
      "matches": 10
    },
    {
      "pos": 2,
      "playerId": "demo-futbol-7-vil-4",
      "teamId": "demo-futbol-7-vil",
      "name": "Arnau Xirau",
      "value": 4,
      "matches": 10
    },
    {
      "pos": 3,
      "playerId": "demo-futbol-7-bel-5",
      "teamId": "demo-futbol-7-bel",
      "name": "Eloi Gual",
      "value": 4,
      "matches": 10
    }
  ],
  "teams": [
    {
      "id": "demo-futbol-7-sal",
      "name": "CF Saltiró",
      "short": "SAL",
      "color": "#7B4FD6",
      "homeVenue": "Camp del Saltiró"
    },
    {
      "id": "demo-futbol-7-mon",
      "name": "Club Montalt",
      "short": "MON",
      "color": "#D6458F",
      "homeVenue": "Camp de Montalt"
    },
    {
      "id": "demo-futbol-7-roc",
      "name": "FC Rocafort",
      "short": "ROC",
      "color": "#1F9D55",
      "homeVenue": "Camp Municipal Rocafort"
    }
  ]
}

GET/leagues/{slug}/teams/{teamId}

Team page

One team: its details, its standings row, its matches and its squad (when the league publishes players).

Parameters

slugstring · path · requiredThe league's public address.
teamIdstring · path · requiredThe team's identifier (Team's id field).

Returns: TeamView

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7/teams/demo-futbol-7-sal \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"
Example response
{
  "team": {
    "id": "demo-futbol-7-sal",
    "name": "CF Saltiró",
    "short": "SAL",
    "color": "#7B4FD6",
    "homeVenue": "Camp del Saltiró"
  },
  "standing": {
    "teamId": "demo-futbol-7-sal",
    "played": 10,
    "won": 5,
    "drawn": 4,
    "lost": 1,
    "for": 19,
    "against": 6,
    "diff": 13,
    "points": 19,
    "form": [
      "W",
      "W",
      "W",
      "D",
      "D"
    ],
    "pos": 1,
    "zone": "champion"
  },
  "matches": [
    {
      "id": "demo-futbol-7-j1-4",
      "round": 1,
      "homeId": "demo-futbol-7-sal",
      "awayId": "demo-futbol-7-can",
      "startsAt": 1787385600000,
      "venue": "Camp del Saltiró",
      "status": "finished",
      "homeScore": 1,
      "awayScore": 1
    },
    {
      "id": "demo-futbol-7-j2-9",
      "round": 2,
      "homeId": "demo-futbol-7-vil",
      "awayId": "demo-futbol-7-sal",
      "startsAt": 1787990400000,
      "venue": "Camp de Vilanoveta",
      "status": "finished",
      "homeScore": 1,
      "awayScore": 5
    }
  ],
  "players": [
    {
      "id": "demo-futbol-7-sal-1",
      "name": "Jofre Pagès",
      "number": 1,
      "position": "goalkeeper"
    },
    {
      "id": "demo-futbol-7-sal-5",
      "name": "Roger Vilaró",
      "number": 5,
      "position": "forward"
    }
  ]
}

GET/leagues/{slug}/calendar.ics

iCal fixtures

Dated matches as iCalendar, to subscribe to from Google Calendar, Apple Calendar or Outlook. With ?team= only one team's.

Parameters

slugstring · path · requiredThe league's public address.
teamstring · query · optionalOnly this team's matches.

Returns: iCalendar

curl https://derbiapp.com/client-api/v1/leagues/demo-futbol-7/calendar.ics \
  -H "Authorization: Bearer dk_demo_derbi_client_api_v1"
Example response
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Derbi//Lliga//CA
X-WR-CALNAME:Lliga Demo Futbol 7
BEGIN:VEVENT
UID:demo-futbol-7-j11-50@demo-futbol-7.derbi
DTSTART:20261107T090000Z
DTEND:20261107T101500Z
SUMMARY:CE Gavarres - Penya Bellavista
LOCATION:Camp de les Gavarres
DESCRIPTION:Lliga Demo Futbol 7 · J11
END:VEVENT
END:VCALENDAR

Objects

Optional fields are only present when they have a value. Field names won't change within v1.

LeagueView

FieldTypeDescription
leagueLeagueThe league.
teamsTeam[]Every team, by name.
standingsStanding[]The standings, by position.
matchesMatch[]Every match, by round and kick-off.
scorersScorer[] | nullTop scorers; null when the league doesn't publish players.
livebooleanA match is being played right now.

League

FieldTypeDescription
namestringLeague name.
group?stringGroup or division.
city?stringCity.
seasonstringSeason ("2026/27").
sport"futsal" | "football7" | "football11" | "basketball"Sport.
roundsintegerTotal rounds.
currentRoundintegerCurrent round.
championSlotsintegerChampion positions (1..n).
playoffSlotsintegerPlay-off positions after the champion ones.
columnsstring[]The sport's standings columns, in order.
scoreUnit"goals" | "points"Score unit: goals or points.
playersbooleanWhether the league publishes player names.
brandBrandThe look the organiser chose for the site.

Brand

FieldTypeDescription
mode"dark" | "light"Theme: dark or light.
color?stringMain colour (hex).
logoUrl?stringURL of the league's logo.
coverUrl?stringURL of the cover image.
intro?stringPresentation text (up to 280 characters).

Team

FieldTypeDescription
idstringIdentifier.
namestringName.
shortstring3-letter short name.
colorstringMain colour (hex).
homeVenue?stringUsual ground or hall.
kit?objectKit colours, per piece (hex).
crest?objectCrest colours (hex).

Standing

FieldTypeDescription
posintegerPosition.
teamIdstringTeam.
playedintegerPlayed.
wonintegerWon.
drawnintegerDrawn (always 0 in basketball).
lostintegerLost.
forintegerGoals or points scored.
againstintegerGoals or points conceded.
diffintegerDifference.
pointsintegerTable points.
zone"champion" | "playoff" | nullZone: champion, play-off or none.
form("W" | "D" | "L")[]Last 5 results, most recent last.

Match

FieldTypeDescription
idstringIdentifier.
roundintegerRound.
homeIdstringHome team.
awayIdstringAway team.
startsAtinteger | nullKick-off in UTC milliseconds; null while the date is pending.
venuestringGround or hall.
status"scheduled" | "live" | "pending_result" | "finished" | "postponed" | "suspended_rain"Status: scheduled, live, pending result, finished, postponed or suspended for rain.
homeScore?integerHome score, once started.
awayScore?integerAway score, once started.
outcome?{ kind, by }When it wasn't fully played: kind (walkover, abandoned…) and the side at fault.

Scorer

FieldTypeDescription
posintegerPosition.
playerIdstringPlayer.
teamIdstringTeam.
namestringName (full, or first name and initial, as the league chose).
valueintegerGoals or points.
matchesintegerMatches played.

TeamView

FieldTypeDescription
teamTeamThe team.
standingStanding | nullIts standings row.
matchesMatch[]Its matches.
playersPlayer[] | nullSquad by number; null when the league doesn't publish players.

Player

FieldTypeDescription
idstringIdentifier.
namestringName.
numberintegerShirt number.
positionstringPosition (the sport's identifier).

Error

FieldTypeDescription
error"key" | "billing" | "league" | "not_found" | "rate"Error code.
messagestringExplanation, in English.
docsstringLink to this page.

Errors

Errors come with an HTTP status and a JSON body with a stable code, an explanation and a link to these docs.

HTTPCodeWhen
401keyThe key is missing, unknown or revoked.
402billingThe key's account doesn't have the API active (or the payment failed).
403leagueThe key can't read this league (the demo key only reads the demo leagues).
404not_foundThere's no published league at this address, or the team doesn't exist.
429rateToo many calls in a minute. Wait and try again.
{
  "error": "key",
  "message": "Missing, unknown or revoked API key. Send it as `Authorization: Bearer <key>`; create one in the Derbi admin.",
  "docs": "https://derbiapp.com/client-api/v1/apidoc"
}

Limits and data

Per-key limit
600 calls per minute (30 with the demo key). Beyond that, 429.
Live data
Every keyed call is computed afresh: you see the result the referee has just closed.
Keep the answer
The table changes a few times a day: keep it for a few minutes on your server and save calls.
Dates
Milliseconds since 1/1/1970 UTC. Convert them to the league's local time (Europe/Madrid) to show them.
Published leagues
Only leagues with their public site on and an up-to-date subscription can be read.

Privacy

Each league's organiser decides how players appear: full name, first name and surname initial, or no names (then there are no top scorers or squads). The API never returns emails, phone numbers, birth years, invite codes, call-ups, referees or payments.

Pricing

You pay for what you use, monthly, with your organiser account's card. No calls, no charge.

10,000

calls a month free

€0.50

per 1,000 calls after that

Examples per month

CallsAmount
5,000€0
10,000€0
50,000€20
200,000€95
1,000,000€495

Prices exclude VAT. Stripe emails the invoice.

Get a key

Versioning

v1 is stable: we'll only add new fields or endpoints, never remove them or change their meaning. If an incompatible change is ever needed, it will ship as /client-api/v2 and v1 will keep working.

Download the OpenAPI specification