Pricing, Tariffs & Market Data API¶
Base paths:
/core/api/communities/{community_id}/dso/core/api/communities/{community_id}/erse/core/api/erse(global ERSE losses and tariffs)/core/api/communities/{community_id}/coefficients/core/api/communities/{community_id}/bilateral-prices/core/api/communities/{community_id}/opportunity_costs/core/api/omie
These endpoints hold the inputs that market clearing and settlement consume: the DSO measurements and allocation data, the ERSE grid-access tariffs and network losses, the allocation coefficients, the bilateral prices, the opportunity costs and the OMIE day-ahead prices. Most of them are time series on the 15-minute grid, so uploading them for past intervals reopens the sessions they touch (see Business Validity).
Common conventions:
- Time zone. CSV files use
Data(DD/MM/YYYY) andHora(HH:MM) inEurope/Lisbon.Horais the end of the interval: the platform subtracts 15 minutes, so the row00:15is stored as the interval starting at00:00. JSON payloads carry the interval start indatetime_timestamp(ISO 8601). Templates are listed in Upload Templates. - Asynchronous uploads. Most JSON and file uploads are queued on a Celery worker and answer
201with{"message": "Processing started", "task_id": "..."}. PollGET /core/api/communities/{community_id}/tasks/{task_id}?group_task=falseuntilstateisSUCCESSorFAILURE. Errors raised inside the task (for example an unknown meter identifier) are only visible there, not in the201response. - Pagination endpoints. All
.../paginationendpoints takelimitandoffsetand returntotal_count,data,distinct_datesanddistinct_times(the distinct values available for the active filters, used by table filter UIs). FilterdateisYYYY-MM-DDandtimeisHH:MM:SS.sort_direction=ascsorts ascending; any other value sorts descending. - Permissions. Community-scoped endpoints require a verified user who belongs to the community: members (
MEMBER) may only callGETendpoints, community admins (ADMIN) and platform admins (SUPER_USER) may also write. Global endpoints under/core/api/erseare readable by any verified user and writable only by a platform admin. Missing membership or write permission returns403.
Endpoint summary¶
| Method | Path | Purpose |
|---|---|---|
| POST | /core/api/communities/{community_id}/dso |
Upload DSO loads and aggregator loads as JSON |
| POST | /core/api/communities/{community_id}/dso/file_upload |
Upload a DSO file (hidden from OpenAPI) |
| GET | /core/api/communities/{community_id}/dso/pagination |
Paginated DSO loads |
| GET | /core/api/communities/{community_id}/dso/aggregator/pagination |
Paginated DSO aggregator loads |
| GET | /core/api/communities/{community_id}/dso/metrics/kpis |
DSO totals for a date range |
| GET | /core/api/communities/{community_id}/dso/metrics |
Community DSO loads at a chosen granularity |
| GET | /core/api/communities/{community_id}/dso/metrics/meters |
DSO loads per meter at a chosen granularity |
| GET | /core/api/communities/{community_id}/dso/aggregator/metrics/meters |
DSO aggregator loads per meter at a chosen granularity |
| GET | /core/api/communities/{community_id}/dso/metrics/meters/share |
Each meter's share of injection, consumption and grid self-consumption |
| GET | /core/api/communities/{community_id}/erse/tariffs/self_consumption_tariffs_between_dates |
ERSE self-consumption tariff for every CPE pair and 15-minute interval |
| POST | /core/api/erse/losses |
Upload the global network losses table (CSV) |
| GET | /core/api/erse/losses/years |
List years with loaded losses |
| GET | /core/api/erse/losses/{year} |
Read all losses of a year |
| GET | /core/api/erse/losses/{year}/pagination |
Paginated losses of a year |
| DELETE | /core/api/erse/losses/{year} |
Delete all losses of a year |
| POST | /core/api/erse/tariffs |
Upload the global ERSE tariffs table (XLSX) |
| GET | /core/api/erse/tariffs/validities |
List loaded tariff validity dates |
| GET | /core/api/erse/tariffs/energy/value |
Look up one energy tariff value |
| GET | /core/api/erse/tariffs/{validity} |
Read all tariffs of a validity |
| DELETE | /core/api/erse/tariffs/{validity} |
Delete all tariffs of a validity |
| POST | /core/api/communities/{community_id}/coefficients/fixed/file_upload |
Upload fixed allocation coefficients as CSV (hidden from OpenAPI) |
| POST | /core/api/communities/{community_id}/coefficients/fixed |
Upload fixed allocation coefficients as JSON |
| GET | /core/api/communities/{community_id}/coefficients/fixed/pagination |
Paginated fixed allocation coefficients |
| POST | /core/api/communities/{community_id}/bilateral-prices |
Upload per-interval bilateral prices as JSON |
| POST | /core/api/communities/{community_id}/bilateral-prices/file_upload |
Upload per-interval bilateral prices as CSV (hidden from OpenAPI) |
| GET | /core/api/communities/{community_id}/bilateral-prices/by_provider |
Bilateral prices of one provider over a date range |
| GET | /core/api/communities/{community_id}/bilateral-prices/pagination |
Paginated per-interval bilateral prices |
| POST | /core/api/communities/{community_id}/bilateral-prices/fixed |
Create or replace fixed bilateral prices |
| GET | /core/api/communities/{community_id}/bilateral-prices/fixed |
List the fixed bilateral prices in force today |
| PUT | /core/api/communities/{community_id}/bilateral-prices/fixed/{receiver_user_id}/{provider_user_id} |
Set the price of a fixed bilateral pair for a period |
| DELETE | /core/api/communities/{community_id}/bilateral-prices/fixed/{receiver_user_id}/{provider_user_id} |
Remove the price of a fixed bilateral pair from a date |
| GET | /core/api/communities/{community_id}/opportunity_costs |
Uploaded opportunity cost of one meter at one interval |
| GET | /core/api/communities/{community_id}/opportunity_costs/by_meter |
Opportunity costs of one meter over a time range |
| GET | /core/api/communities/{community_id}/opportunity_costs/by_community |
Opportunity costs of all active meters of the community |
| POST | /core/api/communities/{community_id}/opportunity_costs/file_upload |
Upload opportunity costs as CSV (hidden from OpenAPI) |
| POST | /core/api/communities/{community_id}/opportunity_costs |
Upload opportunity costs as JSON |
| GET | /core/api/communities/{community_id}/opportunity_costs/pagination |
Paginated opportunity costs |
| GET | /core/api/omie |
OMIE prices, optionally aggregated |
| GET | /core/api/omie/pagination |
Paginated OMIE prices |
DSO¶
Data sent by the distribution system operator (DSO) for the community's CPEs and aggregator meters. Each row is one meter and one 15-minute interval. Energy values are in kWh. See Meters for CPE and aggregator meters and Settlement for how the values are used.
Upload DSO Data¶
Uploads DSO loads (per CPE) and, optionally, DSO aggregator loads as JSON. The request is processed in the background: rows
for the same (community_id, datetime_timestamp, meter_id) replace the existing ones, market sessions are created (or reopened) for the
timestamps in dso_loads, and sessions touching those timestamps are invalidated.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
dso_loads |
body | array | Yes | Rows below. Must be present; may be [] only if dso_aggregator_loads has rows |
dso_aggregator_loads |
body | array | No | Aggregator rows below. Defaults to [] |
dso_loads[] fields: datetime_timestamp (datetime, interval start), meter_id (UUID), community_id (UUID), energy_surplus,
imputed_energy, grid_sc, grid_injection (floats, kWh), consumption (float, optional) and the stage code of each value
(energy_surplus_stage, imputed_energy_stage, grid_sc_stage, grid_injection_stage, consumption_stage optional; integers as reported by the DSO).
dso_aggregator_loads[] fields: datetime_timestamp, meter_id, community_id, total_surplus, sharing_energy (floats, kWh),
total_surplus_stage, sharing_energy_stage (integers).
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"dso_loads": [
{
"datetime_timestamp": "2023-05-01T00:30:00+01:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"energy_surplus": 0.0, "energy_surplus_stage": 0,
"imputed_energy": 0.0, "imputed_energy_stage": 0,
"grid_sc": 0.0, "grid_sc_stage": 0,
"consumption": 18.81, "consumption_stage": 0,
"grid_injection": 0.0, "grid_injection_stage": 0
}
],
"dso_aggregator_loads": [
{
"datetime_timestamp": "2023-05-01T00:30:00+01:00",
"meter_id": "1b4e28ba-2fa1-11d2-883f-0016d3cca427",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"total_surplus": 0.0, "total_surplus_stage": 0,
"sharing_energy": 0.0, "sharing_energy_stage": 0
}
]
}'
Response (abridged)
Tip
- Returns
400with{"message": "No DSO data provided."}when both lists are empty. - Because the body has two array fields, they must be sent inside one JSON object (
dso_loads/dso_aggregator_loads), not as a bare array. - Missing numeric values are stored as
0. Meters and community are validated in the background task, so check the task status forNotFoundor inactive-object errors. - Uploading DSO data invalidates the affected sessions: they go back to
OPENand their transactions and settlement outputs are deleted. Re-run market clearing and settlement. - As implemented, the task finishes with an error if
dso_loadshas rows anddso_aggregator_loadsis empty. Send at least one aggregator row with the loads, or check the task status after every upload.
Upload DSO File¶
Uploads a DSO file. The meter identifiers in the file (CPE codes) are resolved to community meters of type CPE or AGGREGATOR_METER as they were
at each timestamp. Values are processed like Upload DSO Data.
Hidden endpoint
This route is excluded from the OpenAPI schema (include_in_schema=False) but is used by the web application.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
file_upload |
body (multipart) | file | Yes | File sent with content type text/csv |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/file_upload \
-H "Authorization: Bearer $TOKEN" \
-F "file_upload=@dso.csv;type=text/csv"
Each line of the file is identifier;code;unit;YYYYMMDD;flag;HHMM|value|state;HHMM|value|state;..., for example:
code selects the variable: 424 grid injection, 423 consumption, 413 energy surplus, 415 imputed energy, 418 grid self-consumption
(loads) and 421 total surplus, 452 sharing energy (aggregator loads). These are the same codes listed in the header of the DSO template in
Upload Templates.
Response (abridged)
Tip
- Anything other than
text/csvis rejected (InvalidDocumentType, returned as404). - Rows with unit
kWare converted to kWh by dividing by 4 (15-minute intervals). TheHHMMtoken is the interval end; the storeddatetime_timestampis the interval start, inEurope/Lisbonwith DST handled. - The
statevalue of each token is stored as the*_stageof the variable. - Unknown identifiers fail the background task; check it with the task status endpoint.
- Sessions are created or reopened and invalidated exactly as in the JSON upload.
List DSO Loads (Paginated)¶
Returns DSO loads of all meters of the community, one row per meter and interval, with the meter identifier. Used by the DSO data table.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
limit |
query | integer | Yes | Page size |
offset |
query | integer | No | Rows to skip. Default 0 |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
meter_id |
query | string | No | Filter by meter UUID |
sort_column |
query | string | No | date, time, meter_id (sorts by meter identifier) or any column of the load row (for example grid_injection) |
sort_direction |
query | string | No | asc for ascending, otherwise descending |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/pagination?limit=50&offset=0&date=2023-05-01&sort_column=time&sort_direction=asc" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 96,
"data": [
{
"datetime_timestamp": "2023-04-30T23:30:00+00:00",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"meter_identifier": "PT0002000000000000AA",
"energy_surplus": 0.0,
"imputed_energy": 0.0,
"grid_sc": 0.0,
"consumption": 18.81,
"grid_injection": 0.0
}
],
"distinct_dates": [{ "date": "2023-05-01" }],
"distinct_times": [{ "time": "00:30:00" }]
}
Tip
Without sort_column the order is not defined; always send a sort when paging through many rows. Energy is in kWh.
List DSO Aggregator Loads (Paginated)¶
Same as List DSO Loads, for the aggregator-meter data (total_surplus and sharing_energy).
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
limit |
query | integer | Yes | Page size |
offset |
query | integer | No | Rows to skip. Default 0 |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
meter_id |
query | string | No | Filter by meter UUID |
sort_column |
query | string | No | date, time, meter_id or a column of the row |
sort_direction |
query | string | No | asc for ascending, otherwise descending |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/aggregator/pagination?limit=50&offset=0" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 96,
"data": [
{
"datetime_timestamp": "2023-04-30T23:30:00+00:00",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"meter_id": "1b4e28ba-2fa1-11d2-883f-0016d3cca427",
"meter_identifier": "PT0002000000000001AA",
"total_surplus": 4.2,
"sharing_energy": 3.1
}
],
"distinct_dates": [{ "date": "2023-05-01" }],
"distinct_times": [{ "time": "00:30:00" }]
}
Tip
The aggregator meter is a virtual meter that the DSO reports allocation data for (see Meters). Values are kWh.
Get DSO KPIs¶
Returns the totals of the DSO values over a date range: one number for the whole community, summed across meters and intervals.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive (the whole day is included) |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/metrics/kpis?start_date=2023-05-01&end_date=2023-05-31" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_grid_injection": 1520.4,
"total_consumption": 3980.7,
"total_imputed_energy": 910.2,
"total_grid_sc": 870.1,
"total_energy_surplus": 610.3,
"total_surplus_energy_aggregator": 640.0,
"total_sharing_energy": 598.5
}
Tip
All totals are in kWh and are 0.0 when there is no data in the range. total_surplus_energy_aggregator and total_sharing_energy come from the aggregator loads, the others from the CPE loads.
Get DSO Loads by Granularity¶
Returns the community's DSO loads summed over all meters and aggregated to the requested granularity. Use it for charts.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
granularity |
query | string | No | MIN15 (default), HOUR, DAY, MONTH or YEAR |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/metrics?start_date=2023-05-01&end_date=2023-05-02&granularity=HOUR" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"datetime_timestamp": "2023-05-01T00:00:00+01:00",
"grid_injection": 0.0,
"energy_surplus": 0.0,
"consumption": 75.3,
"grid_sc": 0.0
}
]
Tip
Values are summed per bucket (kWh) and buckets are computed in Europe/Lisbon. Returns [] when there is no data. Only these four fields are returned; use Get DSO KPIs for imputed energy.
Get DSO Loads by Meter¶
Same aggregation as Get DSO Loads by Granularity, but kept separate per meter. The result is an object keyed by meter UUID.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
granularity |
query | string | No | MIN15 (default), HOUR, DAY, MONTH or YEAR |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/metrics/meters?start_date=2023-05-01&end_date=2023-05-01&granularity=DAY" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"7c9e6679-7425-40de-944b-e07fc1f90ae7": [
{
"datetime_timestamp": "2023-05-01T00:00:00+01:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"grid_injection": 0.0,
"energy_surplus": 0.0,
"consumption": 1810.2,
"grid_sc": 0.0
}
]
}
Tip
Returns {} when there is no data. Values are summed per bucket (kWh).
Get DSO Aggregator Loads by Meter¶
Aggregator loads (total_surplus, sharing_energy) per aggregator meter at the requested granularity, as an object keyed by meter UUID.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
granularity |
query | string | No | MIN15 (default), HOUR, DAY, MONTH or YEAR |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/aggregator/metrics/meters?start_date=2023-05-01&end_date=2023-05-07&granularity=DAY" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"1b4e28ba-2fa1-11d2-883f-0016d3cca427": [
{
"datetime_timestamp": "2023-05-01T00:00:00+01:00",
"meter_id": "1b4e28ba-2fa1-11d2-883f-0016d3cca427",
"total_surplus": 42.0,
"sharing_energy": 31.5
}
]
}
Tip
Returns {} when there is no aggregator data in the range. Values are kWh.
Get DSO Meter Shares¶
Returns each meter's fraction of the community totals of grid injection, consumption and grid self-consumption over the date range.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/dso/metrics/meters/share?start_date=2023-05-01&end_date=2023-05-31" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"grid_injection_share": 0.62,
"consumption_share": 0.35,
"grid_sc_share": 0.4
}
]
Tip
Shares are fractions between 0 and 1 that add up to 1 across meters for each field. A share is 0.0 when the community total of that field is 0. Returns [] when there is no data.
ERSE¶
Routes mounted on /core/api/communities/{community_id}/erse. The global ERSE tables (losses and tariffs) are in
ERSE Losses and ERSE Tariffs.
Get Self-Consumption Tariffs Between Dates¶
Computes the ERSE grid-access tariff charged on self-consumed energy for every ordered pair of distinct CPEs of the community (provider and receiver)
and every 15-minute interval between two dates. It uses the community's contracts (tariff cycle, voltage levels) and the ERSE tariffs valid on start_date.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/erse/tariffs/self_consumption_tariffs_between_dates?start_date=2025-01-01&end_date=2025-01-01" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"data": [
{
"datetime_timestamp": "2025-01-01 00:00:00+00:00",
"provider_meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"receiver_meter_id": "9f8b3c1e-4a6d-4d1b-8a52-0c7f6f2d3e11",
"erse_tariff_value": 0.0123
}
]
}
Tip
- The response has
N x (N - 1) x 96rows per day forNCPEs, so keep the range short for communities with many CPEs. - The 15-minute grid is built from
start_date00:00 toend_date23:59 in UTC, anddatetime_timestampis returned as a string. - Tariffs are taken from the most recent validity on or before
start_date, so a range that crosses a tariff validity uses a single table. Values are in EUR/kWh. - If ERSE tariffs have not been loaded (see ERSE Tariffs) the tariff values cannot be resolved.
ERSE losses¶
Global network-loss table, shared by all communities: one fraction (between 0 and 1) per 15-minute interval and voltage level
(BT, MT, AT, AT/RNT, MAT). Losses are used to compute the opportunity costs of CPEs from their contracts.
Upload Losses¶
Uploads a losses CSV. Rows for the same interval and voltage level replace existing ones, so a year can be corrected by uploading it again.
Auth / permissions: platform admin only (global endpoint, 403 for anyone else).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
file |
body (multipart) | file | Yes | CSV with content type text/csv and exactly the header Data,Hora,BT,MT,AT,AT/RNT,MAT (see template_perdas.csv) |
Example
curl -X POST https://<host>/core/api/erse/losses \
-H "Authorization: Bearer $TOKEN" \
-F "file=@template_perdas.csv;type=text/csv"
The file looks like:
Data,Hora,BT,MT,AT,AT/RNT,MAT
01/01/2025,00:15,0.0938234,0.0362639,0.0129007,0.0226626,0.0173676
01/01/2025,00:30,0.0925803,0.0358695,0.0127697,0.0226626,0.0173676
Response (abridged)
Tip
- Processed synchronously (no
task_id). A wrong content type returns404(InvalidDocumentType) and wrong headers or column count403(Invalid document). - Maximum 36,000 rows per file (about one year of 15-minute data); a bigger file is rejected with an error.
Horais the interval end (00:15is stored as00:00). DST changes are handled inEurope/Lisbon.- Values are fractions of energy, not percentages:
0.0938means 9.38%.
List Loss Years¶
Returns the years for which losses are loaded.
Auth / permissions: any verified user.
Example
Response (abridged)
Tip
Returns [] (not 404) when no losses are loaded. The order of the years is not guaranteed.
Get Losses by Year¶
Returns every loss row of a year: one entry per interval and voltage level.
Auth / permissions: any verified user.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
year |
path | integer | Yes | Calendar year, for example 2025 |
Example
Response (abridged)
[
{ "datetime_timestamp": "2025-01-01T00:00:00+00:00", "voltage_level": "BT", "value": 0.0938234 },
{ "datetime_timestamp": "2025-01-01T00:00:00+00:00", "voltage_level": "MT", "value": 0.0362639 }
]
Tip
A full year is about 175,000 rows (five voltage levels x 35,000 intervals); prefer Get Losses by Year (Paginated) for tables. Returns [] when the year has no data.
Get Losses by Year (Paginated)¶
Paginated losses of a year with optional filters, for the losses table.
Auth / permissions: any verified user.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
year |
path | integer | Yes | Calendar year |
limit |
query | integer | Yes | Page size |
offset |
query | integer | Yes | Rows to skip |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
voltage_level |
query | string | No | One of BT, MT, AT, AT/RNT, MAT |
sortColumn |
query | string | No | date, time or a column (datetime_timestamp, voltage_level, value) |
sortDirection |
query | string | No | asc or desc. Both sortColumn and sortDirection are required to sort |
Example
curl "https://<host>/core/api/erse/losses/2025/pagination?limit=20&offset=0&voltage_level=BT&sortColumn=datetime_timestamp&sortDirection=asc" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 35040,
"data": [
{ "datetime_timestamp": "2025-01-01T00:00:00+00:00", "voltage_level": "BT", "value": 0.0938234 }
],
"distinct_dates": [{ "date": "2025-01-01" }],
"distinct_times": [{ "time": "00:00:00" }]
}
Tip
This endpoint uses camelCase sortColumn / sortDirection, unlike the community-scoped pagination endpoints. Without both, rows are returned newest first.
Delete Losses by Year¶
Deletes all loss rows of a year, for every voltage level.
Auth / permissions: platform admin only.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
year |
path | integer | Yes | Calendar year to delete |
Example
Response (abridged)
Tip
The delete is immediate and affects all communities. It returns 204 even if the year had no data. Opportunity costs that were calculated earlier are not recalculated until the market runs again.
ERSE tariffs¶
Global ERSE grid-access tariff table, shared by all communities. A tariff set is identified by its validity date (the date the ERSE publication takes
effect). Rows have a type (POWER, ENERGY or CONTRACTED_POWER), the voltage level of the consumption point (ic_voltage_level) and of the
injection point (ipr_voltage_level), trimester (1 to 4), period (for example PONTA, CHEIAS, VAZIO), cieg_discount ("0", "50" or "100") and value.
See Settlement for how these tariffs enter the settlement.
Upload Tariffs¶
Uploads the ERSE tariffs spreadsheet. The validity date is read from the file itself, and an existing set with the same validity is replaced.
Auth / permissions: platform admin only.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
file |
body (multipart) | file | Yes | .xlsx with content type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, in the layout of template_tarifas_ERSE.xlsx |
Example
curl -X POST https://<host>/core/api/erse/tariffs \
-H "Authorization: Bearer $TOKEN" \
-F "file=@template_tarifas_ERSE.xlsx;type=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Response (abridged)
Tip
- The data is read from the sheet
Tarifas Acesso_Autoconsumo(validity in cellC1, tables from row 9). A different layout fails with403Invalid document. - Any other content type returns
404(InvalidDocumentType). A database failure returns aDatabaseError. - Replacement is by validity: uploading the same file again does not duplicate rows, but other validities are untouched.
List Tariff Validities¶
Returns the validity dates for which a tariff set is loaded.
Auth / permissions: any verified user.
Example
Response (abridged)
Tip
Returns [] (not 404) when no tariffs are loaded. Use these dates with Get Tariffs by Validity.
Get Energy Tariff Value¶
Looks up the value of one ENERGY tariff for a date, a pair of voltage levels, a period and a CIEG discount. The trimester is derived from the month of validity.
Auth / permissions: no authentication dependency is declared on this route in the code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
validity |
query | date | Yes | Date the tariff must be valid on, YYYY-MM-DD (also determines the trimester) |
ic_voltage_level |
query | string | Yes | Voltage level of the consumption point (for example BT, MT, AT, AT/RNT, BTN simples) |
ipr_voltage_level |
query | string | Yes | Voltage level of the injection point |
period |
query | string | Yes | PONTA, CHEIAS, VAZIO, VAZIO_NORMAL, SUPER_VAZIO, FORA_VAZIO or VENDA_REDE |
cieg_discount |
query | string | Yes | 0, 50 or 100 |
Example
curl "https://<host>/core/api/erse/tariffs/energy/value?validity=2025-02-10&ic_voltage_level=BT&ipr_voltage_level=BT&period=CHEIAS&cieg_discount=0"
Response (abridged)
Tip
- The response is a bare number (EUR/kWh), not an object.
- It uses the latest tariff set whose validity is on or before
validity.AT/RNTis treated asAT, and theBTNvariants andBTEasBTfor the injection level. If no exact match exists, the consumption and injection levels are swapped before giving up. - Returns
404when no tariff is found, and422for values outside the enums. Encode special characters in voltage levels (AT/RNTisAT%2FRNT, spaces as%20). - Results are cached in Redis per combination of parameters and the code sets no expiry, so after reloading tariffs a previously requested combination may still return the cached value.
Get Tariffs by Validity¶
Returns all tariff rows of one validity.
Auth / permissions: any verified user.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
validity |
path | date | Yes | Exact validity date as returned by List Tariff Validities |
Example
Response (abridged)
[
{
"id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
"type": "ENERGY",
"ic_voltage_level": "BT",
"ipr_voltage_level": "BT",
"trimester": 1,
"period": "CHEIAS",
"cieg_discount": "0",
"value": 0.0123,
"validity": "2025-01-01"
}
]
Tip
The match is exact: a date that is not a loaded validity returns [], not the closest earlier set. Rows of type POWER and CONTRACTED_POWER have trimester, period or ipr_voltage_level set to null where they do not apply.
Delete Tariffs by Validity¶
Deletes all tariff rows of one validity.
Auth / permissions: platform admin only.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
validity |
path | date | Yes | Validity date to delete |
Example
Response (abridged)
Tip
Returns 204 even if there were no rows. The delete affects all communities: lookups use the latest validity on or before the requested date, so later calculations fall back to an older set if one exists.
Allocation coefficients¶
Fixed allocation coefficients: the share of the community's surplus allocated to each meter in each 15-minute interval, used when the community's
method_alloc_coeff is FIXED (see Allocation Coefficient Methods and
OSTEC with Allocation Coefficients).
Upload Fixed Coefficients File¶
Uploads fixed coefficients from a CSV. CPE codes are mapped to the community's meters.
Hidden endpoint
This route is excluded from the OpenAPI schema (include_in_schema=False) but is used by the web application.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
file_upload |
body (multipart) | file | Yes | CSV (text/csv) with exactly the columns Data,Hora,CPE,Coeficiente de partilha, see template_coeff_fixed.csv |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/coefficients/fixed/file_upload \
-H "Authorization: Bearer $TOKEN" \
-F "file_upload=@template_coeff_fixed.csv;type=text/csv"
Data,Hora,CPE,Coeficiente de partilha
01/05/2023,00:15,PT00000000000000000A,0.200
01/05/2023,00:30,PT00000000000000000A,0.400
Response (abridged)
Tip
- A wrong content type returns
404and a header mismatch403(Invalid document), before the task starts. CPEmust be the meteridentifierof a community meter; unknown identifiers fail the task.- Maximum 36,000 rows per file. Rows for the same community, interval and meter are replaced.
- Sessions are created or reopened (
OPEN) for the interval timestamps and the existing results are invalidated.
Upload Fixed Coefficients¶
Uploads fixed coefficients as a JSON array, using meter UUIDs.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
| body | body | array | Yes | Each item: datetime_timestamp (datetime, interval start), meter_id (UUID of the CPE), value (float, the coefficient) |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/coefficients/fixed \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{ "datetime_timestamp": "2023-05-01T00:00:00+01:00", "meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "value": 0.2 },
{ "datetime_timestamp": "2023-05-01T00:15:00+01:00", "meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "value": 0.4 }
]'
Response (abridged)
Tip
Returns 400 with {"message": "No coefficients data provided."} for an empty array. Processing is in the background (same side effects as the file upload: replace, open and invalidate sessions). The coefficient value is a dimensionless share; the platform does not check that the shares of an interval add up to 1.
List Fixed Coefficients (Paginated)¶
Returns the stored fixed coefficients, one row per meter and interval.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
limit |
query | integer | Yes | Page size |
offset |
query | integer | Yes | Rows to skip |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
meter_id |
query | UUID | No | Filter by meter |
sort_column |
query | string | No | date, time, meter_id, value or datetime_timestamp |
sort_direction |
query | string | No | asc for ascending, otherwise descending |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/coefficients/fixed/pagination?limit=50&offset=0&meter_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&sort_column=date&sort_direction=asc" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 2,
"data": [
{ "datetime_timestamp": "2023-04-30T23:00:00+00:00", "meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "value": 0.2 }
],
"distinct_dates": [{ "date": "2023-05-01" }],
"distinct_times": [{ "time": "00:00:00" }]
}
Tip
The meter_id filter must be a valid UUID (422 otherwise).
Bilateral prices¶
Prices agreed between a provider and a receiver member, used by the bilateral market rates. There are two forms, selected by the community's market_rate:
per-interval prices (BILATERAL_PRICE, TREE_DNAC) and fixed dated prices (FIXED_BILATERAL_PRICE, FIXED_TREE_DNAC).
See Bilateral Prices. Prices are in EUR/kWh and refer to members (user IDs), not meters.
Upload Bilateral Prices¶
Uploads per-interval bilateral prices as JSON. Processed in the background; rows with the same community, interval, receiver and provider replace the existing ones.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
| body | body | array | Yes | Each item: datetime_timestamp (datetime, interval start), receiver_user_id (UUID), provider_user_id (UUID), price (float, EUR/kWh) |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"datetime_timestamp": "2023-05-01T00:00:00+01:00",
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.08
}
]'
Response (abridged)
Tip
- Returns
400with{"message": "No bilateral prices data provided."}for an empty array. - Uploading invalidates the sessions of the affected timestamps (back to
OPEN; transactions and settlement outputs deleted). - Market clearing is refused unless every session being cleared has at least one provider to receiver price; provide all possible pairs when members can act as either side.
- Only prices of the community's current
market_ratemode are used; prices uploaded for the other mode are ignored.
Upload Bilateral Prices File¶
Uploads per-interval bilateral prices from a CSV, using member names instead of IDs.
Hidden endpoint
This route is excluded from the OpenAPI schema (include_in_schema=False) but is used by the web application.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
file_upload |
body (multipart) | file | Yes | CSV (text/csv) with exactly the columns Data,Hora,Produtor,Consumidor,Preço, see template_bilateral_prices.csv |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/file_upload \
-H "Authorization: Bearer $TOKEN" \
-F "file_upload=@template_bilateral_prices.csv;type=text/csv"
Data,Hora,Produtor,Consumidor,Preço
01/05/2023,00:15,Membro1,Membro2,1
01/05/2023,00:30,Membro1,Membro2,1
Response (abridged)
Tip
ProdutorandConsumidormust match the member name in the community; unknown names fail the task.- Wrong content type returns
404and wrong headers403, before the task starts. Maximum 36,000 rows. - Same replacement and invalidation behaviour as the JSON upload.
Get Bilateral Prices by Provider¶
Returns the per-interval prices set by one provider, for all receivers, between two dates.
Auth / permissions: any community member or platform admin, with data scoping: a MEMBER may only query their own user ID as provider_user_id; a community ADMIN may query any member of the community. Otherwise 403.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
provider_user_id |
query | UUID | Yes | Selling member |
start_date |
query | date | Yes | First day, YYYY-MM-DD |
end_date |
query | date | Yes | Last day, inclusive |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/by_provider?provider_user_id=5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22&start_date=2023-05-01&end_date=2023-05-02" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"datetime_timestamp": "2023-04-30T23:00:00+00:00",
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.08
}
]
Tip
The date range is expanded to the whole of end_date. A 403 Target user is not a member of this community is returned to admins who query a user outside the community.
List Bilateral Prices (Paginated)¶
Paginated per-interval bilateral prices of the community.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
limit |
query | integer | Yes | Page size |
offset |
query | integer | Yes | Rows to skip |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
receiver_user_id |
query | UUID | No | Filter by receiver |
provider_user_id |
query | UUID | No | Filter by provider |
sort_column |
query | string | No | date, time, receiver_user_id, provider_user_id, price; any other value sorts by datetime_timestamp |
sort_direction |
query | string | No | asc for ascending, otherwise descending |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/pagination?limit=50&offset=0&provider_user_id=5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22&sort_column=price&sort_direction=desc" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 192,
"data": [
{
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"datetime_timestamp": "2023-04-30T23:00:00+00:00",
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.08
}
],
"distinct_dates": [{ "date": "2023-05-01" }],
"distinct_times": [{ "time": "00:00:00" }]
}
Tip
Only rows where the receiver or the provider has the MEMBER role in the community are listed. Unlike by_provider, no per-user scoping is applied here.
Upsert Fixed Bilateral Prices¶
Creates or replaces fixed bilateral prices: one price per provider to receiver pair for a dated period. Processed synchronously.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
| body | body | array | Yes | Each item: receiver_user_id (UUID), provider_user_id (UUID), price (float, EUR/kWh), start_date (date), end_date (date, optional) |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/fixed \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.08,
"start_date": "2026-01-01",
"end_date": null
}
]'
Response (abridged)
Tip
- Returns
400with{"message": "No fixed bilateral prices data provided."}for an empty array. start_dateandend_dateare inclusive whole days inEurope/Lisbon;end_date: nullis open-ended. Sending a new price for[start_date, end_date]replaces the overlapping period and keeps the history outside it. See Business Validity.- Sessions in the affected period are invalidated (back to
OPEN, transactions and settlement outputs deleted). end_dateearlier thanstart_dateis not validated at the schema level and fails with a server error.
List Fixed Bilateral Prices¶
Lists the fixed bilateral prices in force today (Europe/Lisbon), one entry per provider to receiver pair.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
Example
curl https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/fixed \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.08,
"version_id": "6f1ed002-ab5d-42e0-868f-9a2a2ad3d1f4",
"start_date": "2026-01-01",
"end_date": null
}
]
Tip
There is no effective_at parameter: only the version valid today is returned, so pairs whose period ended or has not started yet are omitted.
Update Fixed Bilateral Price¶
PUT /core/api/communities/{community_id}/bilateral-prices/fixed/{receiver_user_id}/{provider_user_id}
Sets a new price for an existing pair over [start_date, end_date], keeping the price outside that period.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
receiver_user_id |
path | UUID | Yes | Buying member |
provider_user_id |
path | UUID | Yes | Selling member |
price |
body | float | Yes | New price, EUR/kWh |
start_date |
body | date | Yes | First day the price applies (inclusive) |
end_date |
body | date | No | Last day (inclusive). null or omitted = open-ended |
Example
curl -X PUT https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/fixed/2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11/5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "price": 0.09, "start_date": "2026-07-01", "end_date": null }'
Response (abridged)
{
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"receiver_user_id": "2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11",
"provider_user_id": "5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22",
"price": 0.09,
"version_id": "0b8a7c3e-2f1d-4e6a-9c55-7d4f1b2a3c90",
"start_date": "2026-07-01",
"end_date": null
}
Tip
- Returns
404with{"message": "Fixed bilateral price not found."}when the pair has no fixed price yet; create it with Upsert Fixed Bilateral Prices first. - The affected sessions are invalidated (reopened, results deleted); re-run market clearing and settlement.
- The returned
version_id,start_dateandend_datedescribe the version just written.
Delete Fixed Bilateral Price¶
DELETE /core/api/communities/{community_id}/bilateral-prices/fixed/{receiver_user_id}/{provider_user_id}
Removes the price of a pair from effective_at onwards, or only for [effective_at, end_date] when end_date is given. Earlier history is kept.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
receiver_user_id |
path | UUID | Yes | Buying member |
provider_user_id |
path | UUID | Yes | Selling member |
effective_at |
query | date | Yes | First day to remove, YYYY-MM-DD |
end_date |
query | date | No | Last day to remove (inclusive). Omit to remove everything from effective_at |
Example
curl -X DELETE "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/bilateral-prices/fixed/2c26b46b-68ff-4c3a-9d4e-1f0a7a2b8c11/5d41402a-bc4b-4a2a-9b6e-3e1d7c4f9a22?effective_at=2026-07-01&end_date=2026-07-31" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
Tip
Returns 404 with {"message": "Fixed bilateral price not found."} when the pair has no fixed price at all. Sessions in the removed period are invalidated. Market clearing with a fixed bilateral rate needs at least one price pair, so removing the last one blocks clearing.
Opportunity costs¶
Per-CPE, per-interval buy and sell reference prices (l_buy, l_sell, EUR/kWh) that bound the internal market price. They are either calculated by the platform from contracts, ERSE tariffs,
losses and OMIE (is_upload = false), or uploaded by the integrator when retailer prices cannot be shared (is_upload = true). Uploaded values take precedence. See
Opportunity Costs.
Get Opportunity Cost at a Timestamp¶
Returns the uploaded opportunity cost of one meter for one interval.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
meter_id |
query | UUID | Yes | CPE meter |
datetime_timestamp |
query | string | Yes | Interval start, ISO 8601 |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs?meter_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&datetime_timestamp=2023-05-01T00:00:00%2B01:00" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"datetime_timestamp": "2023-04-30T23:00:00+00:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"meter_name": null,
"l_buy": 0.2,
"l_sell": 0.111,
"is_upload": true
}
Tip
- Returns
400for an unparsable timestamp (Invalid datetime format. Use ISO 8601 format.) and404(Opportunity cost not found) when no uploaded row exists, even if a calculated one does; useby_meterorby_communityto see both. - URL-encode
+in the offset as%2B.
Get Opportunity Costs by Meter¶
Returns all opportunity costs of one meter in a time range, both calculated and uploaded.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
meter_id |
query | UUID | Yes | CPE meter |
start_datetime_timestamp |
query | string | Yes | Range start, ISO 8601 |
end_datetime_timestamp |
query | string | Yes | Range end, ISO 8601 (extended to the end of that day) |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs/by_meter?meter_id=7c9e6679-7425-40de-944b-e07fc1f90ae7&start_datetime_timestamp=2023-05-01T00:00:00&end_datetime_timestamp=2023-05-01T23:45:00" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"datetime_timestamp": "2023-05-01T00:00:00+00:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"meter_name": null,
"l_buy": 0.2,
"l_sell": 0.111,
"is_upload": true
}
]
Tip
Returns 400 for invalid datetimes. The same interval can appear twice (one is_upload: true, one false); the calculated copy is ignored by the market while an uploaded one exists. Timestamps without an offset are interpreted as naive, so send an explicit offset.
Get Opportunity Costs by Community¶
Lists the opportunity costs of all ACTIVE meters of the community, ordered by time and meter, with optional filters.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
start_datetime |
query | datetime | No | Only rows at or after this time |
end_datetime |
query | datetime | No | Only rows at or before this time |
is_upload |
query | boolean | No | true for uploaded rows only, false for calculated rows only |
limit |
query | integer | No | Page size. Default 1000 |
offset |
query | integer | No | Rows to skip. Default 0 |
include_meter_name |
query | boolean | No | When true, fills meter_name with the meter identifier. Default false |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs/by_community?start_datetime=2023-05-01T00:00:00%2B01:00&end_datetime=2023-05-01T23:45:00%2B01:00&is_upload=true&include_meter_name=true&limit=500" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"datetime_timestamp": "2023-04-30T23:00:00+00:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"meter_name": "ginasio",
"l_buy": 0.2,
"l_sell": 0.111,
"is_upload": true
}
]
Tip
The response is a plain array with no total count: page by increasing offset until fewer than limit rows come back. Inactive meters are excluded.
Upload Opportunity Costs File¶
Uploads opportunity costs from a CSV, using meter identifiers.
Hidden endpoint
This route is excluded from the OpenAPI schema (include_in_schema=False) but is used by the web application.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
file_upload |
body (multipart) | file | Yes | CSV (text/csv) with exactly the columns Data,Hora,Contador,Valor Compra,Valor Venda, see template_opportunity_cost.csv |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs/file_upload \
-H "Authorization: Bearer $TOKEN" \
-F "file_upload=@template_opportunity_cost.csv;type=text/csv"
Data,Hora,Contador,Valor Compra,Valor Venda
01/05/2023,00:15,ginasio,0.200,0.111
01/05/2023,00:30,ginasio,0.400,0.111
Response (abridged)
Tip
Contadoris the meteridentifier; unknown identifiers fail the task.Valor Comprabecomesl_buyandValor Vendabecomesl_sell.- Wrong content type returns
404and wrong headers403. Maximum 36,000 rows. - Rows are stored with
is_upload = true, replacing earlier uploaded rows for the same interval and meter, and the sessions of those intervals are invalidated. - The upload must cover every session and every CPE of the period being cleared, otherwise market clearing is refused.
Upload Opportunity Costs¶
Uploads opportunity costs as JSON, using meter UUIDs. Processed synchronously.
Auth / permissions: community admin or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
| body | body | array | Yes | Each item: datetime_timestamp (datetime, interval start), meter_id (UUID), l_buy (float, EUR/kWh), l_sell (float, EUR/kWh) |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{ "datetime_timestamp": "2023-05-01T00:00:00+01:00", "meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "l_buy": 0.2, "l_sell": 0.111 },
{ "datetime_timestamp": "2023-05-01T00:15:00+01:00", "meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "l_buy": 0.4, "l_sell": 0.111 }
]'
Response (abridged)
Tip
- Returns
400(No records provided.) for an empty array and404(Some meters were not found in the database.) when anymeter_iddoes not exist. - Rows are stored with
is_upload = true(anyis_uploadormeter_namein the body is ignored) and the affected sessions are invalidated, so reopened sessions need market clearing and settlement again. - The meters are looked up globally, not only in this community; send only meters of the community.
List Opportunity Costs (Paginated)¶
Paginated opportunity costs of the community, for the opportunity cost table.
Auth / permissions: any community member or platform admin.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community |
limit |
query | integer | Yes | Page size |
offset |
query | integer | Yes | Rows to skip |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
meter_id |
query | UUID | No | Filter by meter |
is_upload |
query | boolean | No | true uploaded only, false calculated only |
sort_column |
query | string | No | date, time, meter_id (by meter identifier) or a column (datetime_timestamp, l_buy, l_sell) |
sort_direction |
query | string | No | asc for ascending, otherwise descending |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/opportunity_costs/pagination?limit=50&offset=0&is_upload=true&sort_column=date&sort_direction=asc" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"total_count": 96,
"data": [
{
"datetime_timestamp": "2023-04-30T23:00:00+00:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"meter_name": null,
"l_buy": 0.2,
"l_sell": 0.111,
"is_upload": true
}
],
"distinct_dates": [{ "date": "2023-05-01" }],
"distinct_times": [{ "time": "00:00:00" }]
}
Tip
meter_name is not filled by this endpoint; use by_community?include_meter_name=true when you need the identifier.
OMIE¶
OMIE day-ahead electricity prices used by indexed contracts and by VANILLA_INTERMEDIATE_MARKET_RATE (see Market). Prices are global,
not per community, and are in EUR/MWh (the platform divides by 1000 where EUR/kWh is needed). The platform fetches missing OMIE data itself when it needs it; these endpoints only read it.
Get OMIE Prices¶
Returns OMIE prices, optionally for a date range and aggregated to a coarser granularity.
Auth / permissions: no authentication dependency is declared on this router in the code (public).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
start_date |
query | date | No | First day, YYYY-MM-DD. Both dates are needed to filter |
end_date |
query | date | No | Last day, inclusive |
granularity |
query | string | No | MIN15 (default), HOUR, DAY, MONTH or YEAR. Only applied when both dates are given |
Example
Response (abridged)
[
{ "datetime_timestamp": "2025-01-01T00:00:00+01:00", "price": 98.4, "adjustment": 0.0, "id": null }
]
Tip
- Without
start_dateandend_dateit returns every stored row, newest first, ignoringgranularity; always send both dates for normal use. - With a range, the price of each bucket is the mean of the underlying prices, buckets are computed in
Europe/Lisbon, andadjustmentis always0.0. - Returns
[]when there is no data in the range (including future dates beyond what OMIE has published).
Get OMIE Prices (Paginated)¶
Paginated OMIE prices, for the OMIE table.
Auth / permissions: no authentication dependency is declared on this router in the code (public).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
limit |
query | integer | Yes | Page size |
offset |
query | integer | Yes | Rows to skip |
date |
query | string | No | Filter by date, YYYY-MM-DD |
time |
query | string | No | Filter by time, HH:MM:SS |
sortColumn |
query | string | No | date, time, price, adjustment or datetime_timestamp |
sortDirection |
query | string | No | asc or desc. Both sort parameters are needed to sort |
Example
curl "https://<host>/core/api/omie/pagination?limit=24&offset=0&date=2025-01-01&sortColumn=time&sortDirection=asc"
Response (abridged)
{
"total_count": 96,
"data": [
{ "datetime_timestamp": "2025-01-01T00:00:00+01:00", "price": 98.4, "adjustment": 0.0, "id": null }
],
"distinct_dates": [{ "date": "2025-01-01" }]
}
Tip
Uses camelCase sortColumn / sortDirection. Without both, rows are ordered newest first. Unlike other paginated endpoints, the response has no distinct_times.