# Handball API complete reference

Handball results and history as a REST API: finished matches by day, scores with half-time, venues, crowds, referees and player lines with goalkeeper saves.

- Base URL: `https://api.handballapi.com/v1`
- Authentication: `Authorization: Bearer <key>` or `X-API-Key: <key>`
- Site: https://handballapi.com
- Endpoints: 62
- Generated: 2026-10-30 02:27 UTC
- This file: https://handballapi.com/documentation/manual.md

## Before anything else

- Factual data only: no predictions, ratings, tips or betting advice on any endpoint.
- Results and history only: a match is served after it is over. There is no live score, no in-play data and no betting prices on any plan, at any price.
- Competitions whose data rights are held by an official data partner are never collected, from any source (see Coverage).
- Every answer is `{"data": ..., "meta": {...}}`. `meta` carries counts, paging, the date or window asked for, and `took_ms`.
- Ids are our own and permanent: `mt_` matches, `tm_` teams, `cp_` competitions, `pl_` players, `rf_` referees, `vn_` venues. Times are UTC with a `Z`.

## Plans

| Plan | Price | Results reach back | Requests a minute | Calls a day | Endpoints |
|---|---|---|---|---|---|
| Free key | free | yesterday and today | 10 | 50 | the free ones |
| Results | not on sale yet | 400 days | 60 | 5,000 | all |
| Archive | not on sale yet | the whole archive | 120 | 25,000 | all |

## Coverage

Counted from the data on every call: `GET /v1/meta/coverage` returns matches, results and player lines by country, with first and latest dates.

## Endpoints

### Results

#### `GET /v1/results/yesterday`

Yesterday's results. Every match finished yesterday (UTC), newest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/results-yesterday

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code (dk, se, si, de, sk, rs, es, ch, ihf, history) | `dk` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/results/yesterday"
```

#### `GET /v1/results/latest`

Latest results. Matches finished in the last days, newest first. Results only: served after full time.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/results-latest

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `days` | query | integer | no | How many days back, 1 to 7 (2) | `2` |
| `country` | query | string | no | Country code | `dk` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/results/latest?days=2"
```

#### `GET /v1/results`

Results on a day. Every match finished on one day (UTC). The free key reaches yesterday and today.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/results-by-date

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `date` | query | date | yes | The day, YYYY-MM-DD | `2026-10-04` |
| `country` | query | string | no | Country code | `si` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/results?date=2026-10-04"
```

#### `GET /v1/results/today`

Today's results. Every match finished today so far (UTC), newest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/results-today

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/results/today"
```

#### `GET /v1/results/range`

Results between two days. Every match finished between two days (UTC), up to 32 days, newest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/results-range

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `from` | query | date | yes | First day, YYYY-MM-DD | `2026-10-01` |
| `to` | query | date | yes | Last day, YYYY-MM-DD | `2026-10-14` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/results/range?from=2026-10-20&to=2026-10-26"
```

### Matches

#### `GET /v1/matches/{id}`

One match. Score, half-time, date, venue, crowd, referees and shootout of one finished match.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/match

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Match id (mt_...) | `mt_00000000` |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |
| `venue` | string|null |
| `attendance` | integer|null |
| `referees` | string[]|null |
| `shootout` | object|null |
| `discipline` | string (indoor, beach, wheelchair) |
| `player_lines` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/matches/mt_8kq2v7xd"
```

#### `GET /v1/matches/{id}/players` (paid plans)

Player lines of a match. A line for every player listed for the match: goals, shots, 7m, assists, cards, and saves and shots faced for goalkeepers.

Plans: every paid plan. Docs: https://handballapi.com/documentation/match-players

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Match id (mt_...) | `mt_00000000` |
| `team` | query | string | no | home or away | `home` |

| Field | Type |
|---|---|
| `player_id` | string |
| `team` | string (home, away) |
| `name` | string |
| `shirt` | string|null |
| `position` | string|null (GK, LW, LB, CB, RB, RW, PV) |
| `goals` | integer|null |
| `shots` | integer|null |
| `seven_m_goals` | integer|null |
| `seven_m_shots` | integer|null |
| `assists` | integer|null |
| `yellow` | integer|null |
| `two_min` | integer|null |
| `red` | integer|null |
| `saves` | integer|null |
| `shots_faced` | integer|null |
| `save_rate` | number|null |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/matches/mt_8kq2v7xd/players"
```

#### `GET /v1/matches` (paid plans)

Find matches. Matches by team, competition, season and dates, finished or scheduled. Give at least one of team, competition, season or from.

Plans: every paid plan. Docs: https://handballapi.com/documentation/matches-search

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `team` | query | string | no | Team id (tm_...) | `tm_00000000` |
| `competition` | query | string | no | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `from` | query | date | no | From this day, YYYY-MM-DD | `2026-09-01` |
| `to` | query | date | no | To this day, YYYY-MM-DD | `2026-10-31` |
| `status` | query | string | no | finished or scheduled (finished) | `finished` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/matches?team=tm_7rx4m2qa"
```

#### `GET /v1/matches/{id}/officials`

Officials of a match. The referees of one finished match, each with our referee id where the name is known to us.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/match-officials

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Match id (mt_...) | `mt_00000000` |

| Field | Type |
|---|---|
| `referee_id` | string|null |
| `name` | string |
| `role` | string (referee) |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/matches/mt_8kq2v7xd/officials"
```

### Fixtures

#### `GET /v1/fixtures`

Fixtures ahead. Matches scheduled in the coming days, soonest first, with throw-off in UTC and in the league's own time.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/fixtures

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `days` | query | integer | no | How many days ahead, 1 to 14 (7) | `7` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `status` | string (scheduled) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/fixtures?days=7"
```

#### `GET /v1/fixtures/today`

Today's fixtures. Matches still to be played today (UTC), soonest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/fixtures-today

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `status` | string (scheduled) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/fixtures/today"
```

#### `GET /v1/fixtures/tomorrow`

Tomorrow's fixtures. Every match scheduled tomorrow (UTC), soonest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/fixtures-tomorrow

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `status` | string (scheduled) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/fixtures/tomorrow"
```

### Competitions

#### `GET /v1/competitions/{id}/table` (paid plans)

