Denowatts

Denowatts API v3

Overview

The Denowatts API v3 is a read-only REST API for pulling device and site telemetry out of Denowatts: raw channel readings, curated rollups, and daily site summaries. It's intended for customers and integration partners who need to bring Denowatts data into their own systems (BI tools, historians, custom dashboards, billing pipelines, etc.).

By using this API, all Users, including Site Owners and Providers, agree to Denowatts' Terms of Use and Privacy Policy.

Base URL

https://data.denowatts.com/api/v3

All endpoint paths in this reference are relative to this base URL.

Authentication

Each Company is issued an API key, visible on any Site Channel Map it has access to. Send it as an HTTP header on every request:

x-api-key: YOUR_API_KEY

Header names are case-insensitive, but x-api-key is the canonical form.

Quickstart

curl "https://data.denowatts.com/api/v3/site-rollup?site=655c9473931af4bce4f457bc&start=2026-07-01T00:00:00Z&end=2026-07-02T00:00:00Z" \
  -H "x-api-key: YOUR_API_KEY"

Conventions

Timestamps. All timestamps in requests and responses are UTC, in ISO 8601 format (for example 2026-07-01T14:00:00Z). The start and end bounds are both inclusive.

Time buckets. Each endpoint labels its records differently:

  • channel-raw uses an ending timestamp: the record is labeled with the time the reading was taken.
  • channel-rollup and site-rollup use a beginning timestamp: a record labeled 14:00 covers 14:00–14:05.
  • site-daily-rollup buckets records by the site's local calendar day, not the UTC day. Each record carries a date field, and start/end filter against that date rather than against timestamp.

Identifiers. site is a 24-character hexadecimal ID. channel is a dotted device-channel address (see Finding Site and Channel IDs).

History window. Each endpoint limits how far into the past start may reach, measured back from the start of the current UTC day. This caps the age of the data you can request, not the width of a single request: a start older than the window is rejected with 400 Bad Request even when the start–end span is small. See History Windows.

Numeric values. All numeric fields are rounded to 4 decimal places.

Field names. Metric field names (nrgNetPmtr, irrPoaRef, tempBom, …) are shared across the platform. Definitions and units for each are listed on the portal's Metrics List.

Endpoint Overview

There are four endpoints, each covering a different level of curation and update latency:

EndpointDescriptionIntervalTimestamp conventionTypical latency
channel-rawRaw device-level readings, as reported by the deviceAs readEnding timestamp~1 minute
channel-rollupCurated device-level rollups5 minuteBeginning timestamp~20 minutes
site-rollupCurated, site-level aggregate rollups5 minuteBeginning timestamp~20 minutes
site-daily-rollupSite-rollup records aggregated by day1 daySite-local calendar dayNext day*

Query Parameters

These parameters are shared across all four endpoints unless the Applies to column says otherwise.

ParameterRequiredTypeApplies toDescription
siteYesstring (24-char hex ID)AllThe site to query, e.g. 655c9473931af4bce4f457bc. Sites are Denowatts' top-level project unit, each with its own name, energy model, and meters.
channelYesstringchannel-raw, channel-rollupA single device channel, formatted <deviceType>.<deviceMajor>.<deviceMinor>.<channelId>, e.g. 1.1.1.9032. See Device Types.
startYesISO 8601 UTC datetimeAllStart of the record range, inclusive.
endYesISO 8601 UTC datetimeAllEnd of the record range, inclusive.
metricsNocomma-separated stringAllRestrict the response to specific fields, e.g. metrics=irrPoaRef,tempBom. The timestamp field is always returned, whether or not you list it. Omit this parameter to return every stored field for that endpoint.
orderNoreverseAllSort order by timestamp. Omit for ascending (oldest first); pass order=reverse for descending (newest first).
pageNointegerAllPage number, 1-indexed. Defaults to 1.
limitNointegerAllRecords per page. Defaults to 1000 and is capped at 1000; any larger value is clamped down to 1000.

Finding Site and Channel IDs

site and channel values, along with the metrics each device reports, are listed on each site's Channel Map in the Denowatts Portal:

Site channel map showing per-device channel IDs and metrics

Endpoints

GET /channel-raw

Raw, per-channel device telemetry. Field names vary by device and channel type; a raw record only ever contains whatever that device reports (irradiance sensors, inverters, and weather stations all report different fields), so use metrics to pin down the fields you need.

Parameters

site, channel, start, end, metrics, order, page, limit. See Query Parameters.

Example request

curl "https://data.denowatts.com/api/v3/channel-raw?site=66b60e72e0b91615654f0731&channel=1.1.1.9032&metrics=irrPoaRef,irrHorRef,tempBom&start=2026-07-01T14:18:11.687Z&end=2026-07-01T15:18:11.687Z" \
  -H "x-api-key: YOUR_API_KEY"
const url = new URL("https://data.denowatts.com/api/v3/channel-raw");
url.search = new URLSearchParams({
  site: "66b60e72e0b91615654f0731",
  channel: "1.1.1.9032",
  metrics: "irrPoaRef,irrHorRef,tempBom",
  start: "2026-07-01T14:18:11.687Z",
  end: "2026-07-01T15:18:11.687Z",
});

