A Python wrapper for accessing and processing Kinexon Handball data. This library provides a clean, type-safe interface to interact with the Kinexon API for handball analytics and position data.
- 🔐 Secure Authentication: Dual-layer authentication system with session and main login
- 📊 Data Export: Export position data, metrics, and events in various formats
- 🏃 Team Management: Access team IDs and session information
- 🛡️ Error Handling: Comprehensive error handling with custom exceptions
- ⚡ Performance: Built-in retry logic and connection pooling
- 🧪 Testing: Full test suite with integration and unit tests
- 📦 Type Safety: Full type hints and Pydantic validation
- Python 3.12 or higher
uv
as package manager- Valid Kinexon API credentials
git clone https://github.com/mad4ms/KinexonHandballAPI.git
cd KinexonHandballAPI
uv pip install -e .
from kinexon_handball_api.client import KinexonClient
from kinexon_handball_api.config import Settings
# Initialize settings from environment variables
settings = Settings()
# Create client instance
client = KinexonClient(settings)
# Get available teams
# Fetches a hardcoded DEFAULT_TEAM_IDS specified in fetchers.py
teams = client.get_team_ids()
print(f"Available teams: {len(teams)}")
# Get session IDs for a team
sessions = client.get_session_ids(
team_id=13, # Füchse Berlin
start="2025-01-01",
end="2025-01-31"
)
# Get position data
position_data = client.get_position_data_by_session_id("session_123")
Create a .env
file with your Kinexon credentials:
# Session Authentication
USERNAME_KINEXON_SESSION=your_session_username
PASSWORD_KINEXON_SESSION=your_session_password
ENDPOINT_KINEXON_SESSION=https://api.kinexon.com/session
# Main Authentication
USERNAME_KINEXON_MAIN=your_main_username
PASSWORD_KINEXON_MAIN=your_main_password
ENDPOINT_KINEXON_MAIN=https://api.kinexon.com/login
# API Configuration
ENDPOINT_KINEXON_API=https://api.kinexon.com/api
API_KEY_KINEXON=your_api_key
Team IDs are stored in config/teams.yaml
and organized by season. To update team IDs for a new season:
- Go to Kinexon Cloud web app
- Click "Team" selection dropdown
- Click user → profile
- Switch to "Teams" tab
- Copy IDs next to team names
- Update
config/teams.yaml
with new season data
The current season is automatically used, or you can specify a season:
# Get current season teams
teams = client.get_team_ids()
# Get specific season teams
teams_2024 = client.get_team_ids("2024-25")
## Development
### Setup Development Environment
```bash
# Clone repository
git clone https://github.com/mad4ms/KinexonHandballAPI.git
cd KinexonHandballAPI
# Install development dependencies
uv pip install -e ".[dev]"
# Install pre-commit hooks (optional but recommended)
uv pip install pre-commit
pre-commit install
# Unit tests
pytest tests/test_client.py
# Integration tests (requires live API access)
pytest tests/test_integration_*.py -m integration
# All tests
pytest
import os
from datetime import datetime, timedelta
from kinexon_handball_api.client import KinexonClient
from kinexon_handball_api.config import Settings
# Load environment variables
from dotenv import load_dotenv
load_dotenv()
# Initialize client
settings = Settings()
client = KinexonClient(settings)
# Get all teams (current season)
teams = client.get_team_ids()
print(f"Found {len(teams)} teams")
# Get teams for specific season
teams_2024 = client.get_team_ids("2024-25")
print(f"Found {len(teams_2024)} teams in 2024-25 season")
# Get sessions for a specific team
team_id = 13 # Füchse Berlin
# Fetch any games of the last 30 days
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
# Fetch session ids of the last 30 days
sessions = client.get_session_ids(
team_id=team_id,
start=start_date.strftime("%Y-%m-%d"),
end=end_date.strftime("%Y-%m-%d")
)
print(f"Found {len(sessions)} sessions for team {team_id}")
# Get position data for each session
for session in sessions:
session_id = session["session_id"]
description = session["description"]
print(f"Getting position data for session: {description} ({session_id})")
# Mind that the download can take ages, as a file is usually around 150 MB.
# @Kinexon: 160MB in 7min = terrible
# Probably using RDBMS for time-series data?
# Time-series DB (or even PG timescaledb) + compression + proper indexes + streaming
# Kinda using a screwdriver to hammer nails
try:
position_data = client.get_position_data_by_session_id(
session_id=session_id,
)
# Save to file
filename = f"positions_{session_id}.csv"
with open(filename, "wb") as f:
f.write(position_data)
print(f"Saved {filename}")
except Exception as e:
print(f"Failed to get position data for session {session_id}: {e}")
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
- Follow PEP 8 style guidelines (enforced by flake8)
- Use Black for code formatting (88 character line length)
- Sort imports with isort (Black-compatible profile)
- Add type hints to all functions (enforced by mypy)
- Write tests for new functionality
- Update documentation for API changes
- Use conventional commit messages
The project includes pre-commit hooks that automatically run code quality checks:
# Install pre-commit hooks
uv pip install pre-commit
pre-commit install
# Run manually (optional)
pre-commit run --all-files
This ensures all code meets quality standards before commits.
This project is licensed under the MIT License - see the LICENSE file for details.
For support and questions:
- Create an issue on GitHub
- Review the test examples for usage patterns
- Initial release
- Basic API client functionality
- Authentication system
- Position data retrieval with progress tracking
- Team and session management
- Comprehensive test suite
- Improved error handling for large CSV downloads
- Kinexon for providing the handball analytics API