# Dispatch

> Telling an asset what to do: immediate dispatch and its history, scheduled dispatch and the anticipated dispatch forecast. Immediate dispatch is an unrestricted override, so read its description before using it.

API reference

Telling an asset what to do: immediate dispatch and its history, scheduled dispatch and the anticipated dispatch forecast. Immediate dispatch is an unrestricted override, so read its description before using it.

6 endpoints

· GET · /v1/assets/{asset\_id}/dispatch/immediate

### Get immediate dispatch history

dispatch.read

Get a history of immediate dispatch issued for an asset.

Time filtering is overlap-based and uses half-open window semantics. With both `start_time` and `end_time`, the endpoint returns dispatch intervals that overlap `[start_time, end_time)`.

Boundary behavior:

-   a dispatch ending exactly at `start_time` is excluded
-   a dispatch starting exactly at `end_time` is excluded

`set_power_mw` is the dispatch set point in MW. Positive values correspond to injection into the grid, negative values to absorption from the grid.

History is limited to the last 30 days.

Path parameters

asset\_id · REQUIRED

string

Query parameters

sort\_by

enum · `start_time` · `end_time` · Field to sort the results by

sort\_order

enum · `asc` · `desc` · Order to sort the results by, either 'asc' or 'desc'

start\_time

string<date-time> · Return immediate dispatch intervals whose end\_time is strictly after this timestamp. With end\_time, the API matches intervals overlapping the half-open window \[start\_time, end\_time).

end\_time

string<date-time> · Return immediate dispatch intervals whose start\_time is strictly before this timestamp. With start\_time, the API matches intervals overlapping the half-open window \[start\_time, end\_time).

Example value

cURL:

```bash
curl ·   · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN"
```

Python:

```python
import ·  httpx

r = httpx.get(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" · , ·   · { · 
   · method · : ·   · "GET" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
   · }, · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "dispatches" · : ·   · [ · 
     · { · 
       · "start_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
       · "end_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
       · "set_power_mw" · : ·   · 0 · 
     · } · 
   · ] · 
 · }
```

Can raise

-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   422 · validation failed
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)

 · POST · /v1/assets/{asset\_id}/dispatch/immediate

### Set immediate dispatch power (unrestricted override)

dispatch.write

Override the dispatch of an asset for a bounded window, bypassing every _safety_ safeguard.

**Unrestricted emergency override — use with extreme care.**

This endpoint deliberately bypasses every platform safeguard: declared unavailabilities, power limits, and regulatory or market restrictions are neither checked nor enforced. The platform attempts to execute the dispatch regardless of the asset's declared state, schedule, or market obligations. Executing it can violate market regulations and cause system imbalances. The caller carries full responsibility for ensuring the requested set point is physically safe for the asset and permissible in the current situation. Use only when strictly necessary, e.g. on explicit TSO instruction or in an emergency.

Behavior:

-   The dispatch becomes active at `start_time` (defaults to now if omitted) and runs until `end_time` (required).
-   At `end_time`, the asset is automatically reset to its currently scheduled wholesale power. Internally, two events are published: an `enable` at `start_time` and an automatic `reset` at `end_time` that queries the current schedule and dispatches it.
-   While an immediate dispatch is active, conflicting wholesale schedule events for the same asset are rejected by the dispatcher.
-   Submitting a new request while an immediate dispatch is already active will override the existing one.

Constraints (request validation and one plausibility bound — none are safety checks):

-   `set_power_mw` must not exceed the asset's `usable_power_capacity` in magnitude (spec ID-04). This is a **static sanity bound**, not a safety check: it refuses a setpoint the asset could not physically produce under any circumstances — a typo of 500 instead of 50 — and consults nothing about the asset's live state, obligations or restrictions. Until now this endpoint had no magnitude bound at all. While the asset is in phase 1 of the validation rollout (`strict_validation` false) a breach is reported in `warnings` and the dispatch is still stored; in phase 2 it is rejected. The historical 2x-capacity bound is always rejected. An asset with no recorded capacity is not refused — the gap is logged instead, since declining an emergency override over a missing parameter would be worse than not bounding it.
-   `end_time` is required and must be in the future.
-   `start_time` is optional. If provided, it must not be more than 1 second in the past (this allowance covers round-trip latency only and prevents backdating).
-   The window `end_time - start_time` must be at least the configured minimum (`IMMEDIATE_DISPATCH_MIN_WINDOW_SECONDS`, default 10s). Requests with a shorter effective window are rejected with 400.