const res = await fetch(url, { headers: { "x-api-key": "YOUR_API_KEY" } });
const data = await res.json();
import requests

response = requests.get(
    "https://data.denowatts.com/api/v3/channel-raw",
    params={
        "site": "66b60e72e0b91615654f0731",
        "channel": "1.1.1.9032",
        "metrics": "irrPoaRef,irrHorRef,tempBom",
        "start": "2026-07-01T14:18:11.687Z",
        "end": "2026-07-01T15:18:11.687Z",
    },
    headers={"x-api-key": "YOUR_API_KEY"},
)
data = response.json()

Example response

{
  "docs": [
    { "timestamp": "2026-07-01T14:19:00.000Z", "irrPoaRef": 612.4, "irrHorRef": 588.1, "tempBom": 31.2 },
    { "timestamp": "2026-07-01T14:24:00.000Z", "irrPoaRef": 618.9, "irrHorRef": 594.7, "tempBom": 31.6 }
  ],
  "totalDocs": 24,
  "limit": 1000,
  "totalPages": 1,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": false,
  "prevPage": null,
  "nextPage": null
}

GET /channel-rollup

Curated 5-minute device-level rollups: the cleaned-up counterpart to channel-raw, with a fixed field set rather than raw per-device fields.

Parameters

site, channel, start, end, metrics, order, page, limit. See Query Parameters.

Example request

curl "https://data.denowatts.com/api/v3/channel-rollup?site=66b60e72e0b91615654f0731&channel=1.1.1.9032&start=2026-07-01T00:00:00Z&end=2026-07-01T06:00:00Z" \
  -H "x-api-key: YOUR_API_KEY"
const url = new URL("https://data.denowatts.com/api/v3/channel-rollup");
url.search = new URLSearchParams({
  site: "66b60e72e0b91615654f0731",
  channel: "1.1.1.9032",
  start: "2026-07-01T00:00:00Z",
  end: "2026-07-01T06:00:00Z",
});

const res = await fetch(url, { headers: { "x-api-key": "YOUR_API_KEY" } });
const data = await res.json();
import requests

response = requests.get(
    "https://data.denowatts.com/api/v3/channel-rollup",
    params={
        "site": "66b60e72e0b91615654f0731",
        "channel": "1.1.1.9032",
        "start": "2026-07-01T00:00:00Z",
        "end": "2026-07-01T06:00:00Z",
    },
    headers={"x-api-key": "YOUR_API_KEY"},
)
data = response.json()

Example response

{
  "docs": [
    {
      "timestamp": "2026-07-01T00:00:00.000Z",
      "dbRssi": -62,
      "insDeno": 0,
      "irrDeno1": 0,
      "irrDeno2": 0,
      "irrDeno3": 0,
      "nrgCompared": 0,
      "nrgDenoExpected": 0,
      "statAcrylic": 0,
      "statTeflon": 0,
      "statWeighting1": 1,
      "statWeighting2": 0,
      "tempBom": 18.4,
      "tempCellDeno": 18.1,
      "vDenoBat": 3.31,
      "vDenoCap": 5.02
    }
  ],
  "totalDocs": 72,
  "limit": 1000,
  "totalPages": 1,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": false,
  "prevPage": null,
  "nextPage": null
}

GET /site-rollup

Curated 5-minute rollups aggregated across an entire site (all channels combined), rather than a single device channel.

Parameters

site, start, end, metrics, order, page, limit. See Query Parameters. This endpoint takes no channel; it is site-wide by design.

Example request

curl "https://data.denowatts.com/api/v3/site-rollup?site=655c9473931af4bce4f457bc&start=2026-07-01T00:00:00Z&end=2026-07-01T06:00:00Z" \
  -H "x-api-key: YOUR_API_KEY"
const url = new URL("https://data.denowatts.com/api/v3/site-rollup");
url.search = new URLSearchParams({
  site: "655c9473931af4bce4f457bc",
  start: "2026-07-01T00:00:00Z",
  end: "2026-07-01T06:00:00Z",
});

const res = await fetch(url, { headers: { "x-api-key": "YOUR_API_KEY" } });
const data = await res.json();
import requests

response = requests.get(
    "https://data.denowatts.com/api/v3/site-rollup",
    params={
        "site": "655c9473931af4bce4f457bc",
        "start": "2026-07-01T00:00:00Z",
        "end": "2026-07-01T06:00:00Z",
    },
    headers={"x-api-key": "YOUR_API_KEY"},
)
data = response.json()

Example response

{
  "docs": [
    {
      "timestamp": "2026-07-01T00:00:00.000Z",
      "nrgNetInv": 0,
      "nrgNetPmtr": 0,
      "pwrAcActiveInv": 0,
      "pwrAcActivePmtr": 0,
      "pwrExpected": 0,
      "tempBom": 18.4
    }
  ],
  "totalDocs": 72,
  "limit": 1000,
  "totalPages": 1,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": false,
  "prevPage": null,
  "nextPage": null
}

