balancing-services


Namebalancing-services JSON
Version 1.4.0 PyPI version JSON
download
home_pageNone
SummaryOfficial Python client for accessing European electricity balancing market data via the Balancing Services REST API
upload_time2025-10-25 12:55:14
maintainerNone
docs_urlNone
authorBalancing Services Team
requires_python>=3.10
licenseMIT
keywords fcr afrr api balancing electricity energy europe grid imbalance mfrr market openapi power reserves
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Balancing Services Python Client

Python client library for the [Balancing Services REST API](https://api.balancing.services). Access European electricity balancing market data with a modern, type-safe Python interface.

## Features

- **Type-safe**: Full type hints for better IDE support and code quality
- **Modern Python**: Built with httpx and attrs for async support and clean data models
- **Auto-generated**: Generated from the official OpenAPI specification
- **Comprehensive**: Access to all API endpoints and data models
- **Well-documented**: Inline documentation and usage examples

## Installation

```bash
uv pip install balancing-services
```

Or with pip:

```bash
pip install balancing-services
```

For development, install from source:

```bash
cd clients/python
uv pip install -e .
```

## Quick Start

```python
from balancing_services import AuthenticatedClient
from balancing_services.api.default import get_imbalance_prices
from balancing_services.models import Area
from datetime import datetime

# Create an authenticated client
client = AuthenticatedClient(
    base_url="https://api.balancing.services/v1",
    token="YOUR_API_TOKEN"
)

# Get imbalance prices for Estonia
response = get_imbalance_prices.sync_detailed(
    client=client,
    area=Area.EE,
    period_start_at=datetime.fromisoformat("2025-01-01T00:00:00Z"),
    period_end_at=datetime.fromisoformat("2025-01-02T00:00:00Z")
)

if response.status_code == 200:
    data = response.parsed
    print(f"Query period: {data.queried_period.start_at} to {data.queried_period.end_at}")
    for imbalance_prices in data.data:
        print(f"Area: {imbalance_prices.area}, Direction: {imbalance_prices.direction}")
        for price in imbalance_prices.prices:
            print(f"  {price.period.start_at}: {price.price} {imbalance_prices.currency}")
```

## Authentication

To obtain an API token:
- **Email:** info@balancing.services
- **Website:** https://balancing.services

Include your token when creating the client:

```python
from balancing_services import AuthenticatedClient

client = AuthenticatedClient(
    base_url="https://api.balancing.services/v1",
    token="YOUR_API_TOKEN"
)
```

## Usage Examples

### Get Balancing Energy Bids with Pagination

```python
from balancing_services import AuthenticatedClient
from balancing_services.api.default import get_balancing_energy_bids
from balancing_services.models import Area, ReserveType
from datetime import datetime

client = AuthenticatedClient(base_url="https://api.balancing.services/v1", token="YOUR_TOKEN")

# First page
response = get_balancing_energy_bids.sync_detailed(
    client=client,
    area=Area.EE,
    period_start_at=datetime.fromisoformat("2025-01-01T00:00:00Z"),
    period_end_at=datetime.fromisoformat("2025-01-02T00:00:00Z"),
    reserve_type=ReserveType.AFRR,
    limit=100
)

if response.status_code == 200:
    data = response.parsed
    print(f"Has more: {data.has_more}")

    # Process first page
    for bid_group in data.data:
        for bid in bid_group.bids:
            print(f"Bid: {bid.volume} MW @ {bid.price} {bid_group.currency}")

    # Get next page if available
    if data.has_more and data.next_cursor:
        next_response = get_balancing_energy_bids.sync_detailed(
            client=client,
            area=Area.EE,
            period_start_at=datetime.fromisoformat("2025-01-01T00:00:00Z"),
            period_end_at=datetime.fromisoformat("2025-01-02T00:00:00Z"),
            reserve_type=ReserveType.AFRR,
            cursor=data.next_cursor,
            limit=100
        )
```

### Async Usage

```python
import asyncio
from balancing_services import AuthenticatedClient
from balancing_services.api.default import get_imbalance_prices
from balancing_services.models import Area
from datetime import datetime

async def fetch_prices():
    client = AuthenticatedClient(
        base_url="https://api.balancing.services/v1",
        token="YOUR_TOKEN"
    )

    response = await get_imbalance_prices.asyncio_detailed(
        client=client,
        area=Area.EE,
        period_start_at=datetime.fromisoformat("2025-01-01T00:00:00Z"),
        period_end_at=datetime.fromisoformat("2025-01-02T00:00:00Z")
    )

    if response.status_code == 200:
        return response.parsed
    return None

# Run async function
prices = asyncio.run(fetch_prices())
```

### Error Handling

```python
from balancing_services import AuthenticatedClient
from balancing_services.api.default import get_imbalance_prices
from balancing_services.models import Area
from datetime import datetime

client = AuthenticatedClient(base_url="https://api.balancing.services/v1", token="YOUR_TOKEN")

response = get_imbalance_prices.sync_detailed(
    client=client,
    area=Area.EE,
    period_start_at=datetime.fromisoformat("2025-01-01T00:00:00Z"),
    period_end_at=datetime.fromisoformat("2025-01-02T00:00:00Z")
)

if response.status_code == 200:
    data = response.parsed
    # Process successful response
elif response.status_code == 400:
    error = response.parsed
    print(f"Bad request: {error.detail}")
elif response.status_code == 401:
    print("Authentication failed - check your API token")
elif response.status_code == 429:
    print("Rate limited - please retry later")
else:
    print(f"Error {response.status_code}: {response.content}")
```

## Data Models

All response and request models are fully typed using attrs. Key models include:

- `ImbalancePricesResponse`, `ImbalanceTotalVolumesResponse`
- `BalancingEnergyVolumesResponse`, `BalancingEnergyPricesResponse`, `BalancingEnergyBidsResponse`
- `BalancingCapacityBidsResponse`, `BalancingCapacityPricesResponse`, `BalancingCapacityVolumesResponse`
- Enums: `Area`, `ReserveType`, `Direction`, `Currency`, `ActivationType`, `BidStatus`

## Development

### Regenerating the Client

The client is generated from the OpenAPI specification. To regenerate:

```bash
cd clients/python
./generate.sh
```

### Running Tests

```bash
# Install development dependencies
uv pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=balancing_services --cov-report=html
```

### Code Quality

```bash
# Format code
ruff format .

# Lint code
ruff check .

# Type checking
mypy balancing_services
```

### Automation Scripts

The Python client includes automation scripts for development and publishing:

#### `generate-pyproject.sh`
Generates `pyproject.toml` from the template with the current version from `openapi.yaml`.

**Note:** The version is stored in `openapi.yaml` (single source of truth). The `pyproject.toml.draft` template contains invalid TOML (`version = __VERSION__` without quotes) to prevent accidental use without proper generation.

```bash
./generate-pyproject.sh
```

This script is automatically called by `check.sh` and `test-and-publish.sh`.

#### `check.sh`
Runs all quality checks in one command:

```bash
./check.sh
```

Performs:
- Generates `pyproject.toml` from draft
- Runs tests with pytest
- Runs linting with ruff
- Runs type checking with mypy
- Verifies the package builds

#### `test-and-publish.sh`
Complete publishing workflow with TestPyPI validation:

**Setup:**
1. Copy `.env.sample` to `.env` and fill in your credentials:
   ```bash
   cp .env.sample .env
   # Edit .env and add:
   #   BALANCING_SERVICES_API_KEY (required - for testing against live API)
   #   UV_PUBLISH_TOKEN_TESTPYPI (required)
   #   UV_PUBLISH_TOKEN_PYPI (required)
   ```

2. Run the publish script:
   ```bash
   ./test-and-publish.sh
   ```

**Emergency option** - skip API tests if the server is down:
```bash
./test-and-publish.sh --skip-api-tests
```
⚠️ This skips testing against the live API. Use only in emergencies!

Alternatively, export variables manually:
```bash
export BALANCING_SERVICES_API_KEY="your-api-key"
export UV_PUBLISH_TOKEN_TESTPYPI="your-testpypi-token"
export UV_PUBLISH_TOKEN_PYPI="your-pypi-token"
./test-and-publish.sh
```

**What it does:**
1. Loads credentials from `.env` (if present)
2. Verifies all required environment variables are set
3. Runs quality checks
4. Publishes to TestPyPI using `UV_PUBLISH_TOKEN_TESTPYPI`
5. Creates isolated test sandbox
6. Installs package from TestPyPI
7. Runs all example scripts against live API using `BALANCING_SERVICES_API_KEY`
8. Prompts to publish to PyPI using `UV_PUBLISH_TOKEN_PYPI` if tests pass
9. Verifies production PyPI package by installing and running examples again

**Get your credentials:**
- API Key: https://balancing.services
- TestPyPI: https://test.pypi.org/manage/account/token/
- PyPI: https://pypi.org/manage/account/token/

**For maintainers:** See `../../scripts/README.md` for the complete release workflow.

## Troubleshooting

### Authentication Errors (401)

**Problem:** Receiving 401 Unauthorized responses

**Solutions:**
- Verify your API token is correct
- Check that the token is being passed to `AuthenticatedClient`
- Ensure your token hasn't expired (contact support if needed)

### Bad Request Errors (400)

**Problem:** Receiving 400 Bad Request responses

**Common causes:**
- Invalid date range (end date before start date)
- Date range too large
- Invalid area code or reserve type
- Malformed datetime strings

**Solution:** Check the error detail in the response for specific information:
```python
if response.status_code == 400:
    error = response.parsed
    print(f"Error detail: {error.detail}")
```

### Empty Results

**Problem:** Receiving 200 OK but no data

**Possible reasons:**
- No data available for the requested period
- Data not yet published for recent periods
- Requesting data for a period before data collection started

**Solution:** Try a different time period or check if data exists for your area

### Timeout Issues

**Problem:** Requests timing out

**Solutions:**
- Increase the client timeout:
```python
client = AuthenticatedClient(
    base_url="https://api.balancing.services/v1",
    token="YOUR_TOKEN",
    timeout=30.0  # Increase from default
)
```
- Reduce the date range in your request
- Use pagination for large datasets

### Type Errors with Enums

**Problem:** Type errors when passing area or reserve type

**Solution:** Use the provided enum classes:
```python
from balancing_services.models import Area, ReserveType

# Correct
area=Area.EE

# Incorrect
area="EE"  # String might work but not type-safe
```

## Documentation

- **API Documentation:** https://api.balancing.services/v1/documentation
- **OpenAPI Spec:** [openapi.yaml](../../openapi.yaml)
- **Main Repository:** https://github.com/balancing-services/rest-api

## Support

- **Website:** https://balancing.services
- **Email:** info@balancing.services
- **Issues:** [GitHub Issues](https://github.com/balancing-services/rest-api/issues)

## License

MIT License - see [LICENSE](../../LICENSE) for details.

## Changelog

See [CHANGELOG.md](../../CHANGELOG.md) for version history and changes.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "balancing-services",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "FCR, aFRR, api, balancing, electricity, energy, europe, grid, imbalance, mFRR, market, openapi, power, reserves",
    "author": "Balancing Services Team",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/31/96/4b619897d722e5d7b9baf61559b3b3ec72bd9f5e8191e304397c7ecba850/balancing_services-1.4.0.tar.gz",
    "platform": null,
    "description": "# Balancing Services Python Client\n\nPython client library for the [Balancing Services REST API](https://api.balancing.services). Access European electricity balancing market data with a modern, type-safe Python interface.\n\n## Features\n\n- **Type-safe**: Full type hints for better IDE support and code quality\n- **Modern Python**: Built with httpx and attrs for async support and clean data models\n- **Auto-generated**: Generated from the official OpenAPI specification\n- **Comprehensive**: Access to all API endpoints and data models\n- **Well-documented**: Inline documentation and usage examples\n\n## Installation\n\n```bash\nuv pip install balancing-services\n```\n\nOr with pip:\n\n```bash\npip install balancing-services\n```\n\nFor development, install from source:\n\n```bash\ncd clients/python\nuv pip install -e .\n```\n\n## Quick Start\n\n```python\nfrom balancing_services import AuthenticatedClient\nfrom balancing_services.api.default import get_imbalance_prices\nfrom balancing_services.models import Area\nfrom datetime import datetime\n\n# Create an authenticated client\nclient = AuthenticatedClient(\n    base_url=\"https://api.balancing.services/v1\",\n    token=\"YOUR_API_TOKEN\"\n)\n\n# Get imbalance prices for Estonia\nresponse = get_imbalance_prices.sync_detailed(\n    client=client,\n    area=Area.EE,\n    period_start_at=datetime.fromisoformat(\"2025-01-01T00:00:00Z\"),\n    period_end_at=datetime.fromisoformat(\"2025-01-02T00:00:00Z\")\n)\n\nif response.status_code == 200:\n    data = response.parsed\n    print(f\"Query period: {data.queried_period.start_at} to {data.queried_period.end_at}\")\n    for imbalance_prices in data.data:\n        print(f\"Area: {imbalance_prices.area}, Direction: {imbalance_prices.direction}\")\n        for price in imbalance_prices.prices:\n            print(f\"  {price.period.start_at}: {price.price} {imbalance_prices.currency}\")\n```\n\n## Authentication\n\nTo obtain an API token:\n- **Email:** info@balancing.services\n- **Website:** https://balancing.services\n\nInclude your token when creating the client:\n\n```python\nfrom balancing_services import AuthenticatedClient\n\nclient = AuthenticatedClient(\n    base_url=\"https://api.balancing.services/v1\",\n    token=\"YOUR_API_TOKEN\"\n)\n```\n\n## Usage Examples\n\n### Get Balancing Energy Bids with Pagination\n\n```python\nfrom balancing_services import AuthenticatedClient\nfrom balancing_services.api.default import get_balancing_energy_bids\nfrom balancing_services.models import Area, ReserveType\nfrom datetime import datetime\n\nclient = AuthenticatedClient(base_url=\"https://api.balancing.services/v1\", token=\"YOUR_TOKEN\")\n\n# First page\nresponse = get_balancing_energy_bids.sync_detailed(\n    client=client,\n    area=Area.EE,\n    period_start_at=datetime.fromisoformat(\"2025-01-01T00:00:00Z\"),\n    period_end_at=datetime.fromisoformat(\"2025-01-02T00:00:00Z\"),\n    reserve_type=ReserveType.AFRR,\n    limit=100\n)\n\nif response.status_code == 200:\n    data = response.parsed\n    print(f\"Has more: {data.has_more}\")\n\n    # Process first page\n    for bid_group in data.data:\n        for bid in bid_group.bids:\n            print(f\"Bid: {bid.volume} MW @ {bid.price} {bid_group.currency}\")\n\n    # Get next page if available\n    if data.has_more and data.next_cursor:\n        next_response = get_balancing_energy_bids.sync_detailed(\n            client=client,\n            area=Area.EE,\n            period_start_at=datetime.fromisoformat(\"2025-01-01T00:00:00Z\"),\n            period_end_at=datetime.fromisoformat(\"2025-01-02T00:00:00Z\"),\n            reserve_type=ReserveType.AFRR,\n            cursor=data.next_cursor,\n            limit=100\n        )\n```\n\n### Async Usage\n\n```python\nimport asyncio\nfrom balancing_services import AuthenticatedClient\nfrom balancing_services.api.default import get_imbalance_prices\nfrom balancing_services.models import Area\nfrom datetime import datetime\n\nasync def fetch_prices():\n    client = AuthenticatedClient(\n        base_url=\"https://api.balancing.services/v1\",\n        token=\"YOUR_TOKEN\"\n    )\n\n    response = await get_imbalance_prices.asyncio_detailed(\n        client=client,\n        area=Area.EE,\n        period_start_at=datetime.fromisoformat(\"2025-01-01T00:00:00Z\"),\n        period_end_at=datetime.fromisoformat(\"2025-01-02T00:00:00Z\")\n    )\n\n    if response.status_code == 200:\n        return response.parsed\n    return None\n\n# Run async function\nprices = asyncio.run(fetch_prices())\n```\n\n### Error Handling\n\n```python\nfrom balancing_services import AuthenticatedClient\nfrom balancing_services.api.default import get_imbalance_prices\nfrom balancing_services.models import Area\nfrom datetime import datetime\n\nclient = AuthenticatedClient(base_url=\"https://api.balancing.services/v1\", token=\"YOUR_TOKEN\")\n\nresponse = get_imbalance_prices.sync_detailed(\n    client=client,\n    area=Area.EE,\n    period_start_at=datetime.fromisoformat(\"2025-01-01T00:00:00Z\"),\n    period_end_at=datetime.fromisoformat(\"2025-01-02T00:00:00Z\")\n)\n\nif response.status_code == 200:\n    data = response.parsed\n    # Process successful response\nelif response.status_code == 400:\n    error = response.parsed\n    print(f\"Bad request: {error.detail}\")\nelif response.status_code == 401:\n    print(\"Authentication failed - check your API token\")\nelif response.status_code == 429:\n    print(\"Rate limited - please retry later\")\nelse:\n    print(f\"Error {response.status_code}: {response.content}\")\n```\n\n## Data Models\n\nAll response and request models are fully typed using attrs. Key models include:\n\n- `ImbalancePricesResponse`, `ImbalanceTotalVolumesResponse`\n- `BalancingEnergyVolumesResponse`, `BalancingEnergyPricesResponse`, `BalancingEnergyBidsResponse`\n- `BalancingCapacityBidsResponse`, `BalancingCapacityPricesResponse`, `BalancingCapacityVolumesResponse`\n- Enums: `Area`, `ReserveType`, `Direction`, `Currency`, `ActivationType`, `BidStatus`\n\n## Development\n\n### Regenerating the Client\n\nThe client is generated from the OpenAPI specification. To regenerate:\n\n```bash\ncd clients/python\n./generate.sh\n```\n\n### Running Tests\n\n```bash\n# Install development dependencies\nuv pip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run tests with coverage\npytest --cov=balancing_services --cov-report=html\n```\n\n### Code Quality\n\n```bash\n# Format code\nruff format .\n\n# Lint code\nruff check .\n\n# Type checking\nmypy balancing_services\n```\n\n### Automation Scripts\n\nThe Python client includes automation scripts for development and publishing:\n\n#### `generate-pyproject.sh`\nGenerates `pyproject.toml` from the template with the current version from `openapi.yaml`.\n\n**Note:** The version is stored in `openapi.yaml` (single source of truth). The `pyproject.toml.draft` template contains invalid TOML (`version = __VERSION__` without quotes) to prevent accidental use without proper generation.\n\n```bash\n./generate-pyproject.sh\n```\n\nThis script is automatically called by `check.sh` and `test-and-publish.sh`.\n\n#### `check.sh`\nRuns all quality checks in one command:\n\n```bash\n./check.sh\n```\n\nPerforms:\n- Generates `pyproject.toml` from draft\n- Runs tests with pytest\n- Runs linting with ruff\n- Runs type checking with mypy\n- Verifies the package builds\n\n#### `test-and-publish.sh`\nComplete publishing workflow with TestPyPI validation:\n\n**Setup:**\n1. Copy `.env.sample` to `.env` and fill in your credentials:\n   ```bash\n   cp .env.sample .env\n   # Edit .env and add:\n   #   BALANCING_SERVICES_API_KEY (required - for testing against live API)\n   #   UV_PUBLISH_TOKEN_TESTPYPI (required)\n   #   UV_PUBLISH_TOKEN_PYPI (required)\n   ```\n\n2. Run the publish script:\n   ```bash\n   ./test-and-publish.sh\n   ```\n\n**Emergency option** - skip API tests if the server is down:\n```bash\n./test-and-publish.sh --skip-api-tests\n```\n\u26a0\ufe0f This skips testing against the live API. Use only in emergencies!\n\nAlternatively, export variables manually:\n```bash\nexport BALANCING_SERVICES_API_KEY=\"your-api-key\"\nexport UV_PUBLISH_TOKEN_TESTPYPI=\"your-testpypi-token\"\nexport UV_PUBLISH_TOKEN_PYPI=\"your-pypi-token\"\n./test-and-publish.sh\n```\n\n**What it does:**\n1. Loads credentials from `.env` (if present)\n2. Verifies all required environment variables are set\n3. Runs quality checks\n4. Publishes to TestPyPI using `UV_PUBLISH_TOKEN_TESTPYPI`\n5. Creates isolated test sandbox\n6. Installs package from TestPyPI\n7. Runs all example scripts against live API using `BALANCING_SERVICES_API_KEY`\n8. Prompts to publish to PyPI using `UV_PUBLISH_TOKEN_PYPI` if tests pass\n9. Verifies production PyPI package by installing and running examples again\n\n**Get your credentials:**\n- API Key: https://balancing.services\n- TestPyPI: https://test.pypi.org/manage/account/token/\n- PyPI: https://pypi.org/manage/account/token/\n\n**For maintainers:** See `../../scripts/README.md` for the complete release workflow.\n\n## Troubleshooting\n\n### Authentication Errors (401)\n\n**Problem:** Receiving 401 Unauthorized responses\n\n**Solutions:**\n- Verify your API token is correct\n- Check that the token is being passed to `AuthenticatedClient`\n- Ensure your token hasn't expired (contact support if needed)\n\n### Bad Request Errors (400)\n\n**Problem:** Receiving 400 Bad Request responses\n\n**Common causes:**\n- Invalid date range (end date before start date)\n- Date range too large\n- Invalid area code or reserve type\n- Malformed datetime strings\n\n**Solution:** Check the error detail in the response for specific information:\n```python\nif response.status_code == 400:\n    error = response.parsed\n    print(f\"Error detail: {error.detail}\")\n```\n\n### Empty Results\n\n**Problem:** Receiving 200 OK but no data\n\n**Possible reasons:**\n- No data available for the requested period\n- Data not yet published for recent periods\n- Requesting data for a period before data collection started\n\n**Solution:** Try a different time period or check if data exists for your area\n\n### Timeout Issues\n\n**Problem:** Requests timing out\n\n**Solutions:**\n- Increase the client timeout:\n```python\nclient = AuthenticatedClient(\n    base_url=\"https://api.balancing.services/v1\",\n    token=\"YOUR_TOKEN\",\n    timeout=30.0  # Increase from default\n)\n```\n- Reduce the date range in your request\n- Use pagination for large datasets\n\n### Type Errors with Enums\n\n**Problem:** Type errors when passing area or reserve type\n\n**Solution:** Use the provided enum classes:\n```python\nfrom balancing_services.models import Area, ReserveType\n\n# Correct\narea=Area.EE\n\n# Incorrect\narea=\"EE\"  # String might work but not type-safe\n```\n\n## Documentation\n\n- **API Documentation:** https://api.balancing.services/v1/documentation\n- **OpenAPI Spec:** [openapi.yaml](../../openapi.yaml)\n- **Main Repository:** https://github.com/balancing-services/rest-api\n\n## Support\n\n- **Website:** https://balancing.services\n- **Email:** info@balancing.services\n- **Issues:** [GitHub Issues](https://github.com/balancing-services/rest-api/issues)\n\n## License\n\nMIT License - see [LICENSE](../../LICENSE) for details.\n\n## Changelog\n\nSee [CHANGELOG.md](../../CHANGELOG.md) for version history and changes.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Official Python client for accessing European electricity balancing market data via the Balancing Services REST API",
    "version": "1.4.0",
    "project_urls": {
        "Changelog": "https://github.com/balancing-services/rest-api/blob/main/CHANGELOG.md",
        "Documentation": "https://api.balancing.services/v1/documentation",
        "Homepage": "https://balancing.services",
        "Repository": "https://github.com/balancing-services/rest-api"
    },
    "split_keywords": [
        "fcr",
        " afrr",
        " api",
        " balancing",
        " electricity",
        " energy",
        " europe",
        " grid",
        " imbalance",
        " mfrr",
        " market",
        " openapi",
        " power",
        " reserves"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7a80b5052dee1eb07d2ef4ef82c3b8ef916126f565ca7c4b6f58cda2b9b6482f",
                "md5": "ff03aa31a0cf2bfe9d8548e727be8abd",
                "sha256": "397a55d0ab15c3ed9ed787d67b9ff52550b22380ca9c356a75a5d1b881d2acf0"
            },
            "downloads": -1,
            "filename": "balancing_services-1.4.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ff03aa31a0cf2bfe9d8548e727be8abd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 56429,
            "upload_time": "2025-10-25T12:55:13",
            "upload_time_iso_8601": "2025-10-25T12:55:13.403247Z",
            "url": "https://files.pythonhosted.org/packages/7a/80/b5052dee1eb07d2ef4ef82c3b8ef916126f565ca7c4b6f58cda2b9b6482f/balancing_services-1.4.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "31964b619897d722e5d7b9baf61559b3b3ec72bd9f5e8191e304397c7ecba850",
                "md5": "3e5266dee66c1851c0ded93767db5480",
                "sha256": "a6c5db2e34cc0d0160955ac7fddfea9a549d83977c55bfb807a5443dd6c46351"
            },
            "downloads": -1,
            "filename": "balancing_services-1.4.0.tar.gz",
            "has_sig": false,
            "md5_digest": "3e5266dee66c1851c0ded93767db5480",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 32021,
            "upload_time": "2025-10-25T12:55:14",
            "upload_time_iso_8601": "2025-10-25T12:55:14.909633Z",
            "url": "https://files.pythonhosted.org/packages/31/96/4b619897d722e5d7b9baf61559b3b3ec72bd9f5e8191e304397c7ecba850/balancing_services-1.4.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-25 12:55:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "balancing-services",
    "github_project": "rest-api",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "balancing-services"
}
        
Elapsed time: 1.14176s