`set_power_mw` is the dispatch set point in MW. Positive values correspond to injection into the grid, negative values to absorption from the grid.

Path parameters

asset\_id · REQUIRED

string

Request body · required

start\_time

string<date-time> · Optional start time of the dispatch in UTC. Defaults to the server's current time when omitted, and must be within 1s of it — immediate dispatches always start now; there is no future scheduling.

end\_time · REQUIRED

string<date-time> · End time of the dispatch in UTC. Required.

set\_power\_mw · REQUIRED

number · Set point for the dispatch in MW. Positive corresponds to injection of energy into the grid, negative corresponds to absorption of energy from the grid.

Example value

cURL:

```bash
curl ·   · -X ·  POST  · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN" ·  \
   · -H ·   · "Content-Type: application/json" ·  \
   · -d ·   · '{"start_time":"2026-09-10T13:30:00Z","end_time":"2026-09-10T13:30:00Z","set_power_mw":55.1}'
```

Python:

```python
import ·  httpx

r = httpx.post(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
    json= · { · 
         · "start_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
         · "end_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
         · "set_power_mw" · : ·   · 55.1 · , · 
     · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate" · , ·   · { · 
   · method · : ·   · "POST" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
     · "Content-Type" · : ·   · "application/json" · , · 
   · }, · 
   · body · : ·  JSON.stringify( · { · "start_time" · : · "2026-09-10T13:30:00Z" · , · "end_time" · : · "2026-09-10T13:30:00Z" · , · "set_power_mw" · : · 55.1 · } · ) · , · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "start_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
   · "end_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
   · "set_power_mw" · : ·   · 0 · , · 
   · "warnings" · : ·   · [ · 
     · "<string>" · 
   · ] · 
 · }
```

Can raise

-   400 · malformed request
-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   409 · state conflict
-   422 · validation failed
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)· PUT · /v1/assets/{asset\_id}/dispatch/immediate/disable

### Disable immediate dispatch

dispatch.write

Disable the active immediate dispatch for a specific asset.

Sets the active dispatch's `end_time` to the current time; the dispatcher derives the reset from the operational-state snapshot and restores the scheduled wholesale power. Returns the now-closed dispatch record. Returns 404 if no dispatch was active.

Path parameters

asset\_id · REQUIRED

string

Example value

cURL:

```bash
curl ·   · -X ·  PUT  · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate/disable" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN"
```

Python:

```python
import ·  httpx

r = httpx.put(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate/disable" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/immediate/disable" · , ·   · { · 
   · method · : ·   · "PUT" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
   · }, · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "start_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
   · "end_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
   · "set_power_mw" · : ·   · 0 · 
 · }
```

Can raise

-   400 · malformed request
-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   409 · state conflict
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)

· GET · /v1/assets/{asset\_id}/dispatch/scheduled

### Get scheduled dispatch

dispatch.read

Get the current dispatch schedule for an asset.

The schedule is returned for the specified date and time range. If no start or end time is provided, the entire day is considered.

The returned schedule provides a continuous view of the asset's dispatch schedule. For each schedule event, the response includes the power in MW, delivery day, and start time of the delivery. The power is held same until the next schedule event within the same 15-minute block interval.

| Deliver Day | Delivery Block Start Time | Start Time | Power (MW) |
| --- | --- | --- | --- |
| 2025-01-01 | 00:00:00 | 00:00:00 | 0 |
| 2025-01-01 | 00:00:00 | 00:09:00 | 10 |
| 2025-01-01 | 00:30:00 | 00:30:00 | \-20 |
| 2025-01-01 | 00:30:00 | 00:32:00 | \-5 |
| 2025-01-01 | 00:45:00 | 00:45:00 | 0 |
| 2025-01-01 | 01:00:00 | 01:00:00 | 30 |

At 00:00, the power is 0 MW until 00:09, when it changes to 10 MW. At 00:15, the power is reset to 0 MW as we move to the next 15-minute block. At 00:30, the power changes to -20 MW and remains until 00:32, when it changes to -5 MW. At 00:45, the power is set to 0 MW and held until 01:00, when it changes to 30 MW. At 01:15, the power is reset to 0 MW as we move to the next 15-minute block.