League table. The table of a competition and season, computed from the results held: played, won, drawn, lost, goals and points.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-table

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `rank` | integer |
| `team_id` | string |
| `name` | string |
| `played` | integer |
| `won` | integer |
| `drawn` | integer |
| `lost` | integer |
| `goals_for` | integer |
| `goals_against` | integer |
| `goal_diff` | integer |
| `points` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/table"
```

#### `GET /v1/competitions/{id}/scorers` (paid plans)

Top scorers. The leading scorers of a competition and season, from the player lines held, with matches, 7m goals and goals a match.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-scorers

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many players, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `team_id` | string |
| `team` | string |
| `matches` | integer |
| `goals` | integer |
| `seven_m_goals` | integer |
| `goals_per_match` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/scorers"
```

#### `GET /v1/competitions`

Competitions. Every competition with results, with country, men or women, league or cup, seasons and dates held.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competitions

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code | `de` |
| `gender` | query | string | no | men or women | `women` |
| `q` | query | string | no | Part of the name, 2 characters or more | `liga` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `name` | string |
| `country` | string |
| `gender` | string (men, women) |
| `kind` | string (league, cup) |
| `matches` | integer |
| `seasons` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions?country=de"
```

#### `GET /v1/competitions/{id}`

One competition. A competition: country, men or women, league or cup, seasons held, first and last match, and its latest season.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competition

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |

| Field | Type |
|---|---|
| `id` | string |
| `name` | string |
| `country` | string |
| `gender` | string (men, women) |
| `kind` | string (league, cup) |
| `matches` | integer |
| `seasons` | integer |
| `first_match` | date |
| `last_match` | date |
| `latest_season` | string |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd"
```

#### `GET /v1/competitions/{id}/seasons`

Seasons of a competition. Every season held for a competition, newest first: matches, teams, dates and how many matches have player lines.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competition-seasons

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |

| Field | Type |
|---|---|
| `season` | string |
| `matches` | integer |
| `teams` | integer |
| `first_match` | date |
| `last_match` | date |
| `matches_with_player_lines` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/seasons"
```

#### `GET /v1/competitions/{id}/results`

Results of a competition. Every result of a competition in a season, newest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competition-results

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/results"
```

#### `GET /v1/competitions/{id}/fixtures`

Fixtures of a competition. The matches still to be played in a competition, soonest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competition-fixtures

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `status` | string (scheduled) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/fixtures"
```

#### `GET /v1/competitions/{id}/teams`

Teams of a competition. Every team that played in a competition and season, with matches played.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/competition-teams

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `team_id` | string |
| `name` | string |
| `played` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/teams"
```

#### `GET /v1/competitions/{id}/goalkeepers` (paid plans)

Goalkeepers of a season. The best save rates of a competition and season, among goalkeepers who faced at least min_shots shots.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-goalkeepers

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |
| `min_shots` | query | integer | no | Shots faced at least (30) | `30` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `team_id` | string|null |
| `team` | string|null |
| `gk_matches` | integer |
| `saves` | integer |
| `shots_faced` | integer |
| `save_rate` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/goalkeepers"
```

#### `GET /v1/competitions/{id}/seven-metres` (paid plans)

7m takers of a season. The leading 7m scorers of a competition and season, with throws taken and the rate scored.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-seven-metres

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `team_id` | string|null |
| `team` | string|null |
| `matches` | integer |
| `seven_m_goals` | integer |
| `seven_m_shots` | integer|null |
| `seven_m_rate` | number|null |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/seven-metres"
```

#### `GET /v1/competitions/{id}/discipline` (paid plans)

Discipline of a season. Players with the most red cards, 2 minute suspensions and yellow cards in a competition and season.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-discipline

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `team_id` | string|null |
| `team` | string|null |
| `matches` | integer |
| `yellow` | integer |
| `two_min` | integer |
| `red` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/discipline"
```

#### `GET /v1/competitions/{id}/assists` (paid plans)

Assists of a season. The leading assist makers of a competition and season, where the league publishes assists.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-assists

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `team_id` | string|null |
| `team` | string|null |
| `matches` | integer |
| `assists` | integer |
| `goals` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/assists"
```

#### `GET /v1/competitions/{id}/home-away` (paid plans)

Home and away tables. Two tables for a competition and season: home matches only and away matches only.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-home-away

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `home` | object[] (rank, team_id, name, played, won, drawn, lost, goals_for, goals_against, goal_diff, points) |
| `away` | object[] (the same) |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/home-away"
```

#### `GET /v1/competitions/{id}/form` (paid plans)

Form table. Every team of a competition and season with its last five results and its current run.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-form

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `team_id` | string |
| `name` | string |
| `form` | string (last five, newest first, W D L) |
| `streak` | string (such as W3) |
| `played` | integer |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/form"
```

#### `GET /v1/competitions/{id}/stats` (paid plans)

Season figures. A competition season in figures: goals a match, home and away goals, home win, draw and away win rates, average crowd.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-stats

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `matches` | integer |
| `teams` | integer |
| `goals` | integer |
| `goals_per_match` | number |
| `home_goals_per_match` | number |
| `away_goals_per_match` | number |
| `home_win_rate` | number |
| `draw_rate` | number |
| `away_win_rate` | number |
| `matches_with_half_time` | integer |
| `average_crowd` | integer|null |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/stats"
```

#### `GET /v1/competitions/{id}/records` (paid plans)

Season records. The biggest win, the highest and lowest scoring match and the largest crowd of a competition season.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-records

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `biggest_win` | object (a match) |
| `highest_scoring` | object (a match) |
| `lowest_scoring` | object (a match) |
| `largest_crowd` | object|null (a match with attendance) |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/records"
```

#### `GET /v1/competitions/{id}/attendance` (paid plans)

Crowds of a season. Average, highest and total home crowd per team in a competition season, where crowds are published.

Plans: every paid plan. Docs: https://handballapi.com/documentation/competition-attendance

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `rank` | integer |
| `team_id` | string |
| `name` | string |
| `home_matches` | integer |
| `average` | integer |
| `highest` | integer |
| `total` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/competitions/cp_3fw9h2kd/attendance"
```

### Teams

#### `GET /v1/teams/{id}/head-to-head` (paid plans)

Head to head. Every finished match between two teams, newest first, with a summary from the first team's side: won, drawn, lost and goals.

Plans: every paid plan. Docs: https://handballapi.com/documentation/head-to-head

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `opponent` | query | string | yes | The other team's id (tm_...) | `tm_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/head-to-head?opponent=tm_5bn8c1zt"
```

#### `GET /v1/teams`

Find teams. Teams by part of the name or by country, with matches held and dates.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/teams

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `q` | query | string | no | Part of the name, 2 characters or more | `kiel` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `team_id` | string |
| `name` | string |
| `country` | string |
| `gender` | string (men, women) |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams?q=bratislava"
```

