Skip to main content

Cofy API

Cofy API is an open-source modular framework for ingesting, standardising, storing, and computing energy-related data.

This package contains the runtime API and module system: the piece you need for route 1 in the root README, running a single energy community yourself. If you'd rather start from a ready-made repo than from this package directly, see cofy-api-template.

Install

pip install "cofy-api[all]"

Cofy is modular — install only what you need via extras. Each module has an extra of its own name, and each integration providing data for those modules has one too, so you only install the libraries of the sources you use. Example — the tariff module with ENTSO-E prices:

pip install "cofy-api[tariff,entsoe]"
Module extras Integration extras
tariff, production, simultaneity, directive, billing, members entsoe, energy-cost, energyid, acc

Quick start

Create an app.py file with a minimal Cofy API:

from cofy.api import CofyAPI
from cofy.integrations.entsoe import EntsoeDayAheadTariffSource
from cofy.modules.tariff import TariffModule

app = CofyAPI()
app.register_module(TariffModule(source=EntsoeDayAheadTariffSource(api_key="YOUR_ENTSOE_KEY"), name="entsoe"))

Run it:

fastapi dev app.py

The API is now available at http://127.0.0.1:8000 with interactive docs at /docs.

Sources and families

Every timeseries source belongs to a family describing what it produces, and every field taking a source accepts one family. A tariff module only takes prices, a directive only takes numeric values, and so on, so only valid combinations can be configured.

TimeseriesSource
├── NumericSource           cofy.modules.timeseries
│   ├── PriceSource         cofy.modules.tariff
│   ├── ProductionSource    cofy.modules.production
│   ├── NetVolumeSource     cofy.modules.simultaneity
│   └── RatioSource         cofy.modules.simultaneity
├── DirectiveSeriesSource   cofy.modules.directive
└── BoundarySource          cofy.modules.directive

A source of your own subclasses the family it belongs to, and implements _fetch_timeseries:

class MyPriceSourceSettings(PriceSourceSettings):
    type: Literal["my_price"] = "my_price"


class MyPriceSource(PriceSource, settings=MyPriceSourceSettings):
    async def _fetch_timeseries(self, start, end, resolution, **kwargs) -> Timeseries: ...

A family of your own is an abstract subclass of the family it narrows, and a field accepting it is typed with its union, which is published once every type is registered:

class TemperatureSourceSettings(NumericSourceSettings):
    type: Literal["temperature_source"] = "temperature_source"


class TemperatureSource(NumericSource, settings=TemperatureSourceSettings, abstract=True): ...


if TYPE_CHECKING:
    AnyTemperatureSourceSettings = TemperatureSourceSettings


class HeatingModuleSettings(TimeseriesModuleSettings):
    type: Literal["heating"] = "heating"
    source: "AnyTemperatureSourceSettings"

Every family's union also accepts a reference to a source resource, so a field accepts one family: for sources of two families that aren't nested, use their common ancestor.

Caching

Any source can cache what it fetches, in memory and in aligned chunks of time, by giving it a cache:

source:
  type: acc_forecast
  ean: "541448800000000000"
  credentials: ${ACC_CREDENTIALS}
  cache:
    max_age: PT15M  # defaults to how long the source says its data stays valid

From Python, pass cache=CacheSettings(...) to the source's constructor. A source implements _fetch_timeseries, and takes cache and passes it on to super().__init__; the public fetch_timeseries serves from the cache when there is one, and a source can override it to cache differently.

Secrets

Credentials live in a community's secrets, and every field needing one references a secret with {type: secret, name: ...} instead of holding it. A secret's value is never sent back by the management API.

secrets:
  - name: entsoe_key
    value: my-entsoe-api-key

modules:
  - type: tariff
    name: prices
    source: { type: entsoe_day_ahead, api_key: { type: secret, name: entsoe_key } }

A settings field of your own holding a credential is typed Secret; its object is built with the secret's value. Built from Python, objects take the value itself, as before.

Resources

A value used in several places - a source, a tariff - can be configured once as a named resource and referenced by name wherever one of its kind fits. A referenced source is built once, so every module referencing it shares its cache.

resources:
  - type: source
    name: day_ahead
    value:
      type: entsoe_day_ahead
      api_key: { type: secret, name: entsoe_key }
      cache: {}

modules:
  - type: tariff
    name: prices
    source: { type: resource, name: day_ahead }

A reference to a source resource fits wherever the source it holds would. Energy-cost tariffs accept references too, and a field of your own opts in with Annotated[..., Referable("<kind>")].

Authentication

Protect the API with bearer-token authentication:

from os import environ

from cofy.api import CofyAPI, TokenAuth, TokenInfo

app = CofyAPI(auth=TokenAuth([TokenInfo(name="admin", key=environ["COFY_API_TOKEN"])]))

Or in settings:

auth:
  type: token
  tokens:
    - name: admin
      description: Our admin app
      key: ${COFY_API_TOKEN}
      expires: 2027-01-01T00:00:00Z  # optional

A token is given as its key, or as its hash to keep the key itself out of the settings; when both are given, the hash is used. Generate a strong key and its hash with:

python -c "from cofy.api import generate_key, hash_key; key = generate_key(); print(key, hash_key(key))"

Clients authenticate via header (Authorization: Bearer <key>) or query parameter (?token=<key>).

Development

We use astral python tooling for our development environment. We use poethepoet to define some essential tasks. The demo run task is also available as vscode execution task, making it easy to run and debug the demo application from within vscode.

Install/update dependencies:

First install uv if you don't have it yet.

Then install/update dependencies:

uv sync

Install poethepoet and pre-commit

uv tool install poethepoet
uv tool install pre-commit

Activate pre-commit hooks that enforce code style on every commit:

pre-commit install

Tests and linting

uv sync --group dev
poe test
poe lint
poe format
poe check

Metadata

Release files for cofy-api 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cofy-api 0.9.0
File Size Uploaded Provenance Actions
cofy_api-0.9.0.tar.gz 44.8 kB Without provenance Details for cofy_api-0.9.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cofy-api 0.9.0
File Interpreter ABI Platform Actions
cofy_api-0.9.0-py3-none-any.whl Python 3 none any Details for cofy_api-0.9.0-py3-none-any.whl

Total release size: 105.7 kB

Release files / cofy_api-0.9.0.tar.gz

Download URL cofy_api-0.9.0.tar.gz
Size 44.8 kB
Tags Source
SHA-256 checksum
How to use checksums
ebc4409d496f291ec4a7dc5f0c30f5b2135f9c1191e1e2720a53e89321e99ea6
BLAKE2b-256 checksum
How to use checksums
716cefe0881b1b176fc7a5faff69b28da5f0000019cf072c89e09e0f1e6881ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / cofy_api-0.9.0-py3-none-any.whl

Download URL cofy_api-0.9.0-py3-none-any.whl
Size 60.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
60cde108642f99721a72ec744b834451ef5b1f40112e7e9244668b13cdf2d21a
BLAKE2b-256 checksum
How to use checksums
b0dd8d08f67fd9186fcbecfd08082ad5bf90e01f207bbf079cdbdf057535e532
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for cofy-api 0.9.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page