Skip to content

Contracts

Every CPE must have a contract that defines the commercial terms between the member and their energy retailer. Contracts are used by the settlement engine to compute grid costs, member savings, and KPIs such as the comparison between collective self-consumption (CSC) and individual self-consumption (ISC).

Contracts are attached to a CPE meter and scoped to a member via user_id.

Contract Fields

Field Required Description
buy_type Use: NO_VALUES How buy-side tariff values are provided — FIXED, INDEXED, INDEXED_SIMPLIFIED, or NO_VALUES. NO_VALUES means you must upload opportunity costs
sell_type Use: NO_VALUES How sell-side tariff values are provided — same options as buy_type. NO_VALUES means you must upload opportunity costs
contracted_power ✅ Contracted power of the meter (kVA)
voltage_level ✅ Voltage level (MAT, AT, MT, BT, BTN simples, etc.)
tariff_cycle ✅ Tariff cycle per Portuguese regulation (e.g. TETRA_SEMANAL, BI_HORARIA)
with_holidays ✅ Whether public holidays are treated as Sundays for tariff period calculations
start_date ✅ First day (inclusive, Europe/Lisbon) on which this contract applies. Replaces the old validity field
end_date — Last day (inclusive) on which this contract applies. null = open-ended
user_id ✅ UUID of the community member this contract belongs to
meter_id ✅ UUID of the CPE meter this contract is attached to

Contract Validity

A CPE can have several contracts over time, for example when the member changes retailer or tariff. Each contract covers its own [start_date, end_date] period, and for every day the platform uses exactly one contract: the one whose period contains that day.

%%{init: {"themeVariables": {"fontSize": "18px"}, "gantt": {"barHeight": 30, "barGap": 8}}}%%
gantt
    title Contracts of one CPE
    dateFormat YYYY-MM-DD
    axisFormat %b %Y
    section Contracts
    Retailer A (Jan 1 to Jun 30)        :done, c1, 2026-01-01, 2026-07-01
    Retailer B (Jul 1, end_date null)   :active, c2, 2026-07-01, 2026-12-31
  • Two contracts of the same meter cannot overlap on any day (409 Conflict).
  • Contracts are never chosen by "latest created" and never applied before their start_date or after their end_date.
  • Make sure every day you run market clearing or settlement for is covered by a contract on each CPE. A gap between two contracts means the CPE has no contract on those days.
  • When cloning a contract, give the copy dates that do not overlap the original.
  • GET /meters/{meter_id}/contracts?effective_at=YYYY-MM-DD returns the contract valid on that day.
  • DELETE /meters/{meter_id}/contracts/{contract_id}?effective_at=YYYY-MM-DD removes the contract from that day. Add &end_date=YYYY-MM-DD to remove only that period.

Deprecated validity field

Requests that still send validity are accepted and treated as start_date. Responses always use start_date and end_date. Update your integration to send start_date.

See Business Validity.

Buy and Sell Payloads

When buy_type or sell_type is defined, a payload must be provided with tariff values per period. An example for contracts of type FIXED is described below, but different contract types can be chosen to fit whatever real life Contract is envisioned.

Field Description
peak_value Tariff value during peak hours (€/kWh)
mid_peak_value Tariff value during mid-peak hours (€/kWh)
off_peak_value Tariff value during off-peak hours (€/kWh)
super_off_peak_value Tariff value during super off-peak hours (€/kWh)
multiplierPMD Multiplier applied to the network access tariff (PMD) component
multiplierERSE Multiplier applied to the ERSE peak hour power tariff component

Contracts without values

Setting buy_type and sell_type to NO_VALUES creates a valid contract structure without tariff data, so you must upload opportunity costs. This is sufficient for market clearing but will prevent settlement from computing cost-related KPIs.