#### `GET /v1/teams/{id}`

One team. A team: country, men or women, matches held, first and last match and the competitions it played in.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/team

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |

| Field | Type |
|---|---|
| `team_id` | string |
| `name` | string |
| `country` | string |
| `gender` | string |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |
| `competitions` | object[] (id, name, matches, last_match) |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa"
```

#### `GET /v1/teams/{id}/results`

Results of a team. Every result of a team, newest first, in every competition held.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/team-results

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/results"
```

#### `GET /v1/teams/{id}/fixtures`

Fixtures of a team. A team's matches still to be played, soonest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/team-fixtures

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `status` | string (scheduled) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/fixtures"
```

#### `GET /v1/teams/{id}/squad` (paid plans)

Squad of a season. Every player with a line for the team in a season, with matches and goals.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-squad

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `player_id` | string |
| `name` | string |
| `position` | string|null |
| `matches` | integer |
| `goals` | integer |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/squad"
```

#### `GET /v1/teams/{id}/stats` (paid plans)

Season figures of a team. A team's season per competition: record, goals, home and away, goals a match, form and current run.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-stats

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |

| Field | Type |
|---|---|
| `competition` | object {id, name} |
| `season` | string |
| `played` | integer |
| `won` | integer |
| `drawn` | integer |
| `lost` | integer |
| `goals_for` | integer |
| `goals_against` | integer |
| `home` | object |
| `away` | object |
| `goals_for_per_match` | number |
| `goals_against_per_match` | number |
| `form` | string |
| `streak` | string |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/stats"
```

#### `GET /v1/teams/{id}/form` (paid plans)

Form of a team. A team's last results in every competition, newest first, each marked won, drawn or lost.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-form

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `last` | query | integer | no | How many matches, 1 to 20 (5) | `5` |

| Field | Type |
|---|---|
| `result` | string (W, D, L) |
| `venue` | string (home, away) |
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/form"
```

#### `GET /v1/teams/{id}/scorers` (paid plans)

Scorers of a team. A team's leading scorers in a season, in every competition held.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-scorers

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `matches` | integer |
| `goals` | integer |
| `seven_m_goals` | integer |
| `goals_per_match` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/scorers"
```

#### `GET /v1/teams/{id}/seasons` (paid plans)

Seasons of a team. Every season a team played, per competition, newest first, with its record.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-seasons

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |

| Field | Type |
|---|---|
| `competition` | object {id, name} |
| `season` | string |
| `played` | integer |
| `won` | integer |
| `drawn` | integer |
| `lost` | integer |
| `goals_for` | integer |
| `goals_against` | integer |
| `home` | object |
| `away` | object |
| `goals_for_per_match` | number |
| `goals_against_per_match` | number |
| `form` | string |
| `streak` | string |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/seasons"
```

#### `GET /v1/teams/{id}/streaks` (paid plans)

Runs of a team. A team's current run and its longest winning, unbeaten and losing runs across every competition held.

Plans: every paid plan. Docs: https://handballapi.com/documentation/team-streaks

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Team id (tm_...) | `tm_00000000` |

| Field | Type |
|---|---|
| `team_id` | string |
| `name` | string |
| `played` | integer |
| `form` | string |
| `current` | string |
| `unbeaten_run` | integer |
| `winless_run` | integer |
| `longest_winning_run` | integer |
| `longest_unbeaten_run` | integer |
| `longest_losing_run` | integer |
| `last_match` | object |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/teams/tm_7rx4m2qa/streaks"
```

### Meta

#### `GET /v1/meta/coverage`

Coverage. What the archive holds, counted from the data: matches, results and player lines by country, and what is never collected.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/meta-coverage

| Field | Type |
|---|---|
| `in_play` | boolean |
| `collected` | string |
| `not_collected` | string[] |
| `countries` | object[] |
| `totals` | object |

Errors: `unauthorized`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/meta/coverage"
```

#### `GET /v1/meta/completeness`

Completeness. Every competition season held, with how complete it is: results, half-time, venue, crowd, player lines, and how many of those lines add up to the score.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/meta-completeness

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `country` | query | string | no | Country code | `dk` |
| `season` | query | string | no | Season, as YYYY/YYYY | `2025/2026` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `competition_id` | string |
| `competition` | string |
| `country` | string |
| `season` | string|null |
| `discipline` | string (indoor, beach) |
| `first_match` | date|null |
| `last_match` | date|null |
| `matches` | integer |
| `results` | integer |
| `half_time_pct` | number |
| `venue_pct` | number |
| `attendance_pct` | number |
| `player_lines` | string (published, results_only) |
| `with_player_lines_pct` | number|null |
| `lines_add_up_pct` | number|null |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/meta/completeness?country=si"
```

#### `GET /v1/meta/seasons`

Seasons held. Every season held, newest first, with matches and the countries it covers.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/meta-seasons

| Field | Type |
|---|---|
| `season` | string |
| `matches` | integer |
| `countries` | string[] |

Errors: `unauthorized`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/meta/seasons"
```

#### `GET /v1/updates` (paid plans)

Changed since. Matches added or changed since a time (7 days back at most), oldest change first, for keeping a copy in step.

Plans: every paid plan. Docs: https://handballapi.com/documentation/updates

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `since` | query | datetime | yes | A UTC time, such as 2026-10-28T06:00:00Z | `2026-10-28T06:00:00Z` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |
| `changed_at` | datetime |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/updates?since=2026-10-28T06:00:00Z"
```

### Account

#### `GET /v1/usage`

Your usage. Your plan, calls today, the limits, when they reset and how far back your results reach. Never counted against your allowance.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/usage

| Field | Type |
|---|---|
| `plan` | string |
| `plan_name` | string |
| `calls_today` | integer |
| `calls_this_month` | integer |
| `per_day` | integer|null |
| `per_minute` | integer|null |
| `resets_at` | datetime |
| `results_from` | date|null |
| `all_endpoints` | boolean |

Errors: `unauthorized`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/usage"
```