Querying can be done exclusively on 15-minute block intervals (i.e. on 15 minute marks, e.g. between 00:00:00 and 18:45:00, but not between 00:10:00 and 18:32:00).

`set_power_mw` (deprecated alias of `bess_power_mw`) is the scheduled BESS power in MW for each delivery time slot. Until per-mode persistence lands, responses report `control_mode=bess_only` and `poc_power_mw=null` for all events.

Path parameters

asset\_id · REQUIRED

string

Query parameters

start\_time

string<date-time> · Start Time in ISO8601 format

end\_time

string<date-time> · End Time in ISO8601 format

Example value

cURL:

```bash
curl ·   · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN"
```

Python:

```python
import ·  httpx

r = httpx.get(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" · , ·   · { · 
   · method · : ·   · "GET" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
   · }, · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "schedules" · : ·   · [ · 
     · { · 
       · "control_mode" · : ·   · "passive" · , · 
       · "set_power_mw" · : ·   · 0 · , · 
       · "bess_power_mw" · : ·   · 0 · , · 
       · "poc_power_mw" · : ·   · 0 · , · 
       · "delivery_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
       · "set_time" · : ·   · "2026-09-10T13:30:00Z" · 
     · } · 
   · ], · 
   · "warnings" · : ·   · [ · 
     · "<string>" · 
   · ] · 
 · }
```

Can raise

-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   422 · validation failed
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)

· PUT · /v1/assets/{asset\_id}/dispatch/scheduled

### Update scheduled dispatch

dispatch.write

Update the scheduled dispatch for a specific asset.

The schedule is a list of targets: a BESS power in MW (`bess_power_mw`; the former `power_mw` is a deprecated alias) and the time from which it applies (`delivery_time`). The asset's power is steered towards the most recent target at the asset's default ramp rate. Targets can be submitted at up to per-second resolution (sub-second precision is truncated), e.g. to make the asset ramp slower than its default rate.

**Control modes (co-located PV+BESS sites):** each target carries a `control_mode` deciding which setpoints apply (sign convention: import/charging negative, export/discharging positive):

| `control_mode` | `bess_power_mw` | `poc_power_mw` |
| --- | --- | --- |
| `passive` | must be null/zero | must be null/zero |
| `bess_only` (default when omitted) | required | must be null/zero |
| `bess_and_poc` | required | required — PoC target has priority |
| `poc_only` | must be null/zero | required |

Requests violating this matrix are rejected with 422. `pv_power_mw` is reserved and must be null. `bess_and_poc` and `poc_only` require a co-located asset.

**Green co-location:** where grid import is not permitted, `poc_power_mw` must be >= 0 — the battery may only charge from the co-located producer. Because `bess_only` treats the battery's power as the power reaching the grid, a charging `bess_only` target is rejected on such an asset: at scheduling time there is no way to show the energy came from the producer rather than the grid. **To charge, use `bess_and_poc` with `poc_power_mw=0`**, which pins the point of connection and therefore guarantees producer-only charging.

In `bess_and_poc`, `bess_power_mw` may not exceed `poc_power_mw`: the co-located producer is a source and cannot absorb a surplus.

Targets may span multiple 15-minute delivery blocks. Every block that a target lands in is overridden in full with the submitted targets; blocks not covered by the request are left untouched. At the start of each block the target resets to 0 MW unless a target is placed exactly at the block start.

The entire request is rejected when:

1.  any target is beyond the end of the next UTC day,
2.  any target lands in a delivery block starting in less than 6 minutes (gate closure),
3.  two targets overlap, i.e. fall within the same second,
4.  any target's magnitude is implausibly large (`abs(power)` > 2× the asset's usable power capacity) — a loose sanity check, not an availability check.

**Note:** Targets within the sanity bound are always accepted, even when they exceed the currently available power. During unavailability or power limits they are not rejected — they are clamped to the power available for the duration of the event.

**Multi-product delivery:** targets are additionally capped to the power available for wholesale: per direction, the asset's available power (including any power limits) reduced by the reserved FCR capacity scaled by the regulatory buffer and by the reserved aFRR capacity.

The dispatch outcome of each target — executed in full, clipped, rejected, or failed — can be reviewed after the fact via `GET /assets/{asset_id}/reports/schedule/dispatches`.

