API example
Soccer endpoints
All Soccer endpoints live under https://api.balldontlie.io/stories/soccer/competitions/{competition}. Every request requires a Bearer API key in the Authorization header.
One soccer subscription covers EPL, Bundesliga, La Liga, Ligue 1, Serie A, MLS, UEFA Champions League, and the FIFA World Cup.
List soccer competitions
Returns the soccer competitions included in the StoryStats soccer package. Use the returned key as the :competition path parameter.
/stories/soccer/competitionsExample request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.balldontlie.io/stories/soccer/competitions"Example response
{
"data": [
{
"key": "epl",
"name": "Premier League"
},
{
"key": "bundesliga",
"name": "Bundesliga"
},
{
"key": "laliga",
"name": "La Liga"
},
{
"key": "ligue1",
"name": "Ligue 1"
},
{
"key": "seriea",
"name": "Serie A"
},
{
"key": "mls",
"name": "MLS"
},
{
"key": "ucl",
"name": "UEFA Champions League"
},
{
"key": "world_cup",
"name": "FIFA World Cup"
}
]
}Response schema
data
Available soccer competitions for this package.
| Field | Type | Description |
|---|---|---|
| key | string | Competition slug. Pass this value as :competition in soccer story paths. |
| name | string | Display name for the competition. |
List soccer games
Returns all games for a soccer competition on a given date. Use this endpoint first to discover game IDs for story requests. The same route supports club competitions and the FIFA World Cup.
/stories/soccer/competitions/{competition}/gamesQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| date | string | Yes | ISO-8601 calendar date in YYYY-MM-DD format (e.g. 2022-12-18). |
| timezone | string | No | IANA timezone name used to resolve the date boundary. Defaults to UTC. |
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.balldontlie.io/stories/soccer/competitions/world_cup/games?date=2022-12-18&timezone=UTC"Example response
{
"competition": "world_cup",
"data": [
{
"id": 999,
"home_team": {
"id": 37,
"name": "Argentina",
"short_name": "ARG",
"abbreviation": "ARG",
"location": "ARG"
},
"away_team": {
"id": 33,
"name": "France",
"short_name": "FRA",
"abbreviation": "FRA",
"location": "FRA"
},
"start_time": "2022-12-18T15:00:00.000Z"
}
]
}Response schema
competition
Competition slug from the :competition path parameter. Soccer package access includes every listed competition.
| Field | Type | Description |
|---|---|---|
| competition | string | One of epl, bundesliga, laliga, ligue1, seriea, mls, ucl, or world_cup. |
data
Games scheduled on the requested date, ordered by start_time ascending.
| Field | Type | Description |
|---|---|---|
| id | integer | Game identifier. Pass this value as :game_id to the story endpoints below. |
| home_team | object | Home team. See Team below. |
| away_team | object | Away team. See Team below. |
| start_time | string (date-time) | Scheduled match start in RFC 3339 format. The UTC offset reflects the timezone query parameter. |
Team
Returned on both home_team and away_team for every soccer game.
| Field | Type | Description |
|---|---|---|
| id | integer | Stable BallDontLie team identifier. |
| name | string | Display name for the club or national team. |
| short_name | string| null | Short display name when available. |
| abbreviation | string| null | Team abbreviation when available. |
| location | string| null | Country, region, or city label when available. |
Get soccer pregame story
Returns a single aggregated pregame story for a soccer match. Generated before kickoff; returns 404 if the story has not been generated yet. The World Cup response below illustrates the 200 response shape after a story is generated.
/stories/soccer/competitions/{competition}/games/{game_id}/pregameQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| audience | string | No | Either betting or stats. Defaults to betting. |
| tone | string | No | Either editorial or humor. Defaults to editorial. |
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.balldontlie.io/stories/soccer/competitions/world_cup/games/999/pregame?audience=betting&tone=editorial"Example response
{
"competition": "world_cup",
"game": { "id": 999 },
"story": {
"id": 310001,
"created_at": "2022-12-18T14:15:00.000Z",
"content": "Argentina-France opens with a trophy on the line, matching a disciplined favorite against a defending champion carrying finishing power into the final.",
"entity_tags": {
"teams": [
{ "id": 37, "name": "Argentina", "abbreviation": "ARG" },
{ "id": 33, "name": "France", "abbreviation": "FRA" }
],
"players": []
}
}
}Response schema
competition
Competition slug from the :competition path parameter. Soccer package access includes every listed competition.
| Field | Type | Description |
|---|---|---|
| competition | string | One of epl, bundesliga, laliga, ligue1, seriea, mls, ucl, or world_cup. |
game
Compact reference to the game this response is scoped to. Echoes the :game_id path parameter.
| Field | Type | Description |
|---|---|---|
| id | integer | Game identifier matching the one supplied in the request path. |
story
The single narrative object for this phase. Deterministic for a given (game_id, audience, tone) tuple.
| Field | Type | Description |
|---|---|---|
| id | integer | Stable story identifier. Safe to use as an idempotency key. |
| created_at | string (date-time) | RFC 3339 timestamp (UTC) marking when the narrative was written. |
| content | string| null | Tweet-length narrative body (≤280 characters). Null only in the rare case that the requested tone has not yet been rendered for this story. |
| entity_tags | object | Teams and players referenced in content. See entity_tags below. |
entity_tags
Structured list of the teams and players referenced in the narrative. Use the IDs to join to the corresponding BallDontLie sport APIs.
| Field | Type | Description |
|---|---|---|
| teams | array<object> | Teams mentioned in the story. Each element is { id: integer, name: string, abbreviation: string }. |
| players | array<object> | Players mentioned in the story. Each element is { id: integer, name: string, team?: string }, where team is the abbreviation when known. |
Get soccer live stories
Returns event-driven live stories for a soccer match, sorted oldest to newest by created_at. Returns an empty array if no live stories have been generated yet. The World Cup response below illustrates the live story shape after events have fired.
/stories/soccer/competitions/{competition}/games/{game_id}/liveQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| audience | string | No | Either betting or stats. Defaults to betting. |
| tone | string | No | Either editorial or humor. Defaults to editorial. |
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.balldontlie.io/stories/soccer/competitions/world_cup/games/999/live?audience=betting&tone=editorial"Example response
{
"competition": "world_cup",
"game": { "id": 999 },
"data": [
{
"id": 310014,
"created_at": "2022-12-18T16:47:00.000Z",
"type": "goal",
"content": "France answer late to pull Argentina-France level at 2-2, turning a controlled final into a tense closing stretch with the trophy still loose.",
"entity_tags": {
"teams": [
{ "id": 37, "name": "Argentina", "abbreviation": "ARG" },
{ "id": 33, "name": "France", "abbreviation": "FRA" }
],
"players": []
},
"game_snapshot": {
"period": 2,
"home_score": 2,
"away_score": 2,
"minutes_remaining": 8,
"clock": "82:00"
}
}
]
}Response schema
competition
Competition slug from the :competition path parameter. Soccer package access includes every listed competition.
| Field | Type | Description |
|---|---|---|
| competition | string | One of epl, bundesliga, laliga, ligue1, seriea, mls, ucl, or world_cup. |
game
Compact reference to the game this response is scoped to. Echoes the :game_id path parameter.
| Field | Type | Description |
|---|---|---|
| id | integer | Game identifier matching the one supplied in the request path. |
data
Array of live stories for the game, ordered oldest to newest by created_at. Empty if no live stories have fired yet.
| Field | Type | Description |
|---|---|---|
| id | integer | Stable story identifier. Safe to use as an idempotency key. |
| created_at | string (date-time) | RFC 3339 timestamp (UTC) marking when the narrative was written. |
| type | string | Detection module that produced this story (e.g. game_over, close_game, prop_exceeded, batter_breakout). Useful for routing stories into downstream product surfaces. |
| content | string| null | Tweet-length narrative body (≤280 characters). Null only in the rare case that the requested tone has not yet been rendered for this story. |
| entity_tags | object | Teams and players referenced in content. See entity_tags below. |
| game_snapshot | object | Score and clock at the moment the story fired. See game_snapshot below. |
entity_tags
Structured list of the teams and players referenced in the narrative. Use the IDs to join to the corresponding BallDontLie sport APIs.
| Field | Type | Description |
|---|---|---|
| teams | array<object> | Teams mentioned in the story. Each element is { id: integer, name: string, abbreviation: string }. |
| players | array<object> | Players mentioned in the story. Each element is { id: integer, name: string, team?: string }, where team is the abbreviation when known. |
game_snapshot
Point-in-time state of the game when the story was generated. Useful for rendering a score banner alongside the narrative.
| Field | Type | Description |
|---|---|---|
| home_score | integer | Home team score at the moment the story fired. |
| away_score | integer | Away team score at the moment the story fired. |
| period | integer | Match phase: 1-2 for regulation, 3-4 for extra time, and 5 for a penalty shootout. |
| minutes_remaining | integer | Whole minutes remaining in the current period. |
| clock | string| null | Raw game-clock string when available (e.g. "6:22"). Present on most live triggers; may be absent on period-boundary events. |
Get soccer postgame story
Returns the most recent postgame story after a soccer match is final. Returns 404 if no postgame story has been generated yet. The World Cup response below illustrates the 200 response shape after a recap is generated.
/stories/soccer/competitions/{competition}/games/{game_id}/postgameQuery parameters
| Name | Type | Required | Description |
|---|---|---|---|
| audience | string | No | Either betting or stats. Defaults to betting. |
| tone | string | No | Either editorial or humor. Defaults to editorial. |
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://api.balldontlie.io/stories/soccer/competitions/world_cup/games/999/postgame?audience=betting&tone=editorial"Example response
{
"competition": "world_cup",
"game": { "id": 999 },
"story": {
"id": 310030,
"created_at": "2022-12-18T18:15:00.000Z",
"content": "Argentina and France finish level at 3-3 after extra time, capping a final that swung from Argentina control to a late French surge before penalties.",
"entity_tags": {
"teams": [
{ "id": 37, "name": "Argentina", "abbreviation": "ARG" },
{ "id": 33, "name": "France", "abbreviation": "FRA" }
],
"players": []
}
}
}Response schema
competition
Competition slug from the :competition path parameter. Soccer package access includes every listed competition.
| Field | Type | Description |
|---|---|---|
| competition | string | One of epl, bundesliga, laliga, ligue1, seriea, mls, ucl, or world_cup. |
game
Compact reference to the game this response is scoped to. Echoes the :game_id path parameter.
| Field | Type | Description |
|---|---|---|
| id | integer | Game identifier matching the one supplied in the request path. |
story
The single narrative object for this phase. Deterministic for a given (game_id, audience, tone) tuple.
| Field | Type | Description |
|---|---|---|
| id | integer | Stable story identifier. Safe to use as an idempotency key. |
| created_at | string (date-time) | RFC 3339 timestamp (UTC) marking when the narrative was written. |
| content | string| null | Tweet-length narrative body (≤280 characters). Null only in the rare case that the requested tone has not yet been rendered for this story. |
| entity_tags | object | Teams and players referenced in content. See entity_tags below. |
entity_tags
Structured list of the teams and players referenced in the narrative. Use the IDs to join to the corresponding BallDontLie sport APIs.
| Field | Type | Description |
|---|---|---|
| teams | array<object> | Teams mentioned in the story. Each element is { id: integer, name: string, abbreviation: string }. |
| players | array<object> | Players mentioned in the story. Each element is { id: integer, name: string, team?: string }, where team is the abbreviation when known. |