### Players

#### `GET /v1/players/leaders` (paid plans)

Leaders. The leading players across every competition held, or one season or country: goals, 7m goals, assists or 2 minute suspensions.

Plans: every paid plan. Docs: https://handballapi.com/documentation/players-leaders

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `stat` | query | string | no | goals, seven_m_goals, assists or two_min (goals) | `goals` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `country` | query | string | no | Country code | `de` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `matches` | integer |
| `goals` | integer (or the stat asked for) |
| `per_match` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players/leaders?stat=goals&season=2025/26"
```

#### `GET /v1/players`

Find players. Players by part of the name, with matches, goals and their last match.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/players-search

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `q` | query | string | yes | Part of the name, 3 characters or more | `hansen` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `player_id` | string |
| `name` | string |
| `matches` | integer |
| `goals` | integer |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players?q=hansen"
```

#### `GET /v1/players/{id}`

One player. A player: position, nationality and birth date where published, latest team, matches, goals and dates.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/player

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Player id (pl_...) | `pl_00000000` |

| Field | Type |
|---|---|
| `player_id` | string |
| `name` | string |
| `position` | string|null |
| `nationality` | string|null |
| `birth_date` | date|null |
| `team` | object|null |
| `matches` | integer |
| `goals` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players/pl_4mv8k2rd"
```

#### `GET /v1/players/{id}/matches` (paid plans)

Matches of a player. Every match a player has a line for, newest first, with the line: goals, shots, 7m, assists, suspensions, saves.

Plans: every paid plan. Docs: https://handballapi.com/documentation/player-matches

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Player id (pl_...) | `pl_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |
| `team` | string (home, away) |
| `line` | object (goals, shots, seven_m_goals, seven_m_shots, assists, two_min, saves, shots_faced) |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players/pl_4mv8k2rd/matches"
```

#### `GET /v1/players/{id}/seasons` (paid plans)

Seasons of a player. A player's seasons per competition and team, newest first, with the sums of the lines.

Plans: every paid plan. Docs: https://handballapi.com/documentation/player-seasons

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Player id (pl_...) | `pl_00000000` |

| Field | Type |
|---|---|
| `season` | string |
| `competition` | object |
| `team` | object|null |
| `matches` | integer |
| `goals` | integer |
| `shots` | integer|null |
| `seven_m_goals` | integer |
| `seven_m_shots` | integer|null |
| `assists` | integer|null |
| `yellow` | integer |
| `two_min` | integer |
| `red` | integer |
| `saves` | integer|null |
| `shots_faced` | integer|null |
| `save_rate` | number|null |
| `goals_per_match` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players/pl_4mv8k2rd/seasons"
```

#### `GET /v1/players/{id}/career` (paid plans)

Career of a player. A player's career totals, and per competition, across everything held.

Plans: every paid plan. Docs: https://handballapi.com/documentation/player-career

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Player id (pl_...) | `pl_00000000` |

| Field | Type |
|---|---|
| `player_id` | string |
| `name` | string |
| `totals` | object |
| `competitions` | object[] |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/players/pl_4mv8k2rd/career"
```

#### `GET /v1/goalkeepers/leaders` (paid plans)

Goalkeeper leaders. The best save rates across every competition held, or one season or country, among goalkeepers who faced at least min_shots shots.

Plans: every paid plan. Docs: https://handballapi.com/documentation/goalkeepers-leaders

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `country` | query | string | no | Country code | `de` |
| `limit` | query | integer | no | How many rows, 1 to 200 (25) | `25` |
| `min_shots` | query | integer | no | Shots faced at least (100) | `100` |

| Field | Type |
|---|---|
| `rank` | integer |
| `player_id` | string |
| `name` | string |
| `gk_matches` | integer |
| `saves` | integer |
| `shots_faced` | integer |
| `save_rate` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/goalkeepers/leaders?season=2025/26"
```

### Referees

#### `GET /v1/referees`

Find referees. Referees by part of the name or by country, with matches held and dates.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/referees

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `q` | query | string | no | Part of the name, 3 characters or more | `nygaard` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `referee_id` | string |
| `name` | string |
| `countries` | string[] |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/referees?country=de"
```

#### `GET /v1/referees/{id}`

One referee. A referee: countries, matches held, first and last match.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/referee

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Referee id (rf_...) | `rf_00000000` |

| Field | Type |
|---|---|
| `referee_id` | string |
| `name` | string |
| `countries` | string[] |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/referees/rf_9tq3x6wb"
```

#### `GET /v1/referees/{id}/matches` (paid plans)

Matches of a referee. Every result a referee took charge of, newest first.

Plans: every paid plan. Docs: https://handballapi.com/documentation/referee-matches

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Referee id (rf_...) | `rf_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/referees/rf_9tq3x6wb/matches"
```

#### `GET /v1/referees/{id}/stats` (paid plans)

Record of a referee. A referee's record: home win, draw and away win rates, goals a match, and 2 minute suspensions and 7m throws a match where player lines are held.

Plans: every paid plan. Docs: https://handballapi.com/documentation/referee-stats

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Referee id (rf_...) | `rf_00000000` |

| Field | Type |
|---|---|
| `referee_id` | string |
| `name` | string |
| `countries` | string[] |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |
| `home_win_rate` | number |
| `draw_rate` | number |
| `away_win_rate` | number |
| `goals_per_match` | number |
| `matches_with_player_lines` | integer |
| `two_min_per_match` | number|null |
| `seven_m_per_match` | number|null |
| `seasons` | object[] |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/referees/rf_9tq3x6wb/stats"
```

### Venues

#### `GET /v1/venues`

Find venues. Halls by part of the name or by country, with matches held and dates.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/venues

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `q` | query | string | no | Part of the name, 3 characters or more | `arena` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `venue_id` | string |
| `name` | string |
| `country` | string |
| `matches` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/venues?country=dk"
```

#### `GET /v1/venues/{id}/matches` (paid plans)

Matches at a venue. Every result played at a hall, newest first.

