# football-api

A minimal Python client for the [football-data.org](https://www.football-data.org) API v4.

Provides both **sync** and **async** interfaces with full type safety via [Pydantic](https://docs.pydantic.dev) models.

## Installation

```bash
pip install football-api
```

## Quick Start

### Sync

```python
from football_api import FootballClient

with FootballClient(api_key="YOUR_TOKEN") as client:
    # Premier League standings
    standings = client.get_standings("PL")
    for entry in standings.standings[0].table:
        print(f"{entry.position}. {entry.team.name} — {entry.points} pts")

    # Today's matches
    matches = client.get_matches()
    for m in matches.matches:
        print(f"{m.home_team.name} vs {m.away_team.name} [{m.status}]")
```

### Async

```python
import asyncio
from football_api import AsyncFootballClient

async def main():
    async with AsyncFootballClient(api_key="YOUR_TOKEN") as client:
        comp = await client.get_competition("PL")
        print(comp.name, comp.current_season.current_matchday)

asyncio.run(main())
```

### Environment Variable

Instead of passing `api_key` directly, set `FOOTBALL_DATA_API_KEY`:

```bash
export FOOTBALL_DATA_API_KEY="your-token-here"
```

```python
client = FootballClient()  # reads from env
```

## API Methods

| Method | Description |
|--------|-------------|
| `get_areas()` | List all areas |
| `get_area(id)` | Get area by ID |
| `get_competitions(areas=...)` | List competitions |
| `get_competition(id)` | Get competition by ID or code |
| `get_standings(comp_id, season=..., matchday=...)` | League table |
| `get_scorers(comp_id, season=..., limit=...)` | Top scorers |
| `get_matches(date_from=..., date_to=..., status=...)` | List matches |
| `get_match(id)` | Get single match |
| `get_head2head(match_id, limit=...)` | Head-to-head history |
| `get_competition_matches(comp_id, matchday=..., stage=...)` | Competition matches |
| `get_team(id)` | Get team details |
| `get_competition_teams(comp_id, season=...)` | Teams in competition |
| `get_team_matches(team_id, venue=..., status=...)` | Team matches |
| `get_person(id)` | Get person (player/coach/referee) |
| `get_person_matches(person_id, competitions=..., limit=...)` | Person matches |

All methods are available on both `FootballClient` (sync) and `AsyncFootballClient` (async).

## Error Handling

```python
from football_api import FootballClient, NotFoundError, RateLimitError

with FootballClient(api_key="YOUR_TOKEN") as client:
    try:
        team = client.get_team(99999)
    except NotFoundError:
        print("Team not found")
    except RateLimitError:
        print("Rate limit exceeded, slow down")
```

**Exception hierarchy:**

- `FootballAPIError` — base for all API errors
  - `AuthenticationError` — invalid or missing token (HTTP 403)
  - `NotFoundError` — resource not found (HTTP 404)
  - `RateLimitError` — rate limit exceeded (HTTP 429)
  - `ServerError` — server-side errors (HTTP 5xx)

## Supported Competitions

The free tier includes several major leagues and competitions. See [football-data.org](https://www.football-data.org/coverage) for the full list.

## Development

```bash
git clone https://github.com/ice1x/football-api.git
cd football-api
pip install -e ".[dev]"
pytest
```

## License

[MIT](LICENSE)