GET /site-daily-rollup

Site-rollup data aggregated by calendar day, one record per site per day, including loss attribution once it's been confirmed (see the note under Endpoint Overview).

Days are the site's local calendar day, not UTC days. Records carry a date field, and start/end filter against that date rather than against timestamp.

Parameters

site, start, end, metrics, order, page, limit. See Query Parameters. This endpoint takes no channel.

Example request

curl "https://data.denowatts.com/api/v3/site-daily-rollup?site=655c9473931af4bce4f457bc&start=2026-06-01T00:00:00Z&end=2026-07-01T00:00:00Z" \
  -H "x-api-key: YOUR_API_KEY"
const url = new URL("https://data.denowatts.com/api/v3/site-daily-rollup");
url.search = new URLSearchParams({
  site: "655c9473931af4bce4f457bc",
  start: "2026-06-01T00:00:00Z",
  end: "2026-07-01T00:00:00Z",
});

const res = await fetch(url, { headers: { "x-api-key": "YOUR_API_KEY" } });
const data = await res.json();
import requests

response = requests.get(
    "https://data.denowatts.com/api/v3/site-daily-rollup",
    params={
        "site": "655c9473931af4bce4f457bc",
        "start": "2026-06-01T00:00:00Z",
        "end": "2026-07-01T00:00:00Z",
    },
    headers={"x-api-key": "YOUR_API_KEY"},
)
data = response.json()

Example response

{
  "docs": [
    {
      "date": "2026-06-30T00:00:00.000Z",
      "nrgAcActivePmtr": 4123.7,
      "nrgNetPmtr": 4108.2,
      "nrgExpected": 4300.5,
      "nrgExpectedCloud": 4290.1,
      "nrgCommissioned": 4450,
      "nrgCommissionedAged": 4402.3,
      "nrgLearned": 4310.9,
      "nrgLssOutage": 12.4,
      "nrgLssShade": 3.1,
      "nrgLssSnow": 0,
      "nrgLssSystemic": 8.9,
      "nrgProducedPred": 4300.5,
      "insHorRef": 6.21,
      "insPoaRef": 6.55,
      "dptPrecip24h": 0,
      "dptSnow24h": 0,
      "tempAmb": 21.3,
      "tempBom": 24.8,
      "tempCell": 25.1,
      "tempCellBom": 24.9,
      "tempCellDeno": 24.6
    }
  ],
  "totalDocs": 30,
  "limit": 1000,
  "totalPages": 1,
  "page": 1,
  "pagingCounter": 1,
  "hasPrevPage": false,
  "hasNextPage": false,
  "prevPage": null,
  "nextPage": null
}

Response Format

All four endpoints return the same paginated envelope:

FieldTypeDescription
docsarrayThe matching records for this page.
totalDocsintegerTotal number of records matching the query, across all pages.
limitintegerRecords per page for this response.
totalPagesintegerTotal number of pages available.
pageintegerThe current page number.
pagingCounterintegerThe index of the first record on this page.
hasPrevPagebooleanWhether a previous page exists.
hasNextPagebooleanWhether a next page exists.
prevPageinteger | nullThe previous page number, or null if none.
nextPageinteger | nullThe next page number, or null if none.

Step through a large result set with page, or shrink it with narrower start/end windows and a smaller metrics selection.

Rate Limits

History Windows

Each endpoint limits how far into the past start may reach, measured back from the start of the current UTC day:

EndpointOldest start allowed
channel-raw30 days ago
channel-rollup90 days ago
site-rollup365 days ago
site-daily-rollupNo limit

This is a limit on the age of the data, not on the size of a single request. Splitting an old range into smaller windows will not get around it: a start outside the window is rejected however narrow the request is. For history older than a window, use a coarser endpoint (site-daily-rollup has no limit), and use page to walk through large result sets.

Errors

CodeMeaning
200 OKSuccessful request.
400 Bad RequestThe request was malformed: a required parameter is missing, a parameter has the wrong shape (e.g. site isn't a valid ID, start/end isn't a valid date), or start is older than that endpoint's history window.
403 ForbiddenThe API key is missing or invalid, your IP isn't whitelisted, or your Company doesn't have access to the requested site.
429 Too Many RequestsYou've exceeded the rate limit for this API key + site pair.
5xx Server ErrorAn error occurred on the Denowatts side. If this persists, contact support.

All error responses share the same shape. message is a string for most errors, but parameter-validation failures return an array of strings, one per invalid parameter:

{
  "statusCode": 403,
  "timestamp": "2026-07-23T14:18:11.687Z",
  "path": "/api/v3/site-rollup?site=655c9473931af4bce4f457bc&start=2026-07-01T00:00:00Z&end=2026-07-02T00:00:00Z",
  "message": "IP not whitelisted"
}

Support

For access requests, IP whitelisting, or any other questions, contact support@denowatts.com.

Last updated on

© 2026 Denowatts