Plans: every paid plan. Docs: https://handballapi.com/documentation/venue-matches

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `id` | path | string | yes | Venue id (vn_...) | `vn_00000000` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `date_utc` | datetime |
| `kickoff_local` | datetime|null |
| `timezone` | string|null |
| `status` | string (finished, awarded) |
| `competition` | object {id, name, country, season} |
| `home` | object {team_id, name, goals, ht} |
| `away` | object {team_id, name, goals, ht} |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `not_found`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/venues/vn_2hs7p4ce/matches"
```

### Countries

#### `GET /v1/countries`

Countries. Every country and group held, with matches, results, first match, latest result and player lines.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/countries

| Field | Type |
|---|---|
| `code` | string |
| `name` | string |
| `matches` | integer |
| `results` | integer |
| `first_match` | date |
| `last_result` | date |
| `player_lines` | integer |

Errors: `unauthorized`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/countries"
```

#### `GET /v1/countries/{code}/competitions`

Competitions of a country. Every competition held for a country, the busiest first.

Plans: every plan, the free key included. Docs: https://handballapi.com/documentation/country-competitions

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `code` | path | string | yes | Country code | `dk` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `id` | string |
| `name` | string |
| `country` | string |
| `gender` | string (men, women) |
| `kind` | string (league, cup) |
| `matches` | integer |
| `seasons` | integer |
| `first_match` | date |
| `last_match` | date |

Errors: `bad_request`, `unauthorized`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/countries/dk/competitions"
```

### Stats

#### `GET /v1/stats/home-advantage` (paid plans)

Home advantage. Home win, draw and away win rates and home and away goals a match, by country and season.

Plans: every paid plan. Docs: https://handballapi.com/documentation/stats-home-advantage

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `competition` | query | string | no | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `country` | query | string | no | Country code | `de` |
| `per_page` | query | integer | no | Rows per page, 1 to 200 (100) | `50` |
| `page` | query | integer | no | Page number, from 1. Wins over cursor | `1` |
| `cursor` | query | string | no | The next_cursor from the previous answer |  |

| Field | Type |
|---|---|
| `country` | string |
| `season` | string |
| `matches` | integer |
| `home_win_rate` | number |
| `draw_rate` | number |
| `away_win_rate` | number |
| `home_goals_per_match` | number |
| `away_goals_per_match` | number |
| `home_goal_edge` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/stats/home-advantage?season=2025/26"
```

#### `GET /v1/stats/half-time-full-time` (paid plans)

Half-time and full-time. How often each half-time outcome ends in each full-time outcome, for a competition, season or country, with the comebacks.

Plans: every paid plan. Docs: https://handballapi.com/documentation/stats-half-time-full-time

| Parameter | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| `competition` | query | string | no | Competition id (cp_...) | `cp_00000000` |
| `season` | query | string | no | Season, such as 2025/26 (the latest with results) | `2025/26` |
| `country` | query | string | no | Country code | `de` |

| Field | Type |
|---|---|
| `half_time` | string (home, draw, away) |
| `full_time` | string (home, draw, away) |
| `matches` | integer |
| `rate` | number |

Errors: `bad_request`, `unauthorized`, `upgrade_required`, `unknown_parameter`, `rate_limited`, `quota_exceeded`.

```bash
curl -H "Authorization: Bearer YOUR_KEY" "https://api.handballapi.com/v1/stats/half-time-full-time?season=2025/26"
```

## Guides

### Quick start

Your first call in a minute: the key, the base address and the answer's shape. https://handballapi.com/documentation/quick-start

Every call goes to `https://api.handballapi.com/v1/...` with your key in a header.

```bash
curl -H "Authorization: Bearer YOUR_KEY" https://api.handballapi.com/v1/results/yesterday
```

Every answer has the same two parts: `data` (a list or one object) and `meta` (counts, paging and timing).

```json
{"data": [{"id": "mt_8kq2v7xd", "date_utc": "2026-10-06T18:00:00Z", "status": "finished",
  "competition": {"id": "cp_3m9t1bra", "name": "Liga NLB", "country": "si", "season": "2026/27"},
  "home": {"team_id": "tm_5h2c8wqe", "name": "RK Celje", "goals": 31, "ht": 15},
  "away": {"team_id": "tm_0d7r4kna", "name": "RD Riko Ribnica", "goals": 27, "ht": 13}}],
 "meta": {"count": 1, "next_cursor": null, "page": 1, "per_page": 100, "total": 1, "total_pages": 1,
  "next_page": null, "prev_page": null, "date": "2026-10-06", "took_ms": 6}}
```

The ids above are examples of the shape. Take a real match `id` from any list and ask for the match itself, or its player lines:

```bash
curl -H "Authorization: Bearer YOUR_KEY" https://api.handballapi.com/v1/matches/mt_8kq2v7xd
curl -H "Authorization: Bearer YOUR_KEY" https://api.handballapi.com/v1/matches/mt_8kq2v7xd/players
```

### Authentication

Sending your key in either of two headers, why never in the address, and rotating a key. https://handballapi.com/documentation/authentication

Send your key in one of two headers. Both work on every endpoint and on the MCP server.

`Authorization: Bearer YOUR_KEY`

```bash
curl -H "Authorization: Bearer YOUR_KEY" https://api.handballapi.com/v1/results/yesterday
```

`X-API-Key: YOUR_KEY`

```bash
curl -H "X-API-Key: YOUR_KEY" https://api.handballapi.com/v1/results/yesterday
```

A key in the address (`?api_key=`, `?key=`) is refused with `400 bad_request`, so keys never end up in logs or browser history. A missing, unknown or revoked key is `401 unauthorized`.

Your plan is read from your account on every call, so an upgrade works on your next request with the same key.

##### Rotating a key

Make a new key in your account under Keys, move your app over to it, then revoke the old one. A revoked key stops at once with `401 unauthorized`. All your keys share your plan's limits, and each call is counted against the key that made it, so you can see which app is busy.

The key you make in your account is saved for these documentation pages in your own browser, so Try it works with it straight away.

`GET /v1/usage` tells a key about itself: plan, calls today and this month, the limits, when they reset and how far back its results reach. It is never counted against your allowance.

### Plans and limits

What each plan reaches, its requests a minute and calls a day, and the headers on every answer. https://handballapi.com/documentation/plans-and-limits

| Plan | Price | Results reach back | Requests a minute | Calls a day | Endpoints |
|---|---|---|---|---|---|
| Free key | free | yesterday and today | 10 | 50 | the free ones |
| Results | not on sale yet | 400 days | 60 | 5,000 | all |
| Archive | not on sale yet | the whole archive | 120 | 25,000 | all |

