Overview
The NOX Control Package provides access to:- Device information
- Production data.
- Forecasted production (day-ahead)
- Realtime forecasted production
- Actual production
- Typical production as if NOX would not have curtailed the device (per device and fleet-level).
- Changing user Settings
- Curtailing PV production or grid export by submitting a control schedule.
- Executing immediate flex control across a fleet of devices.
- Retrieving a log of executed flex controls.
Getting Started
Prerequisites
- Valid NOX API key (see Authentication)
Base URL
All endpoints use the base URL:- Sandbox:
https://api.sandbox.nox.energy - Production:
https://api.nox.energy
Core Workflows
All our collection api endpoints use a
next_token to paginate through results if the size limit of the response has been reached.
To paginate through a response, you can use the next_token received in the response as a query parameter and call the same endpoint with
the same parameters again. You can repeat this process until you have received the last page of the response, which is signified
by the next_token field becoming null.1. Getting Device Information
To fetch all devices configuration data you can call the following endpoint:cURL
user_id and/or device_id in the
redirect_uri callback parameters. Use the parameters received from the redirect and the
/devices/pv endpoint to fetch on a per user_id or per device_id basis.
This can be done using the query parameters like the below example:
cURL
device_id- Unique identifier per device. Each nox user_id can have multiple device_id’s.brand- Manufacturer brand of the inverter.capacity_kw- Installed PV capacity in kW.has_grid_export_curtailment/has_production_curtailment- Signifies which curtailment capabilities the device supports. Use this to know whether you should submitexport_curtailmentand/orproduction_curtailmentschedules for the device.current_production_kw/last_updated_at- The latest known production in kW and when it was measured. Only treatcurrent_production_kwas current iflast_updated_atis recent (e.g. less than 5 minutes in the past).current_curtailment_state- The curtailment state currently active on the device, e.g.default,production_curtailmentorexport_curtailment.response_latency_seconds- Expected delay in seconds before the device reacts to a steering command. Use this to know how far in advance to schedule a control action.
needs_reauthentication through our webhook. You can communicate to us which fields you are interested in and
we can set up a custom webhook with a POST endpoint you provide to us and you will receive real-time updates on change events.
We suggest you read Partner webhooks page for more info.
A lot of query parameters exist on the /devices/pv we recommend you to use them
if relevant, to reduces the size of data transfer.
2. Retrieving Production Data
2.1 Historical Production
Get actual measured production data of all devices of a certain timeframe:cURL
aggregated=true query parameter to
get the aggregated production across all devices.
If you are not interested in aggregated data but on a per device basis, you should use the query parameter device_id to get the production data on a per device basis.
Another option is to query without providing the device_id query parameter but loop over the same api call using the next_token query parameter
to paginate through the data of all devices. We would only recommend this option if you are interested in all devices data and if your timeframe you are querying is small (e.g. 15minutes)
as the amount of data can become quite large if you query a long timeframe and have many devices.
More info about the /devices/pv/production endpoint.
2.2 Forecasted Production
Get forecasted production data for all devices of a certain timeframe:cURL
device_id query parameter.
More info about the /devices/pv/production/forecast endpoint.
2.3 Realtime Forecasted Production
Get an aggregated, always up-to-date production forecast covering the past 15 minutes up to 24 hours ahead:cURL
2.4 Typical Production
Get baseline production, i.e. the production the device(s) would have generated if NOX had not applied any curtailment:2.4.1 Per-device typical production
cURL
2.4.2 Fleet-level typical production
If you are only interested in the aggregated typical production across your whole PV pool rather than a per-device breakdown, you can use the fleet-level endpoint instead. This requires ageneration_time in addition to the start_time/end_time, since only one forecast vintage is returned per call:
cURL
generation_time pins the call to one specific forecast run, only the forecast produced at that exact moment is returned. This makes results reproducible when you want to compare a specific vintage of the typical production forecast against what was actually delivered.
More info about the /fleet/pv/production/typical-production endpoint.
3. Managing User/Device Settings
Update user preferences and optimization settings on a per user/device basis. We recommend to directly go to the endpoint documentation of /devices/pv/settings to see all possible settings you can change. We recommend to at least implement the following settings options in your UI components of your website/app:- Optimization Settings, more specifically
pv_curtailment_mode. This can be set to:managed- NOX Energy manages the PV curtailment.external- We follow the curtailment schedule you provide through the schedules endpoint. This should only be enabled if you are a supplier that is using the partner control package.off- PV curtailment is disabled entirely.
- Location information for better forecasting and optimization results:
- Country
- Postal code
- Webhooks setup -> Real-time settings sync between all parties
4. Curtailing PV Production
This feature only exists if you are using the partner control package. If you are using the NOX control package, you can skip this section.
steerable_status from /devices/pv: steering_enabled and steerable must both be true. If steerable is false, general_reason explains why (e.g. reauthentication required, holiday mode active, still learning the device). Also check has_grid_export_curtailment / has_production_curtailment to know which control_type the device actually supports.
We provide two complementary ways to steer a PV device:
- Schedules: plan curtailment windows ahead of time, per device.
- Flex: immediately curtail (or release) production across a fleet of devices by a target kW or percentage, without pre-planning exact windows.
4.1 Submitting a curtailment schedule
Submit a curtailment schedule withPOST /devices/pv/schedules by providing, per device, a list of start_time/end_time windows and a control_type. Unlike the heat pump’s fixed 96-slot schedule, PV schedules use arbitrary start/end timestamps at 1-minute granularity, so you only need to submit entries for the windows you actually want to curtail.
cURL
device_id– the device to schedule. You can batch up to 250 device_ids in a single request, each with up to 25 schedule entries.schedules[].start_time/schedules[].end_time– the curtailment window in UTC.start_timemust be beforeend_time, andend_timemust be in the future. Ifend_timeis omitted, only a start command is scheduled and it will not automatically revert.schedules[].control_type– one of:export_curtailment– keep grid export at 0 kW during the scheduled window by curtailing production if needed.production_curtailment– keep PV production at 0 kW during the scheduled window.default– do not curtail; let production/export follow normal household consumption and generation. Onceend_timefor adefaultentry is reached, the device stays indefaultuntil another schedule overwrites it.
response_latency_seconds on /devices/pv).
Only send schedules for devices that have external steering optimization enabled (pv_curtailment_mode set to external) and are compatible. We filter out any others regardless, but this avoids unnecessary rejections.
On success (all accepted):
rejected array. Each entry includes a reason and reason_code explaining why that specific device_id’s schedule was not accepted (e.g. an invalid time range, or the device currently not being steerable):
4.2 Executing fleet flex control
UsePOST /devices/pv/flex when you want to curtail (or release) production across your whole fleet right now, instead of pre-planning per-device windows. You express the target as either an absolute target_kw to reduce the aggregated production by, or a target_percentage of max fleet capacity, optionally scoped to specific brands and optionally reverted automatically at an end_time.
cURL
target_kw– target power in kW to reduce aggregated fleet production by. Mutually exclusive withtarget_percentage.target_percentage– target percentage (0-100) of max fleet capacity to reduce production to. Atarget_percentageof100releases curtailment and restores full production.end_time– optional, UTC ISO 8601. If provided, we automatically revert to the original (pre-flex) state at that time. If omitted, the curtailment stays active until you call this endpoint again. Provideend_timeat least 4 minutes in the future so devices have time to react.brand_filter– optional list of brands to scope the flex command to (e.g.["Sma", "Solis"]). If omitted, the command applies across all brands.
4.3 Getting fleet flex control logs
Retrieve a history of the flex commands you have executed over a given time range, useful for auditing or reconciling with production data:cURL
control_type, target (target_percentage), any brand_filter applied, the executed_flex_device_count at that time, and the end_time if one was set, use this to confirm a flex command was actually picked up across the expected number of devices.
More info at /devices/pv/flex/logs.
Next Steps
- Set up Partner Webhooks for real-time data updates.