Path parameters

asset\_id · REQUIRED

string

Request body · required

schedules · REQUIRED

array\[object\] · List of scheduled power events

Example value

cURL:

```bash
curl ·   · -X ·  PUT  · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN" ·  \
   · -H ·   · "Content-Type: application/json" ·  \
   · -d ·   · '{"schedules":[{"control_mode":"passive","power_mw":0,"bess_power_mw":0,"poc_power_mw":0,"pv_power_mw":0,"delivery_time":"2026-09-10T13:30:00Z"}]}'
```

Python:

```python
import ·  httpx

r = httpx.put(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
    json= · { · 
         · "schedules" · : ·   · [ · 
             · { · 
                 · "control_mode" · : ·   · "passive" · , · 
                 · "power_mw" · : ·   · 0 · , · 
                 · "bess_power_mw" · : ·   · 0 · , · 
                 · "poc_power_mw" · : ·   · 0 · , · 
                 · "pv_power_mw" · : ·   · 0 · , · 
                 · "delivery_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
             · }, · 
         · ], · 
     · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/dispatch/scheduled" · , ·   · { · 
   · method · : ·   · "PUT" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
     · "Content-Type" · : ·   · "application/json" · , · 
   · }, · 
   · body · : ·  JSON.stringify( · { · "schedules" · :[{ · "control_mode" · : · "passive" · , · "power_mw" · : · 0 · , · "bess_power_mw" · : · 0 · , · "poc_power_mw" · : · 0 · , · "pv_power_mw" · : · 0 · , · "delivery_time" · : · "2026-09-10T13:30:00Z" · }]} · ) · , · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "schedules" · : ·   · [ · 
     · { · 
       · "control_mode" · : ·   · "passive" · , · 
       · "set_power_mw" · : ·   · 0 · , · 
       · "bess_power_mw" · : ·   · 0 · , · 
       · "poc_power_mw" · : ·   · 0 · , · 
       · "delivery_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
       · "set_time" · : ·   · "2026-09-10T13:30:00Z" · 
     · } · 
   · ], · 
   · "warnings" · : ·   · [ · 
     · "<string>" · 
   · ] · 
 · }
```

Can raise

-   400 · malformed request
-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   409 · state conflict
-   422 · validation failed
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)

· GET · /v1/assets/{asset\_id}/forecasts/anticipated\_dispatch

### Get anticipated dispatch forecast N seconds ahead

dispatch.read

Return the step-interpolated scheduled dispatch power (MW) at a future instant.

Step-interpolation uses the most recent scheduled event with `set_time <= target`. If no such event exists within the delivery block, the value defaults to 0 MW.

Path parameters

asset\_id · REQUIRED

string

Query parameters

seconds\_into\_the\_future · REQUIRED

integer · Forecast horizon in seconds from now (max 1 day / 86\_400 s)

Example value

cURL:

```bash
curl ·   · "https://api.ebx.energy/v1/assets/DE_BESS_01/forecasts/anticipated_dispatch?seconds_into_the_future=900" ·  \
   · -H ·   · "Authorization: Bearer $EBX_TOKEN"
```

Python:

```python
import ·  httpx

r = httpx.get(
     · "https://api.ebx.energy/v1/assets/DE_BESS_01/forecasts/anticipated_dispatch?seconds_into_the_future=900" · , · 
    headers= · { · "Authorization" · : ·  f · "Bearer {token}" · }, · 
)
print(r.json())
```

TypeScript:

```typescript
const ·  res =  · await ·  fetch( · "https://api.ebx.energy/v1/assets/DE_BESS_01/forecasts/anticipated_dispatch?seconds_into_the_future=900" · , ·   · { · 
   · method · : ·   · "GET" · , · 
   · headers · : ·   · { · 
    Authorization · : ·   · `Bearer ${token}` · , · 
   · }, · 
 · } · );
 · const ·  data =  · await ·  res.json();
```

Example response · 200

```json
{ · 
   · "set_time" · : ·   · "2026-09-10T13:30:00Z" · , · 
   · "set_power_mw" · : ·   · 0 · 
 · }
```

Can raise

-   401 · no valid token
-   403 · scope missing
-   404 · unknown or not visible
-   422 · validation failed
-   429 · rate limited

[ALL CODES →](https://docs.ebx.energy/reference/errors.md)