Every answer carries:

- `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (Unix seconds): this minute's requests.
- `X-Quota-Remaining`: calls left today. The day resets at 00:00 UTC.

Over the minute is `429 rate_limited`; the day used up is `429 quota_exceeded`. Both carry `Retry-After` in seconds. Asking past your plan's reach (an older date, or an endpoint your plan does not have) is `403 upgrade_required`, and `error.plan` names the plan that has it.

### Pagination

Pages and cursors on every list. https://handballapi.com/documentation/pagination

Every list takes `per_page` (1 to 200, 100 by default) and either `page` (from 1) or `cursor`. If both are sent, `page` wins.

A first call returns in `meta`: `count`, `next_cursor`, `page`, `per_page`, `total`, `total_pages`, `next_page` and `prev_page` (`null` at the ends).

To walk a long list, pass `meta.next_cursor` back as `cursor` until it is `null`. A cursor call returns only `count` and `next_cursor`, which keeps every page fast.

An empty list is a `200` with `meta.count` 0, never a 404.

### Errors

The error shape and every code, fixed for v1. https://handballapi.com/documentation/errors

Every error has the same shape. The `code` is for code and never changes in v1; the `message` is for people.

```json
{"error": {"code": "upgrade_required", "message": "This match is on the Results plan. Plans: https://handballapi.com/pricing",
  "plan": "results", "docs": "https://handballapi.com/documentation/errors#upgrade_required"}}
