API reference
Reporting & settlement
aFRR dispatch events and performance timeline for an asset, wholesale schedule dispatch events, settlement over a UTC range and the quality gate detail behind it.
GET/v1/assets/{asset_id}/reports/afrr/dispatches
List aFRR dispatch events for an asset
report.read
Required scopes: report.read
Return aFRR dispatch events for this asset within the requested time window.
Each event represents a single dispatch instruction sent to the asset during a TSO pool activation. Use outcome and filter_reason to identify issues:
outcomeisNonewhen the dispatch was delivered successfully.filter_reasonis set when the asset was excluded from dispatch.
Defaults to the last 24 hours; maximum window is 90 days.
Path parameters
- asset_idREQUIRED
- stringThe ID of the asset
Query parameters
- start_time
- string<date-time>Start time for filtering results
- end_time
- string<date-time>End time for filtering results
- limit
- integerdefault 100
- offset
- integerdefault 0
curl "https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/dispatches" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/dispatches",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/dispatches", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"dispatches": [
{
"event_id": "<string>",
"activation_id": "<string>",
"request_id": "<string>",
"asset_id": "<string>",
"created_at_utc": "2026-10-22T20:30:00Z",
"planned_set_power": 0,
"set_power": 0,
"accepted": 0,
"outcome": "<string>",
"filter_reason": "<string>",
"filter_details": "<string>",
"dispatch_category": "<string>",
"dispatch_slot_utc": "2026-10-22T20:30:00Z",
"energy_price": 0,
"capacity_price": 0
}
],
"total": 0,
"limit": 0,
"offset": 0
}- 401no valid token
- 403scope missing
- 404unknown or not visible
- 422validation failed
- 429rate limited
GET/v1/assets/{asset_id}/reports/afrr/performance
aFRR performance timeline for an asset
report.read
Required scopes: report.read
Return aggregated aFRR dispatch performance metrics for this asset.
Buckets dispatch events by granularity (fifteen_minutes | hourly | daily). fill_rate_pct = accepted / set_power × 100 and is the primary health indicator. A high filtered_count relative to dispatch_count indicates the asset is regularly skipped.
Defaults to the last 24 hours; maximum window is 90 days.
Path parameters
- asset_idREQUIRED
- stringThe ID of the asset
Query parameters
- start_time
- string<date-time>Start time for filtering results
- end_time
- string<date-time>End time for filtering results
- granularity
- enum
fifteen_minuteshourlydaily
curl "https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/performance" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/performance",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/assets/DE_BESS_01/reports/afrr/performance", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"asset_id": "<string>",
"granularity": "fifteen_minutes",
"periods": [
{
"period_start": "2026-10-22T20:30:00Z",
"granularity": "fifteen_minutes",
"dispatch_count": 0,
"dispatched_count": 0,
"filtered_count": 0,
"total_set_power": 0,
"total_accepted": 0,
"fill_rate_pct": 0
}
]
}- 401no valid token
- 403scope missing
- 404unknown or not visible
- 422validation failed
- 429rate limited
GET/v1/assets/{asset_id}/reports/schedule/dispatches
List wholesale schedule dispatch events for an asset
report.read
Required scopes: report.read
Return wholesale schedule dispatch events for asset_id in [start_time, end_time).
Both bounds must be aligned to 15-minute UTC boundaries. The window must be at most 1 hour wide; longer ranges should be fetched as multiple requests.
Each event reports the set_power_mw requested and the effective_set_power_mw actually dispatched, plus a derived status:
full— the executed magnitude was not short of the requested setpoint; normally it equals it.clipped— the executed magnitude was smaller than the one requested. This marks any shortfall in magnitude, whatever the cause.rejected— not dispatched because the asset was unavailable or an immediate dispatch was overriding the wholesale schedule.failed— not dispatched because of a processing error.unknown— forward-compatibility fallback for any new status this client version doesn't recognise; treat as opaque.
message contains a free-form rejection reason or error diagnostic. It is usually absent on successful dispatches, including clipped ones; a reason for a shortfall is not guaranteed. outcome is the dispatch result ("success", "rejected", "error", ...).
set_time_utc is the customer-supplied UTC moment the setpoint was supposed to fire; created_at_utc is when the dispatch was processed. They typically coincide within milliseconds for executed schedules. set_time_utc may be null for historical rows emitted before the field was added.
Ingestion delay: events become queryable through this endpoint within roughly 5 minutes of the dispatch being processed.
Path parameters
- asset_idREQUIRED
- stringThe ID of the asset
Query parameters
- start_timeREQUIRED
- string<date-time>15-min aligned UTC start of the window (inclusive)
- end_timeREQUIRED
- string<date-time>15-min aligned UTC end of the window (exclusive)
curl "https://api.ebx.energy/v1/assets/DE_BESS_01/reports/schedule/dispatches?start_time=2026-05-18T10:00:00Z&end_time=2026-05-18T11:00:00Z" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/assets/DE_BESS_01/reports/schedule/dispatches?start_time=2026-05-18T10:00:00Z&end_time=2026-05-18T11:00:00Z",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/assets/DE_BESS_01/reports/schedule/dispatches?start_time=2026-05-18T10:00:00Z&end_time=2026-05-18T11:00:00Z", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"dispatches": [
{
"event_id": "<string>",
"request_id": "<string>",
"source_id": "<string>",
"asset_id": "<string>",
"created_at_utc": "2026-10-22T20:30:00Z",
"set_time_utc": "2026-10-22T20:30:00Z",
"status": "full",
"set_power_mw": 0,
"effective_set_power_mw": 0,
"outcome": "<string>",
"message": "<string>"
}
]
}- 401no valid token
- 403scope missing
- 404unknown or not visible
- 422validation failed
- 429rate limited
GET/v1/balancing-groups/afrr/schedules
Get day-after aFRR balancing-group schedules for a Berlin delivery day
report.read
Required scopes: report.read
Return the day-after aFRR balancing-group schedule volumes for one Berlin delivery day.
EBX nominates 15-minute values derived from assigned assets' afrr_power_actual telemetry. Both customer and EBX nominate these same values per TSO zone. TSO reconciliation is separate and never scales these customer values.
The response carries one entry per TSO zone with owned or managed assets. For owner-only views, aggregate_scope is asset_only: headers and zone periods are absent, but your own asset nomination series remain available. Otherwise:
- zone
periods— authoritative: exactly the values EBX nominates, split by the volume sign convention intovolume_pos_mw(positive aFRR, asset discharge; Verkauf series EBX BK → customer BK) andvolume_neg_mw(negative aFRR, asset charge; Kauf series customer BK → EBX BK) magnitudes; assets[]— informational per-asset disaggregation for imbalance tracking; nominations happen only at zone level. Newly generated publications use 0.001 MW resolution for both assets and zone totals. Each directional zone total is rounded half-up; whole-kW rounding residuals are allocated by largest fractional remainder, with asset ID breaking ties. The complete set of assets managed in that balancing group sums exactly to its published zone total.asset_idsnarrows only this list (and which zones appear) — zoneperiodsalways cover all your assets in the zone and match the nomination file regardless of any filter;nomination_pos/nomination_neg— the header metadata of the two nomination-file series.
delivery_day is a Europe/Berlin calendar day; expected_period_count is 96 (92 on the spring-forward day, 100 on the fall-back day) and period instants are ISO-8601 UTC. Requesting today or a future day (Berlin) returns 400 — day-after data cannot exist yet.
Periods with no published data are omitted (periods: [] means nothing published, "0" means EBX nominated 0 MW). Only successfully exchanged revisions are visible; regeneration alone does not publish. Previously exchanged revisions retain their original precision until a new revision is generated and successfully exchanged. Do not round or net the positive and negative directions together. Filtered or owner-only asset views are not the complete balancing-group total.
When to fetch: Start fetching the previous day's schedules at 08:00 Europe/Berlin time, our target publication time. If schedules are not yet available, retry every five minutes. Contact EBX if availability is delayed past 08:30. These times follow German local time (CET in winter, CEST in summer). The publication time is a target, not a guaranteed deadline.
Query parameters
- delivery_dayREQUIRED
- string<date>The Europe/Berlin delivery day; must be a completed day (before today, Berlin time)
- organization_id
- stringOrganization to view; must be an organization you are authorized to access. Required for multi-organization callers
- tso
- enum
50HZTNNTAMPTNBWOptional TSO zone filter; omit for all zones with in-scope assets - asset_ids
- stringOwned or nomination-managed asset ids; omit for all eligible assets. Filters asset presentation and zones, never the caller's BG aggregate
curl "https://api.ebx.energy/v1/balancing-groups/afrr/schedules?delivery_day=2026-07-29" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/balancing-groups/afrr/schedules?delivery_day=2026-07-29",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/balancing-groups/afrr/schedules?delivery_day=2026-07-29", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"delivery_day": "2026-07-29",
"day_start": "2026-10-22T20:30:00Z",
"day_end": "2026-10-22T20:30:00Z",
"expected_period_count": 96,
"zones": [
{
"tso": "50HZ",
"aggregate_scope": "balancing_group",
"control_area_eic": "10YDE-VE-------2",
"nomination_pos": {
"data_exchange_reference": "EBX-Entrix_aFRR_50Hertz_Verkauf_MW",
"source_control_area_eic": "10YDE-VE-------2",
"target_control_area_eic": "10YDE-VE-------2",
"source_balancing_group_eic": "11Y0-0000-3610-H",
"target_balancing_group_eic": "11X0-0000-0685-6",
"unit": "MW"
},
"nomination_neg": {
"data_exchange_reference": "EBX-Entrix_aFRR_50Hertz_Verkauf_MW",
"source_control_area_eic": "10YDE-VE-------2",
"target_control_area_eic": "10YDE-VE-------2",
"source_balancing_group_eic": "11Y0-0000-3610-H",
"target_balancing_group_eic": "11X0-0000-0685-6",
"unit": "MW"
},
"periods": [
{
"period_start": "2026-10-22T20:30:00Z",
"volume_pos_mw": "1.250",
"volume_neg_mw": "0.000"
}
],
"assets": [
{
"asset_id": "DE_50HZ_WEM_PAS_1",
"balancing_group_responsible_org_id": "<string>",
"periods": [
{
"period_start": "2026-10-22T20:30:00Z",
"volume_pos_mw": "1.250",
"volume_neg_mw": "0.000"
}
]
}
]
}
]
}GET/v1/balancing-groups/afrr/schedules/file
Download EBX's aFRR balancing-group nomination file (CSV)
report.read
Required scopes: report.read
Download the nomination file EBX exchanges for one (zone, direction) series.
The file reproduces exactly what EBX nominates against your balancing group for the requested Berlin delivery day — use it to submit or verify the identical values on your side (any mismatch raises an ANO):
| Row | Content |
|---|---|
| 1–5 | Datenaustauschreferenz, Regelzone von/an, Bilanzkreis von/an |
| 6 | Einheit;MW |
| 7+ | one row per quarter-hour: Berlin-local DD.MM.YYYY HH:MM + MW value |
Format: semicolon-delimited, UTF-8 with BOM, decimal comma. On the fall-back DST day the local labels 02:00–02:45 appear twice (100 rows); the spring-forward day has 92 rows.
direction=pos is the Verkauf series (positive aFRR, asset discharge, EBX BK → customer BK), direction=neg the Kauf series (negative aFRR, asset charge, customer BK → EBX BK).
Requesting today or a future day (Berlin) returns 400 — day-after data cannot exist yet. A zone in which your organisation manages no nominations returns 404. Cells without published values stay empty — an empty cell means "no value available", never "0 MW".
Query parameters
- delivery_dayREQUIRED
- string<date>The Europe/Berlin delivery day; must be a completed day (before today, Berlin time)
- organization_id
- stringOrganization to view; must be an organization you are authorized to access. Required for multi-organization callers
- tsoREQUIRED
- enum
50HZTNNTAMPTNBWThe TSO zone the nomination file covers - directionREQUIRED
- enum
posnegSeries direction: 'pos' (positive aFRR / asset discharge, Verkauf series EBX BK -> customer BK) or 'neg' (negative aFRR / asset charge, Kauf series customer BK -> EBX BK)
curl "https://api.ebx.energy/v1/balancing-groups/afrr/schedules/file?delivery_day=2026-07-29&tso=50HZ&direction=pos" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/balancing-groups/afrr/schedules/file?delivery_day=2026-07-29&tso=50HZ&direction=pos",
headers={"Authorization": f"Bearer {token}"},
)
print(r.text)const res = await fetch("https://api.ebx.energy/v1/balancing-groups/afrr/schedules/file?delivery_day=2026-07-29&tso=50HZ&direction=pos", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.text();"<string>"GET/v1/settlements
Get settlement over a UTC range
invoice.read
Required scopes: invoice.read
Settlement per asset and 15-minute block: what was offered, taken, delivered and earned, and what non-delivery cost.
Every product (fcr, afrrc_pos/afrrc_neg, afrre_pos/afrre_neg, backup_fcr, backup_afrr_pos/backup_afrr_neg) has revenue, collateralization, penalty and net = revenue − collateralization − penalty. Every line multiplies out to its amount, rounded half-up to the cent; totals sum the block amounts. Revenue is paid on delivered volume: capacity hours is the part of the block the asset delivered. Collateralisation and penalty are costs, shown positive.
Blocks appear once there is anything to settle (a bid, an award, an activation or a cost). processed_at changes whenever a block is recomputed; omit status for the latest state of every block. Values are preliminary until a block is FINAL. The legal invoice is not issued through this API.
Query parameters
- startREQUIRED
- string<date-time>Range start (inclusive), UTC, 15-min aligned
- endREQUIRED
- string<date-time>Range end (exclusive), UTC, 15-min aligned; at most 31 days after start
- status
- enum
PRELIMINARYFINAL'preliminary' or 'final'; omit for the latest state of every block - asset_ids
- stringComma-separated asset ids; omit for every asset in your organisation
curl "https://api.ebx.energy/v1/settlements?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/settlements?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/settlements?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"start": "2026-10-22T20:30:00Z",
"end": "2026-10-22T20:30:00Z",
"currency": "EUR",
"totals": {
"net": "-215.34",
"fcr": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrrc_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrrc_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrre_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrre_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_fcr": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_afrr_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_afrr_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
}
},
"assets": [
{
"asset_id": "<string>",
"totals": {
"net": "-215.34",
"fcr": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrrc_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrrc_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrre_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"afrre_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_fcr": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_afrr_pos": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
},
"backup_afrr_neg": {
"revenue": "57.34",
"collateralization": "0.00",
"penalty": "0.00",
"net": "57.34"
}
},
"blocks": [
{
"block_start": "2026-10-22T20:30:00Z",
"block_end": "2026-10-22T20:30:00Z",
"status": "PRELIMINARY",
"processed_at": "2026-10-22T20:30:00Z",
"ltu_mw": "3.950",
"fcr": {
"revenue": {
"bid_mw": "1.000",
"accepted_mw": "1.000",
"delivered_mw": "1.000",
"hours": "0.125000",
"price_per_mw_h": "5.1075",
"amount": "0.64"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "-37.36"
},
"afrrc_pos": {
"revenue": {
"bid_mw": "1.000",
"accepted_mw": "1.000",
"delivered_mw": "1.000",
"hours": "0.125000",
"price_per_mw_h": "5.1075",
"amount": "0.64"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "-37.36"
},
"afrrc_neg": {
"revenue": {
"bid_mw": "1.000",
"accepted_mw": "1.000",
"delivered_mw": "1.000",
"hours": "0.125000",
"price_per_mw_h": "5.1075",
"amount": "0.64"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "-37.36"
},
"afrre_pos": {
"revenue": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72",
"market": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
},
"shadow": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
}
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "57.34"
},
"afrre_neg": {
"revenue": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72",
"market": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
},
"shadow": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
}
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "57.34"
},
"backup_fcr": {
"revenue": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "22.20"
},
"backup_afrr_pos": {
"revenue": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "22.20"
},
"backup_afrr_neg": {
"revenue": {
"bid_mw": "3.000",
"activated_mwh": "0.670000",
"delivered_mwh": "0.300000",
"price_per_mwh": "112.4000",
"amount": "33.72"
},
"collateralization": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"penalty": {
"mw": "0.740",
"hours": "0.125000",
"price_per_mw_h": "38.00",
"amount": "3.52"
},
"net": "22.20"
}
}
]
}
]
}GET/v1/settlements/quality
Quality-gate detail and breach episodes behind the settlement
invoice.read
Required scopes: invoice.read
Return per-block quality-gate detail and quality-break episodes over [start, end).
gated_energy_mwh (eligible − paid) is exactly the energy the EBX quality gate withheld from the figures served by /v1/settlements; the episodes list explains each withholding (breach kind, setpoint context, Degraded window, P10 baseline). Blocks with no data are omitted; an asset with no data returns empty blocks and episodes.
Omit status for the latest state of every block, each carrying its own status, with the episodes of each asset-day's latest publishing run: one request instead of a preliminary and a final one to merge.
Query parameters
- startREQUIRED
- string<date-time>Range start (inclusive), UTC, 15-min aligned
- endREQUIRED
- string<date-time>Range end (exclusive), UTC, 15-min aligned; at most 31 days after start
- status
- enum
PRELIMINARYFINAL'preliminary' or 'final'; omit for the latest state of every block - asset_ids
- stringComma-separated asset ids; omit for every asset in your organisation
curl "https://api.ebx.energy/v1/settlements/quality?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/settlements/quality?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/settlements/quality?start=2026-10-01T00:00:00Z&end=2026-10-02T00:00:00Z", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"start": "2026-10-22T20:30:00Z",
"end": "2026-10-22T20:30:00Z",
"assets": [
{
"asset_id": "DE_AMP_TEST_EBX_2",
"afrre_pos": {
"degraded_seconds": 1200,
"baseline_seconds": 3600,
"breach_seconds": 22,
"stale_seconds": 0,
"substitute_seconds": 42,
"eligible_energy_total_mwh": "22.239000",
"paid_energy_total_mwh": "21.874000",
"gated_energy_total_mwh": "0.365000"
},
"afrre_neg": {
"degraded_seconds": 1200,
"baseline_seconds": 3600,
"breach_seconds": 22,
"stale_seconds": 0,
"substitute_seconds": 42,
"eligible_energy_total_mwh": "22.239000",
"paid_energy_total_mwh": "21.874000",
"gated_energy_total_mwh": "0.365000"
},
"blocks": [
{
"block_start": "2026-10-22T20:30:00Z",
"block_end": "2026-10-22T20:30:00Z",
"status": "PRELIMINARY",
"processed_at": "2026-10-22T20:30:00Z",
"afrre_pos": {
"degraded_seconds": 120,
"baseline_seconds": 300,
"breach_seconds": 11,
"stale_seconds": 0,
"substitute_seconds": 3,
"eligible_energy_mwh": "0.250000",
"paid_energy_mwh": "0.245000",
"gated_energy_mwh": "0.005000"
},
"afrre_neg": {
"degraded_seconds": 120,
"baseline_seconds": 300,
"breach_seconds": 11,
"stale_seconds": 0,
"substitute_seconds": 3,
"eligible_energy_mwh": "0.250000",
"paid_energy_mwh": "0.245000",
"gated_energy_mwh": "0.005000"
}
}
],
"episodes": [
{
"direction": "pos",
"kind": "imm",
"start_context": "onset",
"episode_start": "2026-10-22T20:30:00Z",
"episode_end": "2026-10-22T20:30:00Z",
"breach_seconds": 11,
"max_dev_frac": "0.2",
"degraded_until": "2026-10-22T20:30:00Z",
"baseline_kw": "<string>",
"baseline_empty": false
}
]
}
]
}GET/v1/settlements/quality-trace
Per-second quality trace behind the settlement (chart input)
invoice.read
Required scopes: invoice.read
Return the second-resolution trace behind /v1/settlements/quality.
Setpoint against delivered power inside the acceptance channel, each assessed second classified (forgiven / sustained / immediate) and the DEGRADED and BASELINE windows marked — the seconds the block counters aggregate.
Bounded in both window (6 h) and asset count (8), so asset_ids is required here unlike on the block endpoints. Points are bucketed to keep the response bounded; resolution_seconds says how coarse, and the per-asset summary counters stay at one second regardless so the headline numbers never depend on the zoom level.
Query parameters
- startREQUIRED
- string<date-time>Window start (inclusive), UTC
- endREQUIRED
- string<date-time>Window end (exclusive), UTC
- statusREQUIRED
- enum
PRELIMINARYFINALSettlement state filter: 'preliminary' or 'final' (case-insensitive) - asset_idsREQUIRED
- stringComma-separated asset ids (required; at most 8)
curl "https://api.ebx.energy/v1/settlements/quality-trace?start=2026-07-22T01:30:00Z&end=2026-07-22T02:30:00Z&status=preliminary&asset_ids=DE_AMP_TEST_EBX_1,DE_AMP_TEST_EBX_2" \
-H "Authorization: Bearer $EBX_TOKEN"import httpx
r = httpx.get(
"https://api.ebx.energy/v1/settlements/quality-trace?start=2026-07-22T01:30:00Z&end=2026-07-22T02:30:00Z&status=preliminary&asset_ids=DE_AMP_TEST_EBX_1,DE_AMP_TEST_EBX_2",
headers={"Authorization": f"Bearer {token}"},
)
print(r.json())const res = await fetch("https://api.ebx.energy/v1/settlements/quality-trace?start=2026-07-22T01:30:00Z&end=2026-07-22T02:30:00Z&status=preliminary&asset_ids=DE_AMP_TEST_EBX_1,DE_AMP_TEST_EBX_2", {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();{
"start": "2026-10-22T20:30:00Z",
"end": "2026-10-22T20:30:00Z",
"resolution_seconds": 1,
"assets": [
{
"asset_id": "DE_AMP_TEST_EBX_2",
"summary": {
"assessed_seconds": 0,
"breach_immediate_seconds": 0,
"breach_sustained_seconds": 0,
"forgiven_seconds": 0,
"degraded_seconds": 0,
"baseline_seconds": 0,
"stale_seconds": 0
},
"points": [
{
"t": "2026-10-22T20:30:00Z",
"setpoint_kw": 0,
"actual_min_kw": 0,
"actual_max_kw": 0,
"channel_upper_kw": 0,
"channel_lower_kw": 0,
"max_dev_frac": 0,
"breach_sustained": false,
"breach_immediate": false,
"forgiven": false,
"degraded": false,
"baseline": false,
"stale": false,
"substitute": false,
"paid_mwh": 0,
"eligible_mwh": 0,
"revenue_eur": 0,
"penalty_eur": 0
}
]
}
]
}