Sizing & Simulation API¶
Base paths:
/core/api/communities/{community_id}/sizing_general_parameters/core/api/communities/{community_id}/sizing_meter_static_parameters/core/api/communities/{community_id}/meter_dynamic_parameters/core/api/communities/{community_id}/payload/core/api/communities/{community_id}/sizing_simulation/core/api/simulator
The Sizing module is a pre-delivery planning tool: given a community's meters, contracts, consumption and
generation profiles, it runs a MILP (the rec_sizing collective-pool model) that suggests the optimal contracted
power and the optimal new PV (RES) and battery capacity per CPE, together with the resulting energy flows
between members. See the Glossary and the Platform Overview for where sizing fits.
It is separate from the Energy Management modules described in Optimization.
A sizing run follows this order:
- Store the community-wide general parameters (one row per community).
- Store per-meter static parameters (investment costs, capacity limits) for each CPE.
- Make sure the community has CPEs with contracts, linked SCPU/STORAGE resources, loads and opportunity costs for the sizing period.
- Call build and simulate. It returns
202immediately and the MILP runs in a Celery task. - Read the results (replaced on every run).
The Simulator endpoints at the end of the page are a different feature: they build a complete demo community from a simulator export file and trigger market and settlement tasks on it.
Units and time
Energy is in kWh, power in kW, prices and tariffs in EUR (see each field). Result timestamps are returned in the
platform time zone (Europe/Lisbon). Sizing steps are 15 minutes (delta_t = 0.25) or hourly (delta_t = 1).
Business validity
A sizing period cannot cross a day on which the community structure changes. The check runs inside the Celery task (not in the HTTP response); see Business Validity.
Authentication coverage
Only the general-parameters router (GET, POST, PUT on sizing_general_parameters) and the simulator router
declare authentication dependencies in the code. The static-parameters, dynamic-parameters, payload and
sizing-simulation routers declare no authentication or permission dependency. Always send the bearer token
regardless, as described in Authentication.
Endpoint summary¶
| Method | Path | Purpose |
|---|---|---|
| POST | /core/api/communities/{community_id}/sizing_general_parameters |
Create (or update) the community's general sizing parameters |
| GET | /core/api/communities/{community_id}/sizing_general_parameters |
Get the general parameters of a community |
| GET | /core/api/communities/{community_id}/sizing_general_parameters/{general_params_id} |
Get general parameters by ID |
| PUT | /core/api/communities/{community_id}/sizing_general_parameters/{general_params_id} |
Partially update general parameters |
| POST | /core/api/communities/{community_id}/sizing_meter_static_parameters |
Create static sizing parameters for a meter |
| GET | /core/api/communities/{community_id}/sizing_meter_static_parameters/{meter_id} |
List static parameters of a meter |
| PUT | /core/api/communities/{community_id}/sizing_meter_static_parameters/{parameter_id} |
Update static parameters |
| POST | /core/api/communities/{community_id}/meter_dynamic_parameters |
Upload dynamic parameters (consumption CSV) |
| PUT | /core/api/communities/{community_id}/meter_dynamic_parameters/{meter_id} |
Update dynamic parameter rows of a meter |
| POST | /core/api/communities/{community_id}/payload/build_and_simulate |
Build the sizing payload and run the simulation |
| GET | /core/api/communities/{community_id}/sizing_simulation/results |
Get sizing simulation results |
| POST | /core/api/simulator |
Create a demo community from a simulator export |
| POST | /core/api/simulator/{community_id}/simulationtask/{task_name} |
Run a market/settlement/EMS task on a simulator community |
General Parameters¶
One row of general parameters exists per community. They configure the MILP as a whole.
| Field | Type | Description |
|---|---|---|
nr_days |
integer | Number of days to consider. Stored, but the payload builder derives the number of days from the start_date and end_date of the run (end_date - start_date + 1) |
nr_clusters |
integer | Number of representative days for clustering time series. 0 disables clustering; the value is only sent to the solver when greater than 0 and the solver ignores values larger than the number of days |
l_grid |
number | Access tariff for self-consumed energy, EUR/kWh. Expanded to a constant array over the sizing period |
delta_t |
number | Optimization step in hours: 0.25 (15 minutes) or 1 (hourly). With any value other than 0.25, the 15-minute inputs are aggregated to hourly |
storage_ratio |
number | Reference ratio between maximum storage input/output power and nominal capacity (kW/kWh) used for new storage suggestions |
strict_pos_coeffs |
boolean | If true, dynamic allocation coefficients must be strictly positive |
total_share_coeffs |
boolean | If true, meters with surplus must share all of it with consuming meters when the community has a deficit |
Create or Update General Parameters¶
Creates the general parameters of a community and returns 201. The router is written as an upsert: if the
community already has a row, it should update it instead of creating a second one.
Auth / permissions: any authenticated user (get_current_user); the community must exist. The router does not check
community membership.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
community_id |
body | UUID | Yes | Required by the schema (otherwise 422), but overwritten with the path value on creation |
nr_days |
body | integer | Yes | See table above |
nr_clusters |
body | integer | Yes | See table above |
l_grid |
body | number | Yes | EUR/kWh |
delta_t |
body | number | Yes | 0.25 or 1 |
storage_ratio |
body | number | Yes | kW/kWh |
strict_pos_coeffs |
body | boolean | Yes | |
total_share_coeffs |
body | boolean | Yes |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_general_parameters \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"nr_days": 30,
"nr_clusters": 0,
"l_grid": 0.05,
"delta_t": 0.25,
"storage_ratio": 1,
"strict_pos_coeffs": true,
"total_share_coeffs": true
}'
Response (abridged)
{
"id": "9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"nr_days": 30,
"nr_clusters": 0,
"l_grid": 0.05,
"delta_t": 0.25,
"storage_ratio": 1.0,
"strict_pos_coeffs": true,
"total_share_coeffs": true
}
Known issue: calling POST when parameters already exist
The "update existing" branch calls crud.update_general_parameters, which does not exist in the CRUD module (the
function is named update_sizing_general_parameters). As the code stands, a second POST for the same community
fails with 500. Use PUT /core/api/communities/{community_id}/sizing_general_parameters/{general_params_id} to
change existing parameters.
Tip
No uniqueness constraint exists on community_id in the table, so always GET first (or rely on the 404) before creating.
The sizing payload builder reads the first row found for the community, and returns an error in the Celery task
if none exists.
Get General Parameters of a Community¶
Returns the general parameters of the community. Use it to decide between POST and PUT.
Auth / permissions: any authenticated user (get_current_user); the community must exist.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
Example
curl https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_general_parameters \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"id": "9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"nr_days": 30,
"nr_clusters": 0,
"l_grid": 0.05,
"delta_t": 0.25,
"storage_ratio": 1.0,
"strict_pos_coeffs": true,
"total_share_coeffs": true
}
Tip
Returns 404 with "General parameters for the specified community not found." when none were created yet, and
404 (Community with id: ... does not exist.) when the community itself is unknown.
Get General Parameters by ID¶
Returns one general-parameters row by its own ID.
Auth / permissions: any authenticated user (get_current_user); the community must exist.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
general_params_id |
path | UUID | Yes | ID of the general-parameters row |
Example
curl https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_general_parameters/9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42 \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
{
"id": "9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"nr_days": 30,
"nr_clusters": 0,
"l_grid": 0.05,
"delta_t": 0.25,
"storage_ratio": 1.0,
"strict_pos_coeffs": true,
"total_share_coeffs": true
}
Tip
The lookup uses only general_params_id; it does not verify that the row belongs to the community_id in the path.
Returns 404 (General parameters not found) for an unknown ID.
Update General Parameters¶
Partially updates a general-parameters row. Only the fields present (not null) in the body are changed.
Auth / permissions: any authenticated user (get_current_user); the community must exist.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
general_params_id |
path | UUID | Yes | ID of the general-parameters row |
nr_days |
body | integer | No | |
nr_clusters |
body | integer | No | |
l_grid |
body | number | No | EUR/kWh |
delta_t |
body | number | No | 0.25 or 1 |
storage_ratio |
body | number | No | kW/kWh |
strict_pos_coeffs |
body | boolean | No | |
total_share_coeffs |
body | boolean | No |
Example
curl -X PUT https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_general_parameters/9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"delta_t": 1, "nr_clusters": 5}'
Response (abridged)
{
"id": "9b2f1c1e-6a3d-4f6e-8f55-0d9b6c1a7e42",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"nr_days": 30,
"nr_clusters": 5,
"l_grid": 0.05,
"delta_t": 1.0,
"storage_ratio": 1.0,
"strict_pos_coeffs": true,
"total_share_coeffs": true
}
Tip
Because null means "leave unchanged", this endpoint cannot be used to clear a value; all columns are required in the database anyway.
Returns 404 for an unknown general_params_id. Setting delta_t to 1 makes the sizing run aggregate
consumption (sum) and opportunity costs (average) to hourly values.
Meter Static Parameters¶
Static parameters hold the per-meter economic and capacity inputs of the MILP. They are read for each CPE meter
that has contracts. A CPE without a row is sent to the solver with all of these values set to 0.0.
| Field | Type | Description |
|---|---|---|
l_cont |
number | Contracted-power tariff of the meter, adjusted to one day (EUR/kW.day) |
l_gic |
number | Investment cost of new RES (PV) capacity, adjusted to one day over the panel lifespan (EUR/kW.day) |
l_bic |
number | Investment cost of new storage capacity, adjusted to one day over the battery lifespan |
p_meter_max |
number | Maximum power the meter can safely handle (kW); constrains the total contracted power |
p_gn_min |
number | Minimum new RES capacity to install at the meter (kW) |
p_gn_max |
number | Maximum new RES capacity to install at the meter (kW) |
e_bn_min |
number | Minimum storage capacity to install at the meter (kWh) |
e_bn_max |
number | Maximum storage capacity to install at the meter (kWh) |
All fields are optional. The table enforces one row per (meter_id, community_id).
Create Static Parameters¶
Creates the static sizing parameters of one meter.
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | string (UUID) | Yes | Community ID; overwrites community_id in the body |
meter_id |
body | UUID | Yes | CPE meter these parameters belong to |
community_id |
body | UUID | Yes | Required by the schema, then replaced by the path value |
l_cont, l_gic, l_bic |
body | number | No | Costs, see table above |
p_meter_max, p_gn_min, p_gn_max |
body | number | No | kW |
e_bn_min, e_bn_max |
body | number | No | kWh |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_meter_static_parameters \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"l_cont": 0.042753623,
"l_gic": 0.009343915,
"l_bic": 0.000547945,
"p_meter_max": 41.4,
"p_gn_min": 0,
"p_gn_max": 30,
"e_bn_min": 0,
"e_bn_max": 60
}'
Response (abridged)
{
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"l_cont": 0.042753623,
"l_gic": 0.009343915,
"l_bic": 0.000547945,
"p_meter_max": 41.4,
"p_gn_min": 0.0,
"p_gn_max": 30.0,
"e_bn_min": 0.0,
"e_bn_max": 60.0
}
Tip
The response model is the create schema, so the generated row id is not returned; fetch it with the GET below
when you need to PUT. A second row for the same meter and community violates the unique index; the router
wraps every error in a generic handler, so this and a non-existent meter_id both surface as 500 with the
database error text in detail.
List Static Parameters of a Meter¶
Returns the static parameter rows of a meter (at most one in practice, because of the unique index).
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | string | Yes | Community ID (not used by the lookup) |
meter_id |
path | string (UUID) | Yes | Meter ID |
Example
curl https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_meter_static_parameters/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"id": "0d6f3b52-92a4-4f0a-9a1f-6b6a5e1d2c33",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"l_cont": 0.042753623,
"l_gic": 0.009343915,
"l_bic": 0.000547945,
"p_meter_max": 41.4,
"p_gn_min": 0.0,
"p_gn_max": 30.0,
"e_bn_min": 0.0,
"e_bn_max": 60.0
}
]
Tip
Returns [] (not 404) when the meter has no static parameters. The lookup filters only by meter_id. An invalid
UUID is rejected with an error that surfaces as 500 (see the create endpoint).
Update Static Parameters¶
Updates a static-parameters row by its own ID.
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | string | Yes | Community ID (not used by the update) |
parameter_id |
path | string (UUID) | Yes | ID of the static-parameter row (from the GET above) |
l_cont, l_gic, l_bic |
body | number | No | Costs |
p_meter_max, p_gn_min, p_gn_max |
body | number | No | kW |
e_bn_min, e_bn_max |
body | number | No | kWh |
Example
curl -X PUT https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_meter_static_parameters/0d6f3b52-92a4-4f0a-9a1f-6b6a5e1d2c33 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"l_cont": 0.042753623,
"l_gic": 0.009343915,
"l_bic": 0.000547945,
"p_meter_max": 50,
"p_gn_min": 0,
"p_gn_max": 40,
"e_bn_min": 0,
"e_bn_max": 80
}'
Response (abridged)
{
"l_cont": 0.042753623,
"l_gic": 0.009343915,
"l_bic": 0.000547945,
"p_meter_max": 50.0,
"p_gn_min": 0.0,
"p_gn_max": 40.0,
"e_bn_min": 0.0,
"e_bn_max": 80.0
}
Warning
This is a full replace, not a patch: every field of the schema is written, so any field omitted from the body is
saved as null (treated as 0.0 by the sizing run). Always send the complete set of values.
Tip
An unknown parameter_id raises 404 (Static meter parameter not found.) inside a blanket error handler, so the
client receives 500 with 404: Static meter parameter not found. in detail.
Meter Dynamic Parameters¶
Dynamic parameters are time-series rows per meter (datetime_timestamp, l_buy, l_sell, e_c, e_g_factor).
Upload historical consumption with the CSV template
Sizing energy consumed (also listed in Upload Templates).
Current usage by the sizing run
The payload builder currently takes consumption and generation from the community Loads (see
Loads API) and costs from opportunity costs. The block that would read e_c from the dynamic
parameters is commented out in the code, so uploaded dynamic parameters are stored but do not feed
build_and_simulate. There is no GET endpoint for dynamic parameters.
Upload Dynamic Parameters¶
Uploads a CSV with historical consumption per meter. The file is processed asynchronously by the
upload_meter_dynamic_parameters Celery task (queue file_uploads).
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | string (UUID) | Yes | Community ID |
file_upload |
body (multipart) | file | Yes | UTF-8 CSV with columns DateTime, Contador, e_c |
CSV columns:
| Column | Description |
|---|---|
DateTime |
DD/MM/YYYY HH:MM, for example 01/05/2023 00:15 |
Contador |
Meter identifier, which must exist in the community. Rows without it would have no meter and be rejected by the database |
e_c |
Energy consumed in the interval, kWh |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/meter_dynamic_parameters \
-H "Authorization: Bearer $TOKEN" \
-F "file_upload=@template_sizizing_e_consumed.csv"
Response (abridged)
Tip
Poll GET /core/api/communities/{community_id}/tasks/{task_id}?group_task=false for the outcome. On success the task
result reads Successfully inserted N dynamic meter parameters. Failures inside the task (missing e_c header, bad
date format, unknown meter identifier) are reported through the task state, not the HTTP response. Rows are
appended; re-uploading does not replace earlier rows. An invalid community_id is intended to return 400, but because of
the blanket error handler it returns 500 (Internal Server Error).
Update Dynamic Parameters of a Meter¶
Updates existing dynamic-parameter rows of a meter. The body is a list of objects, each identifying a row by its id.
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | string (UUID) | Yes | Community ID |
meter_id |
path | string (UUID) | Yes | Meter ID |
[].id |
body | UUID | Yes | ID of the dynamic-parameter row to update |
[].l_buy |
body | number | No | Defaults to 0.0 when omitted |
[].l_sell |
body | number | No | Defaults to 0.0 when omitted |
[].e_c |
body | number | No | Consumption in kWh; defaults to 0.0 when omitted |
[].e_g_factor |
body | number | No | Generation factor; defaults to 0.0 when omitted |
Example
curl -X PUT https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/meter_dynamic_parameters/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"id": "b1e2c3d4-0000-4000-8000-000000000001", "l_buy": 0.18, "l_sell": 0.05, "e_c": 0.678, "e_g_factor": 0}
]'
Response
Warning
Fields missing from an object are written as 0.0, so send all four values every time. Rows whose id does not
exist for that meter and community are silently skipped (the call still succeeds). A missing id or an invalid UUID is
intended to return 400, but the blanket error handler turns it into 500 with the original message in detail.
Run Sizing¶
Build Payload and Run Simulation¶
Starts the sizing simulation in the background (Celery task simulation_background_task, queue default). The task
builds the rec_sizing input from the community data, solves the MILP (CPLEX solver) and stores the results,
replacing all previous sizing results of the community.
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
start_date |
body | date (YYYY-MM-DD) |
Yes | First day of the sizing period |
end_date |
body | date (YYYY-MM-DD) |
Yes | Last day of the sizing period (inclusive) |
Example
curl -X POST https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/payload/build_and_simulate \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"start_date": "2024-05-01", "end_date": "2024-05-31"}'
Response (202 Accepted)
{
"message": "Simulation started in background",
"task_id": "6f5b1a52-5d1c-4c0e-9a0b-2e8a1f3d9c10"
}
Tip
What the task needs (any gap makes the task fail; the HTTP call has already returned 202, so check
GET /core/api/communities/{community_id}/tasks/{task_id}?group_task=false):
- the period must not cross a business-validity boundary (error
Operation crosses a business-context boundary on YYYY-MM-DD); - general parameters for the community (
No general static parameters found); - meters of type
CPEthat have at least one contract; other meter types are not simulated; - opportunity costs (
l_buy,l_sell) for every such CPE across the period (No opportunity cost data for meter ...); - loads for the period (Loads API) for consumption
e_cand, when present, generation.
How inputs are assembled
SCPUandSTORAGEresources are linked to a CPE through their meter'scpe_id(resources on internal meters under the CPE). An SCPU'sgeneration_capacitybecomes the initial PV capacity (p_gn_init); a STORAGE's nominal capacity,min_SOC,max_SOC, efficiencies anddeg_costbecome the initial storage parameters (efficiencies default to 90% when missing).- Missing static parameters become
0.0. - Generation factors (
e_g_factor) come from the loads' generation normalized by the initial PV capacity. If no meter has generation data, hourly/15-minute PVGIS factors are fetched using the geocoded community address (the community must have an address). nr_daysis computed from the request dates, not from the stored general parameters.
The task result is Simulation completed successfully. or Simulation failed: <reason>.
Sizing Results¶
Get Sizing Simulation Results¶
Returns the stored results of the last sizing run, one row per meter and time step, ordered by datetime_timestamp.
Auth / permissions: no authentication or permission dependency is declared in the router code.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
start_date |
query | string (YYYY-MM-DD) |
No | Keep rows from this day, interpreted as 00:00 UTC |
end_date |
query | string (YYYY-MM-DD) |
No | Keep rows up to 23:59:59 of this day (UTC) |
meter_id |
query | UUID | No | Return only this meter's rows |
Example
curl "https://<host>/core/api/communities/3fa85f64-5717-4562-b3fc-2c963f66afa6/sizing_simulation/results?start_date=2024-05-01&end_date=2024-05-02&meter_id=7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-H "Authorization: Bearer $TOKEN"
Response (abridged)
[
{
"datetime_timestamp": "2024-05-01T01:00:00+01:00",
"meter_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"community_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"obj_value": 1234.56,
"milp_status": "Optimal",
"p_cont": 6.9,
"p_gn_new": 12.0,
"p_gn_total": 12.0,
"e_bn_new": 10.0,
"e_bn_total": 10.0,
"e_cmet": 0.45,
"e_g": 0.0,
"e_sup": 0.45,
"e_sur": 0.0,
"e_bat": 5.0,
"dual_prices": 0.07
}
]
Fields per row (all numeric fields are nullable). Meter-level values (p_*, e_bn_*, c_ind2pool) repeat on every
time step of that meter; obj_value, milp_status, delta_rec_balance and dual_prices are community-level values repeated on every
row.
| Group | Fields | Meaning |
|---|---|---|
| Identification | datetime_timestamp, meter_id, community_id |
Time step start, CPE meter, community |
| Solution | obj_value, milp_status |
Objective value and solver status |
| Sizing decisions | p_cont, p_gn_new, p_gn_total, e_bn_new, e_bn_total |
Contracted power, new / total PV capacity (kW), new / total battery capacity (kWh) |
| Energy flows | e_cmet, e_g, e_bc, e_bd, e_bat, e_sup, e_sur, e_consumed |
Meter consumption, PV generation, battery charge / discharge / stored energy, retailer supply, surplus, energy consumed |
| Local market | e_pur_pool, e_sale_pool, e_slc_pool, e_alc, c_ind2pool |
Pool purchase / sale / selection, allocated energy, individual contribution to the pool |
| Deltas and prices | delta_sup, delta_slc, delta_coeff, delta_rec_balance, delta_meter_balance, dual_prices |
Auxiliary solver variables and dual prices |
Tip
Returns 404 (No simulation results found for the given criteria.) instead of an empty list when nothing matches, and
400 for a date not in YYYY-MM-DD format. Time steps start at start_date 00:00 UTC of the run and advance by 15 minutes
(delta_t = 0.25) or 60 minutes (delta_t = 1); timestamps are returned converted to Europe/Lisbon. The optional EV and
EWH series of the solver output are not stored or returned. Each new run deletes all earlier results of the community.
Simulator¶
The simulator endpoints belong to the Simulation operation mode (see the Overview): they build a community from
a simulator export and run the operational tasks on it. The router requires is_allowed and get_current_user.
Create a Community from a Simulator Export¶
Creates a DEMO community together with its members, meters, resources, ownerships, RESP, contracts, fixed bilateral
prices and (optionally) ERSE, loads and DSO files, in one multipart request. The caller becomes the community admin.
Auth / permissions: platform admin (SUPER_USER) only. The path has no community, so the permission rules reject any
other role's write request with 403 (Only super-users can perform this action).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
basic_info |
form | JSON string (object) | Yes | community_name, community_identifier, allocation, start_date (required); end_date; community_or_aggregator_type (default EGAC); market_rate (default VANILLA_IMR); market_divisor (0.5); market_compensation (0.5); market_small_increment (0.1); market_fixed_price (0.0805) |
members |
form | JSON string (array) | Yes | name, pre_id (UUID chosen by the client), is_host, is_promoter, start_date, end_date |
meters |
form | JSON string (array) | Yes | name (becomes the identifier), pre_id, type (CPE, INTERNAL, AGGREGATOR_METER), cpe (pre_id of the parent CPE for internal meters), installation_type (IC, IPR, IA, IAC), production_identifier, start_date, end_date |
resources |
form | JSON string (array) | Yes | name, pre_id, type, sumCertifiedPower, voltageLevel, type-specific camelCase fields (for example generationCapacity, nominalCapacity, maxPower, minSOC), ownerships (member pre_id, perc, dates), optional meter (pre_id), start_date, end_date |
resp |
form | JSON string (array) | Yes | provider_meter_id, receiver_meter_id (meter pre_ids), is_active, start_date, end_date |
contracts |
form | JSON string (array) | Yes | member (pre_id), optional meter (pre_id of a CPE/aggregator meter), buy_type, sell_type, voltage_level, tariff_cycle, with_holidays, contracted_power, start_date (alias validity), end_date, buy_payload, sell_payload |
fixed_bilateral_prices |
form | JSON string (array) | No | provider_user_id, receiver_user_id (member pre_ids), price, start_date, end_date |
loads_files |
file (repeatable) | CSV | No | Loads files, validated and imported synchronously |
dso_file |
file | DSO file | No | Validated and imported synchronously |
erse_tariffs |
file (repeatable) | file | No | Only the first file is used |
erse_losses |
file (repeatable) | file | No | Every file is imported |
Enumerations are in Enums & Constants, community fields in Create a Community, and the equivalent single-call preload flow in Create a community in One Call.
Example
curl -X POST https://<host>/core/api/simulator \
-H "Authorization: Bearer $TOKEN" \
-F 'basic_info={"community_name":"Demo REC","community_identifier":"demo-rec","allocation":"PROPORTIONAL","start_date":"2024-01-01"}' \
-F 'members=[{"name":"Alice","pre_id":"11111111-1111-4111-8111-111111111111","is_host":true,"start_date":"2024-01-01"}]' \
-F 'meters=[{"name":"CPE-A","pre_id":"22222222-2222-4222-8222-222222222222","type":"CPE","cpe":"22222222-2222-4222-8222-222222222222","installation_type":"IAC","start_date":"2024-01-01"}]' \
-F 'resources=[{"name":"PV-A","pre_id":"33333333-3333-4333-8333-333333333333","type":"SCPU","sumCertifiedPower":10,"voltageLevel":"BTN>","generationCapacity":10,"ownerships":[{"member":"11111111-1111-4111-8111-111111111111","perc":100,"start_date":"2024-01-01"}],"start_date":"2024-01-01"}]' \
-F 'resp=[]' \
-F 'contracts=[{"member":"11111111-1111-4111-8111-111111111111","meter":"22222222-2222-4222-8222-222222222222","buy_type":"FIXED","sell_type":"FIXED","voltage_level":"BTN>","tariff_cycle":"BI_DIARIO","with_holidays":false,"contracted_power":6.9,"start_date":"2024-01-01"}]' \
-F "loads_files=@loads.csv;type=text/csv"
Response (201 Created)
Tip
The response does not contain the new community ID; look it up afterwards by its identifier (for example with
GET /core/api/communities). The pre_id values are client-side IDs used only to cross-reference the arrays
in the same request; the real IDs are generated by the platform. Members get a generated email
(email.<name>@cer.com) and address.
Validation raised by the route: 409 for duplicate resource names (case-insensitive, trimmed) and for two resources on the same CPE or internal meter in overlapping periods
(add internal meters instead); 422 for a resource linked to an unknown or invalid meter; 400 for a contract that
references an unknown CPE meter. Malformed JSON or schema violations in the form fields are parsed manually and are
not converted to 422. The route has no surrounding rollback, so a failure halfway can leave a partially created community.
When contracts[].meter is omitted (legacy simulator files), contracts are matched by position to the CPE and aggregator meters, in order.
Loads files must be text/csv (see Loads API). The community is created with the periods from start_date / end_date; see
Business Validity.
Run a Simulation Task¶
Triggers one of a fixed set of asynchronous operations on a community, mainly to re-run history in simulation mode. Each branch queues a Celery task and returns its ID.
Auth / permissions: is_allowed on the community: platform admin or community admin (a plain member gets 403 because this is a POST). The
community must exist (404 otherwise).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
community_id |
path | UUID | Yes | Community ID |
task_name |
path | string | Yes | One of calculate_opportunity_costs, open_sessions, clear_market, run_settlement, run_pre_delivery_energy_management |
start_date |
body | date | Depends | Required by calculate_opportunity_costs; optional for open_sessions |
end_date |
body | date | Depends | Required by calculate_opportunity_costs; optional for open_sessions |
use_dso_measurements |
body | boolean | No | Default false. Used by clear_market and run_settlement |
task_name |
Effect | Body fields used |
|---|---|---|
calculate_opportunity_costs |
Computes opportunity costs between the dates (feeds sizing; see Run Sizing) | start_date, end_date |
open_sessions |
Opens all sessions of the community, optionally limited to the dates | start_date, end_date |
clear_market |
Clears the local market (Market) | use_dso_measurements |
run_settlement |
Runs settlement | use_dso_measurements |
run_pre_delivery_energy_management |
Calculates EMS setpoints for the community (Energy Management) | none |
Example
curl -X POST https://<host>/core/api/simulator/3fa85f64-5717-4562-b3fc-2c963f66afa6/simulationtask/clear_market \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"use_dso_measurements": false}'
Response (abridged)
Tip
An unknown task_name is not rejected: the endpoint returns 200 with a null body. For calculate_opportunity_costs
the body is mandatory; omitting it fails with 500. Poll
GET /core/api/communities/{community_id}/tasks/{task_id}?group_task=false for task status.
Warning
The function signature exposes a db_url parameter with a default taken from the server settings, which FastAPI publishes as an
optional query parameter. It is meant for internal use; do not set it from clients.