```

| Code | HTTP | Meaning |
|---|---|---|
| `bad_request` | 400 | A value is wrong: a bad date, an unknown country, a key sent in the address. The message says what was expected. |
| `unauthorized` | 401 | No key was sent, or the key is not valid or has been revoked. |
| `upgrade_required` | 403 | Your plan does not reach this: an endpoint or a date further back. error.plan names the plan that does. |
| `not_found` | 404 | No endpoint at that address, or no finished match with that id. |
| `method_not_allowed` | 405 | The API only answers GET. |
| `unknown_parameter` | 422 | A parameter the endpoint does not take. The message lists the ones it does. |
| `rate_limited` | 429 | Too many requests this minute. Wait for Retry-After seconds. |
| `quota_exceeded` | 429 | Today's calls are used up. They reset at 00:00 UTC; Retry-After says when. |
| `server_error` | 500 | Something went wrong on our side. It has been logged; try again shortly. |

### Results

Finished matches by day, by the last few days or yesterday, filtered by country, and how to walk a busy day. https://handballapi.com/documentation/results

A result is a match that is over: `finished`, or `awarded` when it was given at the table. Matches appear after full time and never during play.

Three calls find them:

- `GET /v1/results/yesterday`: every match finished yesterday (UTC). The call to run each morning.
- `GET /v1/results/latest?days=3`: the last 1 to 7 days, newest first. Good for catching up after a gap.
- `GET /v1/results?date=2026-10-04`: one whole UTC day, every league.

All three take `country` (one of the codes in [Coverage](https://handballapi.com/documentation/coverage)) and page with `per_page`, `page` or `cursor` ([Pagination](https://handballapi.com/documentation/pagination)).

Each row carries the match `id` (`mt_`), its `date_utc`, the `competition` with its own `id` (`cp_`), `name`, `country` and `season`, and the `home` and `away` sides with `team_id` (`tm_`), `name`, `goals` and `ht`, the goals at half-time where the source published them, else `null`.

###### Common jobs

- A nightly import: call `results/yesterday` once a day and store rows by `id`. Ids never change, so a second run is safe.
- A league table: collect a competition's results by `competition.id` and `season`; two points a win and one a draw is the usual handball count.
- A team's form: filter stored rows by `team_id` on either side, newest first.

The free key reaches yesterday and today; older dates are on the paid plans ([Plans and limits](https://handballapi.com/documentation/plans-and-limits)).

### Matches

One match in full: venue, crowd, referees, shootout and discipline. https://handballapi.com/documentation/matches

`GET /v1/matches/{id}` returns one finished match: everything in a results row, plus

- `venue` and `attendance`, where published;
- `referees`, a list of names, where published;
- `shootout`, home and away goals when a match went to 7m throws, else `null`;
- `discipline`: `indoor`, `beach` or `wheelchair`;
- `player_lines`: how many player lines it has. When it is above 0, call its [player lines](https://handballapi.com/documentation/match-players).

Take the `id` from any results row. An id that is not ours, a match not yet played, or a competition on the not-collected list all answer `404 not_found`, so nothing is given away about what is not served.

The free key reaches matches from yesterday and today.

### Players and goalkeepers

Player lines: scorers, 7m throws, cards, and goalkeepers with saves and save rate. https://handballapi.com/documentation/players

`GET /v1/matches/{id}/players` returns a line for every player listed for the match, with `team=home` or `team=away` to take one side.

Each line has the player's own `player_id` (`pl_`), `team`, `name`, `shirt` and `position`, then `goals`, `shots`, `seven_m_goals`, `seven_m_shots`, `assists`, `yellow`, `two_min` and `red`. Goalkeepers also carry `saves`, `shots_faced` and `save_rate` (saves divided by shots faced).

Positions are our own codes: `GK`, `LW`, `LB`, `CB`, `RB`, `RW` and `PV` (pivot), or `null` where not known. A figure the match sheet did not carry is `null`, never 0, so a missing number is never mistaken for none.

###### Common jobs

- Top scorers: sum `goals` by `player_id` over a competition's matches.
- Goalkeeper tables: sum `saves` and `shots_faced` by `player_id`, then divide; leave out keepers under a minimum of shots.
- Discipline: count `two_min` and `red` by team.

Player lines are on the paid plans ([Plans and limits](https://handballapi.com/documentation/plans-and-limits)). `player_lines` on [one match](https://handballapi.com/documentation/match) says whether a match has any.

##### A player across matches

The sums are compiled every night from the lines held, so these calls never count across the archive while you wait.

- `GET /v1/players?q=hansen`: find a player by part of the name. Free key.
- `GET /v1/players/{id}`: one player, with the latest team, matches, goals and dates. Free key.
- `GET /v1/players/{id}/matches`: every match the player has a line for, newest first, with the line itself.
- `GET /v1/players/{id}/seasons`: the sums per season, competition and team.
- `GET /v1/players/{id}/career`: the totals, and per competition, across everything held.

##### Leaders

- `GET /v1/players/leaders?stat=goals&season=2025/26`: the top players by `goals`, `seven_m_goals`, `assists` or `two_min`, for one season or all time, one country or all.
- `GET /v1/goalkeepers/leaders?season=2025/26&min_shots=100`: the best save rates among keepers who faced at least `min_shots` shots.

A season looks like `2025/26`; calendar-year leagues use the year alone. Without a season, leaders count everything held, which needs a plan that reaches the whole archive.

### Competitions and seasons

Leagues and cups: finding them, their seasons, tables, leaders, form, figures and records. https://handballapi.com/documentation/competitions-and-seasons

A competition is a league or a cup in one country, with its own permanent id (`cp_`). Its `kind` is `league` or `cup`; a cup is played as knockout and has no table.

##### Finding one

- `GET /v1/competitions?country=de&gender=women`: every competition with results, filtered by country, men or women, or part of the name (`q`).
- `GET /v1/countries/{code}/competitions`: the same for one country, the busiest first.
- `GET /v1/competitions/{id}`: one competition, with its latest season.
- `GET /v1/competitions/{id}/seasons`: every season held, with matches, teams, dates and how many matches carry player lines.

##### A season

Every call below takes `season` (such as `2025/26`); without it, the latest season with results is used.

- Results and fixtures: `/results` and `/fixtures`.
- The clubs: `/teams`.
- Tables: `/table` overall, `/home-away` for home and away matches apart, and `/form` for each team's last five and current run. Two points a win and one a draw, ordered by points, goal difference and goals scored.
- Players: `/scorers`, `/goalkeepers` (save rates, with `min_shots`), `/seven-metres`, `/assists` (where the league publishes them) and `/discipline`.
- The season in figures: `/stats` (goals a match, home and away goals, home win, draw and away win rates, average crowd), `/records` (biggest win, highest and lowest scoring, largest crowd) and `/attendance` (crowds by home team).

Tables, form, figures and leaders are compiled every night from the results and player lines held; their `meta.compiled_at` says when.

### Teams and form

Clubs: finding them, their results and fixtures, squads, season figures, form, runs and head to head. https://handballapi.com/documentation/teams-and-form

A team is one side of a club, men or women, with its own permanent id (`tm_`). It keeps that id across every competition it plays in.

##### Finding one

- `GET /v1/teams?q=kiel` or `?country=de`: teams by part of the name or by country, with matches held and dates.
- `GET /v1/teams/{id}`: one team and the competitions it played in.

##### Matches

- `/results` (with `season` to narrow it) and `/fixtures`.
- `GET /v1/matches?team={id}&from=2026-09-01`: matches by team, competition, season and dates, finished or scheduled.
- `/head-to-head?opponent={id}`: every meeting of two teams, with the summary from the first team's side.

##### The season and the club's history

- `/squad` and `/scorers`: every player with a line for the team in a season, and the leading scorers.
- `/stats`: the record per competition, home and away, goals a match, form and current run.
- `/seasons`: every season the team played, per competition.
- `/form?last=10`: the last results in every competition, each marked `W`, `D` or `L`.
- `/streaks`: the current run, and the longest winning, unbeaten and losing runs across everything held.

Squads, figures and runs are compiled every night; `meta.compiled_at` says when.

### Referees and venues

The referees of each match and their record, and the halls matches are played in. https://handballapi.com/documentation/referees-and-venues

Referees and halls get their own permanent ids: `rf_` for a referee and `vn_` for a hall. A name is matched the same way every time, so one referee keeps one id across seasons and competitions.

##### Referees

- `GET /v1/matches/{id}/officials`: the referees of one match, each with a `referee_id`.
- `GET /v1/referees?q=nygaard` or `?country=de`: referees by part of the name or by country.
- `GET /v1/referees/{id}` and `/matches`: one referee, and every result they took charge of.
- `GET /v1/referees/{id}/stats`: the record: home win, draw and away win rates and goals a match, and 2 minute suspensions and 7m throws a match where the matches carry player lines, with a line per season.

##### Venues

- `GET /v1/venues?country=dk` or `?q=arena`: halls by country or part of the name, with matches held and dates.
- `GET /v1/venues/{id}/matches`: every result played in a hall.

A hall is known by its name as published, so a hall that changed its name appears under both. Referees and halls are linked to matches every night.

### League stats

League-wide figures: home advantage and half-time against full-time, the seasons held, and keeping a copy in step. https://handballapi.com/documentation/league-stats

These calls answer questions across many matches at once. Each takes `competition`, `season` and `country` to narrow it; without a season they count everything held, which needs a plan that reaches the whole archive.

- `GET /v1/stats/home-advantage?season=2025/26`: home win, draw and away win rates and home and away goals a match, by country and season (20 matches or more).
- `GET /v1/stats/half-time-full-time?country=de`: the nine half-time and full-time outcomes, how often each happens, and the comebacks: a side behind at half-time that won.

##### The archive and its changes

- `GET /v1/meta/seasons`: every season held, with matches and the countries it covers.
- `GET /v1/updates?since=2026-10-28T06:00:00Z`: every match added or changed since a time, up to 7 days back, oldest change first. Store `meta.next_since` and pass it next time to keep a copy in step without fetching everything again.

The figures are compiled every night from the results held.

### Coverage

What the archive holds and what it never holds. https://handballapi.com/documentation/coverage

Handball API is results and history. A match is served once it is over (finished, or awarded), never during play: there is no live score, no in-play feed and no betting data on any plan.

The figures are counted from the data on every call to `GET /v1/meta/coverage`: matches, results and player lines by country, with the first and latest dates.

Countries and groups you can filter by with `country=`:

- `dk`: Denmark
- `se`: Sweden
- `si`: Slovenia
- `hr`: Croatia
- `cz`: Czech Republic
- `tr`: Turkey
- `gr`: Greece
- `br`: Brazil
- `de`: Germany
- `sk`: Slovakia
- `rs`: Serbia
- `es`: Spain
- `ch`: Switzerland
- `ihf`: International
- `history`: History

Never collected, from any source, on any plan:

- Handball-Bundesliga
- EHF competitions
- Superliga (Poland, men and women)
- Austrian Handball Leagues (HLA Meisterliga, HLA Challenge)
- Liga ASOBAL (Spain, men's top league, its cup and super cup)
- Czech men's Extraliga and the Czech cups (men and women)

Ids are our own (`mt_` matches, `tm_` teams, `cp_` competitions, `pl_` players, `rf_` referees, `vn_` venues) and stay the same for good.

### Changelog

Every change to the API, newest first. v1 only ever gains fields. https://handballapi.com/documentation/changelog

Nothing in v1 is ever renamed, retyped or removed; changes only add.

| Date | Change | What |
|---|---|---|
| 2026-10-28 | [Fifty more endpoints](https://handballapi.com/documentation/competitions-and-seasons) | Competitions, teams, players, referees and venues: seasons, home and away tables, form, runs, leaders, goalkeepers, discipline, season figures and records, match search, officials, home advantage, half-time and full-time, and changes since a time. Referees and halls get permanent ids, rf_ and vn_. |
| 2026-10-09 | [Fixtures, tables, scorers, head to head](https://handballapi.com/documentation/fixtures) | GET /v1/fixtures, league tables and top scorers by competition and season, head to head between two teams, and kick-off in local time on every match. |
| 2026-10-07 | [Documentation](https://handballapi.com/documentation) | A page for every endpoint and guide, with Try it, search and real example answers. |
| 2026-10-07 | [MCP server and agent skill](https://handballapi.com/documentation/mcp) | Six tools at /mcp, and the skill at /skill.md for Claude and other agents. |
| 2026-10-07 | [Plans and limits](https://handballapi.com/documentation/plans-and-limits) | Requests a minute and calls a day on every answer's headers, and GET /v1/usage. |
| 2026-10-07 | [v1](https://handballapi.com/documentation/quick-start) | Results, matches, player lines and coverage, with permanent ids for everything. |

### MCP server

Using Handball API from Claude, Cursor and other agents over the Model Context Protocol. https://handballapi.com/documentation/mcp

The MCP server is at `https://handballapi.com/mcp` (JSON-RPC 2.0 over HTTP POST). Send your key as `Authorization: Bearer YOUR_KEY`; each tool call is an API call on your plan, with the same limits.

