Guide: Creating a Promoter-based Community¶
This guide walks through the full API call sequence to create a community based on the Promoter-Anchor business model, where a Promoter owns a generation asset (PV) installed behind an Anchor member's CPE and sells energy to the community.
Payloads may change
Specific endpoint payloads may change as DSO data expectations are clarified. Read the earlier concept pages before continuing, and consult the API Reference for authoritative field definitions.
Scenario Overview¶
We will create:
- 1 Community — Dynamic allocation with Tree Dynamic Allocation (
TREE_DNAC) market pricing - 4 Members — Anchor (Host), Promoter, Consumer 1, Consumer 2
- 3 CPEs — one for the Anchor (prosumer/IAC), two for consumers (IC)
- 2 Internal Meters — both behind the Anchor CPE: one for house consumption, one for PV generation
- 3 Contracts — one per CPE
- 4 Resources/Assets — Anchor (IC), Promoter PV (SCPU), Consumer 1 (IC), Consumer 2 (IC)
graph TD
subgraph CPE_C1["CPE Consumer1 — PT000...1AA (IC)"]
RC1["Consumer1 Resource (IC)"]
end
subgraph CPE_A["CPE Anchor HOST — PT000...1BB (IAC)"]
subgraph INT_A["Anchor Internal Meter"]
RA["Anchor Resource (IC)"]
end
subgraph INT_P["Promoter PV Internal Meter"]
RP["Promoter PV Resource (SCPU)"]
end
end
subgraph CPE_C2["CPE Consumer2 — PT000...1CC (IC)"]
RC2["Consumer2 Resource (IC)"]
end
RP -->|"Sells at 70 €/MWh"| INT_A
RP -->|"Sells at 80 €/MWh"| CPE_C1
RP -->|"Sells at 80 €/MWh"| CPE_C2
Every API call returns the created object alongside its UUID, which you will need for subsequent calls.
Step 1 — Create the Community¶
POST /core/api/communities
This uses DYNAMIC allocation coefficients and TREE_DNAC — a decision-tree algorithm for
computing dynamic allocation coefficients per interval.
Simpler alternative
For a proof-of-concept integration you may set method_alloc_coeff to PROPORTIONAL,
which requires no dynamic coefficient submission to the DSO.
{
"name": "communityname",
"community_identifier": "111ACC",
"type": "PROD",
"method_alloc_coeff": "DYNAMIC",
"market_rate": "TREE_DNAC"
}
Step 1 (alternative) — Create Full Community in One Call¶
POST /core/api/communities
See the dedicated guide: Creating a Community in One Call
The preload approach creates the entire community structure (members, meters, contracts,
resources, and bilateral prices) in a single API call using *_ref forward references,
instead of the multi-step sequence above.
Step 2 — Create the Anchor/Host Member¶
POST /core/api/communities/{community_id}/users
Terminology: Anchor = Host
Anchor and Host are used interchangeably throughout this documentation and the API. Both refer to the same member role: the priority member who typically hosts the generation asset behind their CPE.
Set is_host to true. This designates the member as an Anchor (also called Host) — a
member with priority in the business model who typically hosts the generation asset behind
their CPE.
{
"name": "Anchor Client XXX",
"role": "MEMBER",
"status": "ACTIVE",
"is_host": true,
"is_promoter": false
}
Save the returned UUID as anchor_user_id.
Step 3 — Create the Promoter¶
POST /core/api/communities/{community_id}/users
Set is_promoter to true. The Promoter is the entity that owns the generation asset (e.g.
the PV panels) and sells that energy to community members.
Save the returned UUID as promoter_user_id.
Step 4 — Create Consumer Members (×2)¶
POST /core/api/communities/{community_id}/users
Terminology: Consumer = OffTaker = NonHost
Consumer, OffTaker, and NonHost all refer to the same member type: a member that consumes energy from the community without owning production assets.
For each consumer, set both is_host and is_promoter to false.
{
"name": "Consumer1",
"role": "MEMBER",
"status": "ACTIVE",
"is_host": false,
"is_promoter": false
}
Repeat for Consumer 2. Save the returned UUIDs as consumer1_user_id and consumer2_user_id.
Step 5 — Create the Anchor CPE¶
POST /core/api/communities/{community_id}/meters
The Anchor CPE is a Prosumer installation (IAC) because the Promoter's PV sits behind it.
This requires both identifier (consumption point) and production_identifier (injection
point), as Prosumers are metered separately for consumption and generation by the DSO.
{
"identifier": "PT002XXXXXXX",
"production_identifier": "PT002XXXXXXX",
"type": "CPE",
"installation_type": "IAC",
"status": "ACTIVE"
}
Save the returned UUID as anchor_cpe_id.
Step 6 — Create the Anchor Internal Meter¶
POST /core/api/communities/{community_id}/meters
This internal meter measures the Anchor member's house consumption behind the CPE. The
identifier can be any common name or internal ID.
cpe_id vs identifier
The cpe_id must be the UUID returned in Step 5 — the internal database ID of the CPE
meter — not the CPE's identifier string.
{
"identifier": "HouseMeter1",
"type": "INTERNAL",
"status": "ACTIVE",
"cpe_id": "<anchor_cpe_id>"
}
Save the returned UUID as anchor_internal_meter_id.
Step 7 — Create the Promoter PV Internal Meter¶
POST /core/api/communities/{community_id}/meters
This internal meter measures the PV generation from the Promoter's solar panels, also
located behind the Anchor CPE. Use the same cpe_id as Step 6.
Save the returned UUID as promoter_pv_meter_id.
Step 8 — Create Consumer CPEs (×2)¶
POST /core/api/communities/{community_id}/meters
Consumer CPEs use installation_type: IC (Consumption Installation) since they have no local
generation.
Repeat for Consumer 2. Save the returned UUIDs as consumer1_cpe_id and consumer2_cpe_id.
Step 9 — Create Contracts (×3, one per CPE)¶
POST /core/api/communities/{community_id}/meters/{meter_id}/contracts
Create one contract per CPE. The user_id is the member responsible for the CPE (Anchor for
the Anchor CPE, each Consumer for their own). The meter_id in the path is the CPE UUID.
This scenario uses FIXED buy/sell types. Define peak, mid_peak, off_peak, and
super_off_peak values per your retailer contracts. Multipliers can be left at 1 or adjusted:
Buy Price = Period_Price + (MultiplierPMD × Network_Access_Tariff)
+ (MultiplierERSE × Peak_Hour_Power_Tariff × 4 × Days_In_Month / N_Peak_Periods)
Sell Price = Period_Price_Sell + (MultiplierPMD × Network_Access_Tariff)
{
"buy_type": "FIXED",
"sell_type": "FIXED",
"voltage_level": "BTN simples",
"tariff_cycle": "TETRA_SEMANAL",
"with_holidays": true,
"contracted_power": 6.9,
"validity": "2026-01-01",
"user_id": "<anchor_user_id>",
"meter_id": "<anchor_cpe_id>",
"buy_payload": {
"buy_or_sell_type": "CONTRACT_BUY_VALUES",
"peak_value": 0,
"mid_peak_value": 0,
"off_peak_value": 0,
"super_off_peak_value": 0,
"multiplierPMD": 1,
"multiplierERSE": 1,
"contract_id": "<contract_uuid>"
},
"sell_payload": {
"buy_or_sell_type": "CONTRACT_SELL_VALUES",
"peak_value": 0,
"mid_peak_value": 0,
"off_peak_value": 0,
"super_off_peak_value": 0,
"multiplierPMD": 1,
"multiplierERSE": 1,
"contract_id": "<contract_uuid>"
}
}
Repeat for Consumer 1 and Consumer 2 CPEs, substituting the respective user_id and meter_id.
Step 10 — Create the Anchor Resource¶
POST /core/api/communities/{community_id}/resources
The Anchor resource represents the house consumption. Use type IC. The meter_id is the
Anchor Internal Meter UUID from Step 6 — always the meter directly above the resource in
the structure tree.
ownerships_payload assigns ownership shares. Multiple members can own fractional percentages.
{
"name": "RESOURCE AAA",
"type": "IC",
"status": "ACTIVE",
"meter_id": "<anchor_internal_meter_id>",
"ownerships_payload": [
{
"user_id": "<anchor_user_id>",
"perc_ownership": 100
}
],
"ic_payload": {
"description": "Anchor house",
"sum_certified_power": 0,
"ic_voltage_level": "BTN simples"
}
}
Step 11 — Create the Promoter PV Resource¶
POST /core/api/communities/{community_id}/resources
The Promoter's PV resource uses type SCPU (Self-Consumption Production Unit). The meter_id
is the Promoter PV Internal Meter UUID from Step 7.
{
"name": "RESOURCE PV",
"type": "SCPU",
"status": "ACTIVE",
"meter_id": "<promoter_pv_meter_id>",
"ownerships_payload": [
{
"user_id": "<promoter_user_id>",
"perc_ownership": 100
}
],
"scpu_payload": {
"generation_capacity": 0
}
}
Step 12 — Create Consumer Resources (×2)¶
POST /core/api/communities/{community_id}/resources
Each consumer resource uses type IC. The meter_id is the respective Consumer CPE UUID
(the consumer CPE is directly above the resource in the tree — no internal meter is needed).
{
"name": "RESOURCE AAA",
"type": "IC",
"status": "ACTIVE",
"meter_id": "<consumer1_cpe_id>",
"ownerships_payload": [
{
"user_id": "<consumer1_user_id>",
"perc_ownership": 100
}
],
"ic_payload": {
"description": "Consumer house",
"sum_certified_power": 0,
"ic_voltage_level": "BTN simples"
}
}
Repeat for Consumer 2, substituting consumer2_cpe_id and consumer2_user_id.
Step 13 — Upload DSO Measurements for each CPE¶
POST /core/api/communities/{community_id}/dso
Upload one record per 15-minute interval per CPE. The meter_id here refers to CPEs only,
not internal meters. Repeat for all three CPEs.
| Field | DSO Code | Description |
|---|---|---|
energy_surplus |
413 | Surplus energy allocated to this meter (kWh) |
imputed_energy |
415 | Share of total injected energy allocated to this meter (kWh) |
grid_sc |
418 | Self-consumed energy from the public grid (kWh) |
consumption |
423 | Energy consumed from the public grid (kWh) |
grid_injection |
424 | Energy injected into the public grid (kWh) |
{
"datetime_timestamp": "2026-03-19T16:47:41.201Z",
"energy_surplus": 0,
"imputed_energy": 0,
"grid_sc": 0,
"grid_injection": 0,
"consumption": 0,
"meter_id": "<cpe_uuid>"
}
Aggregator CPEs
Aggregator-type CPEs are not covered in this scenario. Contact INESC TEC if your integration requires them.
Step 14 — Upload Internal Meter Measurements¶
POST /core/api/communities/{community_id}/loads
Upload 15-minute measurements for each Internal Meter (Anchor Internal Meter and Promoter PV Internal Meter). These are measurements not observed by the DSO, installed behind the CPE.
{
"datetime_timestamp": "2026-03-19T16:47:41.201Z",
"generation": 0,
"consumption": 0,
"meter_id": "<internal_meter_uuid>"
}
Repeat for both internal meters.
Step 15 — Upload Bilateral Prices¶
POST /core/api/communities/{community_id}/bilateral-prices
Upload the price for each provider → receiver pair for every 15-minute interval. In this scenario the Promoter sells at different prices depending on the buyer:
- Promoter → Anchor: 70 €/MWh (behind the same CPE —
INTRA_CPEtransaction) - Promoter → Consumer 1: 80 €/MWh
- Promoter → Consumer 2: 80 €/MWh
Prices may change dynamically per interval in other scenarios.
All possible pairs
If you cannot guarantee that every member strictly produces or strictly consumes in every interval, you may need to provide prices for all possible provider–receiver combinations.
[
{
"datetime_timestamp": "2026-04-10T09:03:50.986Z",
"receiver_user_id": "<anchor_user_id>",
"provider_user_id": "<promoter_user_id>",
"price": 70
},
{
"datetime_timestamp": "2026-04-10T09:03:50.986Z",
"receiver_user_id": "<consumer1_user_id>",
"provider_user_id": "<promoter_user_id>",
"price": 80
},
{
"datetime_timestamp": "2026-04-10T09:03:50.986Z",
"receiver_user_id": "<consumer2_user_id>",
"provider_user_id": "<promoter_user_id>",
"price": 80
}
]
Step 16 — Run Operations and Check Status¶
POST /core/api/communities/{community_id}/operations/run
GET /core/api/communities/{community_id}/tasks/{task_id}
Each operation call returns a task_id you can poll to check its status.
Phase 1 — Market Clearing¶
clear_market generates transactions and, for DYNAMIC communities, the bilateral energy
allocation coefficients (dynamic ACs) to be submitted to the DSO.
Phase 2 — Settlement¶
Once market clearing is complete:
run_settlement generates billing information and financial settlement results.
Dynamic coefficient flow (DYNAMIC communities)
After clear_market, the integrator fetches the dynamic ACs (Step 17) and submits them to
the DSO for validation. The DSO either approves (returns final dynamic allocation) or rejects
(falls back to proportional allocation). Final settlement must be run with the DSO-approved
allocation.
Step 17 — Get Bilateral Energy Allocations¶
GET /core/api/communities/{community_id}/bilateral_energy_allocations/data
Returns the dynamic allocation coefficients generated by clear_market, to be submitted to the
DSO. Only pairs where the coefficient is non-zero are returned, in 15-minute intervals.
Query parameters: start_date (YYYY-MM-DD), end_date (YYYY-MM-DD)
[
{
"datetime_timestamp": "2026-04-23T09:54:51.770Z",
"receiver_identifier": "PT002...",
"provider_identifier": "PT002...",
"coefficient_value": 0
}
]
An optional /export endpoint is available to download a DSO-compliant ZIP file with CSVs.
Step 18 — Get Transactions¶
GET /core/api/communities/{community_id}/sessions/transactions
Returns all transactions in the date range. Transactions are made between Member-Resource pairs.
If a transaction is behind-the-meter (INTRA_CPE), provider_meter_id and receiver_meter_id
will be the same.
Query parameters: start_date (YYYY-MM-DD), end_date (YYYY-MM-DD)
Step 19 — Get Settlement Outputs¶
POST /core/api/communities/{community_id}/sessions/settlement/outputs/query
A POST is used here because the query accepts a JSON body for specifying outputs, fields, and filters. You can filter by date range, member, resource, or meter, and select which output categories to return.
{
"start_date": "2026-03-01",
"end_date": "2026-03-31",
"outputs": ["cpes", "cpes_bilateral", "members", "rec"],
"fields": {
"cpes": ["e_lem", "e_pur", "e_alc", "rev_total"],
"cpes_bilateral": "ALL",
"members": ["e_sup", "e_pur", "rev_total", "rev_total_no_csc"],
"rec": ["e_inj", "e_con", "rev_sur"]
},
"meters": "ALL",
"resources": "ALL",
"members": ["<member_uuid>"]
}
See the Settlement Guide for a full description of all available output fields.