For Claude Code:

```bash
claude mcp add --transport http handballapi https://handballapi.com/mcp --header "Authorization: Bearer YOUR_KEY"
```

The tools:

- `yesterdays_results`: Every match finished yesterday (UTC), newest first.
- `latest_results`: Matches finished in the last days, newest first. Results only: served after full time.
- `results_on_day`: Every match finished on one day (UTC). The free key reaches yesterday and today.
- `get_match`: Score, half-time, date, venue, crowd, referees and shootout of one finished match.
- `match_players`: A line for every player listed for the match: goals, shots, 7m, assists, cards, and saves and shots faced for goalkeepers.
- `fixtures`: Matches scheduled in the coming days, soonest first, with throw-off in UTC and in the league's own time.
- `league_table`: The table of a competition and season, computed from the results held: played, won, drawn, lost, goals and points.
- `top_scorers`: The leading scorers of a competition and season, from the player lines held, with matches, 7m goals and goals a match.
- `head_to_head`: Every finished match between two teams, newest first, with a summary from the first team's side: won, drawn, lost and goals.
- `coverage`: What the archive holds, counted from the data: matches, results and player lines by country, and what is never collected.
- `search_matches`: Matches by team, competition, season and dates, finished or scheduled. Give at least one of team, competition, season or from.
- `match_officials`: The referees of one finished match, each with our referee id where the name is known to us.
- `find_competitions`: Every competition with results, with country, men or women, league or cup, seasons and dates held.
- `competition_seasons`: Every season held for a competition, newest first: matches, teams, dates and how many matches have player lines.
- `top_goalkeepers`: The best save rates of a competition and season, among goalkeepers who faced at least min_shots shots.
- `home_away_table`: Two tables for a competition and season: home matches only and away matches only.
- `league_form`: Every team of a competition and season with its last five results and its current run.
- `season_stats`: A competition season in figures: goals a match, home and away goals, home win, draw and away win rates, average crowd.
- `find_teams`: Teams by part of the name or by country, with matches held and dates.
- `team_results`: Every result of a team, newest first, in every competition held.
- `team_fixtures`: A team's matches still to be played, soonest first.
- `team_squad`: Every player with a line for the team in a season, with matches and goals.
- `team_stats`: A team's season per competition: record, goals, home and away, goals a match, form and current run.
- `team_form`: A team's last results in every competition, newest first, each marked won, drawn or lost.
- `player_leaders`: The leading players across every competition held, or one season or country: goals, 7m goals, assists or 2 minute suspensions.
- `find_players`: Players by part of the name, with matches, goals and their last match.
- `player_career`: A player's career totals, and per competition, across everything held.
- `find_referees`: Referees by part of the name or by country, with matches held and dates.
- `referee_stats`: A referee's record: home win, draw and away win rates, goals a match, and 2 minute suspensions and 7m throws a match where player lines are held.
- `home_advantage`: Home win, draw and away win rates and home and away goals a match, by country and season.

Every tool with its arguments, the endpoint it calls and the plan it needs: [MCP tools](https://handballapi.com/documentation/mcp-tools).

A refusal (your plan, a limit, a match not found) comes back as a tool result with `isError`, with the reason in words.

### Use with Claude and agents

The agent skill: one file that teaches an agent to use Handball API. https://handballapi.com/documentation/agent-skill

The agent skill is one markdown file that teaches an AI agent how to use Handball API: the key, the calls that answer common questions, the limits and the errors.

- Download: https://handballapi.com/skill.md
- Discovery index: https://handballapi.com/.well-known/agent-skills/index.json

For Claude Code, save it as `~/.claude/skills/handballapi/SKILL.md`. In Claude's apps, upload it as a skill in settings.

## Errors

Every error is `{"error": {"code", "message", "plan"?, "docs"}}`. The full list: https://handballapi.com/documentation/errors

## About this document

Generated from the endpoint registry, the guides and the plans configuration. The Generated date above is the newest change to those sources, so a copy with an older date is stale. Machine-readable alternatives: https://handballapi.com/openapi.json and the MCP server at https://handballapi.com/mcp. Operated by DeveloperData.net.
