# Authentication Source: https://docs.minstroem.app/api-reference/authentication The Min Strøm Enterprise API uses **Bearer** authentication. ## Prerequisites 1. API key 2. API secret Click here to get in contact to obtain API key and secret. ## Generate Bearer token Create an `HMAC-SHA256` hash of the **API key** with **API secret** as key Concatenate your **API key** with the hashed value with a `:` ```text theme={null} API_KEY:HASHED_VALUE ``` Create a Base64 encoded string of the above concatenation Include this as **Bearer** token in the HTTP header: ```json theme={null} "Authorization": "Bearer " ``` # Endpoints Source: https://docs.minstroem.app/api-reference/endpoints ## Base URL The Min Strøm Enterprise API is accessed through the following base URL: ``` https://api.minstroem.app/thirdParty ``` *** # Prices ## Spot prices Get the future hourly electricity spot prices excl. charges. ```javascript theme={null} GET /prices/{region} ``` | | | | | | -------- | ------ | ------------ | ---------------------------------------------------------------- | | `region` | String | **Required** | See [Regions](/api-reference/shared#regions) for possible values | ```json theme={null} [ { "date": "2023-10-12T14:00:00Z", "price": 2.04095, "color": "yellow" }, { "date": "2023-10-12T15:00:00Z", "price": 3.6294125, "color": "yellow" } ] ``` | Parameter | Type | | Description | | --------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `date` | String | **Required** | ISO8601 timestamp of the price interval start | | `price` | Double | **Required** | The *total* electricity price for that hour, but only spot price if charges are unavailable. | | `color` | String | *Optional* | The suggested color to show along with the `price`. This is dynamic based on `region` and whether `charges` are available or not. Possible values are: `green`, `yellow`, `red`. | *** ## Full prices (incl. charges) There are two overall approaches to get electricity prices including all charges. 1. **Coordinate lookup** - Using lat/long to look up charges 2. **Address lookup** - Using a free text address query to look up charges One of the easiest ways to get prices including charges. ```javascript theme={null} GET /prices/location?latitude={latitude}&longitude={longitude} ``` | | | | | | ----------- | ------ | ------------ | ------------- | | `latitude` | Double | **Required** | The latitude | | `longitude` | Double | **Required** | The longitude | ```json theme={null} [ { "date": "2023-10-12T14:00:00Z", "price": 2.04095, "charges": 1.4335, "color": "yellow" }, { "date": "2023-10-12T15:00:00Z", "price": 3.6294125, "charges": 2.277875, "color": "yellow" } ] ``` | Parameter | Type | | Description | | --------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `date` | String | **Required** | ISO8601 timestamp of the price interval start | | `price` | Double | **Required** | The *total* electricity price for that hour, but only spot price if charges are unavailable. | | `charges` | Double | *Optional* | The total amount of charges. | | `color` | String | *Optional* | The suggested color to show along with the `price`. This is dynamic based on `region` and whether `charges` are available or not. Possible values are: `green`, `yellow`, `red`. | If you know the address of the user, this approach is the quickest way to get full electricity prices. This process consists of **2** steps: Search for the end-user's address so they can select the correct location. You can now request electricity prices incl. all current and applicable charges. If you already have the DAWA address ID, you can skip Step 1 and go directly to Step 2. ### Search address In order to get prices including charges you first need to get a valid address to make the lookup with. ```javascript theme={null} GET /prices/addresses/suggestions/{query} ``` | | | | | | ------- | ------ | ------------ | ----------------------------------------- | | `query` | String | **Required** | The free text address query to search for | ```json theme={null} [ { "id": "645db24a-f11a-3388-e044-0003ba298018", "suggestion": "Solbakkevej 11, 2630 Taastrup, 2. tv.", "streetName": "Solbakkevej", "streetNumber": "11", "floor": "2", "door": "tv", "zipCode": "2630", "city": "Taastrup", } ] ``` | Parameter | Type | | Description | | -------------- | ------ | ------------ | ---------------------------------------------------------------------- | | `id` | String | **Required** | The ID of the address to pass on to subsequent endpoints as parameter | | `suggestion` | String | **Required** | The full text string representation of the address to show to the user | | `streetName` | String | *Optional* | The street name | | `streetNumber` | String | *Optional* | The street number | | `floor` | String | *Optional* | The floor | | `door` | String | *Optional* | The door | | `zipCode` | String | *Optional* | The zip code | | `city` | String | *Optional* | The city | ### Get prices for address With a valid address you can now look up precise prices including charges: ```javascript theme={null} GET /prices/addresses/{addressId} ``` | | | | | | ----------- | ------ | ------------ | ------------------------------------------------------------- | | `addressId` | String | **Required** | The address ID returned from the address susgestion endpoint. | ```json theme={null} [ { "date": "2023-10-12T14:00:00Z", "price": 2.04095, "charges": 1.4335, "color": "yellow" }, { "date": "2023-10-12T15:00:00Z", "price": 3.6294125, "charges": 2.277875, "color": "yellow" } ] ``` | Parameter | Type | | Description | | --------- | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `date` | String | **Required** | ISO8601 timestamp of the price interval start | | `price` | Double | **Required** | The *total* electricity price for that hour, but only spot price if charges are unavailable. | | `charges` | Double | *Optional* | The total amount of charges. | | `color` | String | *Optional* | The suggested color to show along with the `price`. This is dynamic based on `region` and whether `charges` are available or not. Possible values are: `green`, `yellow`, `red`. | *** # Charges ## Hour specific Get full charges information for a specific location and date ```javascript theme={null} GET /prices/charges/location?latitude={latitude}&longitude={longitude}&date={date} ``` | | | | | | ----------- | ------ | ------------ | --------------------------------------- | | `latitude` | Double | **Required** | The latitude | | `longitude` | Double | **Required** | The longitude | | `date` | Date | **Required** | ISO8601 timestamp of the price validity | ```json theme={null} { "date": "2024-04-19T23:00:00Z", "address": "Feldskovvej 1B, 3. mf., 4180 Sorø", "subscriptions": [ { "name": "TSO - System Abonnement", "ownerName": "Energinet", "price": 0.625 }, { "name": "Net abo C forbrug time", "ownerName": "Cerius A/S", "price": 2.19791 } ], "tariffs": [ { "name": "Transmissions nettarif", "ownerName": "Energinet", "price": 0.0925 }, { "name": "Systemtarif", "ownerName": "Energinet", "price": 0.06375 }, { "name": "Elafgift", "ownerName": "Energinet", "price": 0.95125 }, { "name": "Nettarif C time", "ownerName": "Cerius A/S", "price": 0.14075 } ] } ``` | Parameter | Type | | Description | | --------------- | ------ | ------------ | --------------------------------------- | | `date` | String | **Required** | ISO8601 timestamp of the price validity | | `address` | String | *Optional* | The address of the location | | `subscriptions` | Array | **Required** | A list of all applicable subscriptions | | `tariffs` | Array | **Required** | A list of all applicable tariffs | *** ## Historic charges Get historical full charges information for a specific location and date range. ```javascript theme={null} GET /prices/charges/location/history?latitude={latitude}&longitude={longitude}&fromDate={fromDate}&toDate={toDate} ``` | | Type | | Description | | ----------- | ------ | ------------ | -------------------------------------------------------------------------------------------------- | | `latitude` | Double | **Required** | The latitude of the location | | `longitude` | Double | **Required** | The longitude of the location | | `fromDate` | String | **Required** | ISO8601 timestamp marking the start of the date range (inclusive) | | `toDate` | String | *Optional* | ISO8601 timestamp marking the end of the date range (exclusive). Defaults to the current date/time | ```json theme={null} { "from": "2025-02-14T21:31:50Z", "to": "2025-05-14T21:31:50Z", "tariffs": [ { "price": { "static": { "price": 0.9 } }, "ownerName": "Energinet", "name": "Elafgift", "from": "2024-12-31T23:00:00Z" }, // ... additional tariff entries ... ], "subscriptions": [ { "name": "Net abo C forbrug", "price": { "static": { "price": 26.686367 } }, "ownerName": "N1 A/S - 131", "from": "2024-12-31T23:00:00Z" }, // ... additional subscription entries ... ] } ``` | Parameter | Type | | Description | | --------------- | ------ | ------------ | ------------------------------------------------- | | `from` | String | **Required** | ISO8601 timestamp marking the start of the period | | `to` | String | *Optional* | ISO8601 timestamp marking the end of the period | | `tariffs` | Array | **Required** | List of tariffs with time intervals | | `subscriptions` | Array | **Required** | List of subscriptions with time intervals | *** # API Usage ## Request count Get the running request count for your account ```javascript theme={null} GET /currentRequestCount ``` ```json theme={null} [ { "date": "2024-05-16T22:00:00Z", "requestCount": 1257 }, { "date": "2024-05-17T22:00:00Z", "requestCount": 1104 } ] ``` | Parameter | Type | | Description | | -------------- | ------ | ------------ | --------------------------------------------------------------- | | `date` | String | **Required** | ISO8601 timestamp of the day | | `requestCount` | Int | **Required** | The *total* requests logged for your account on the given `day` | # Shared data types Source: https://docs.minstroem.app/api-reference/shared ## Regions | | | | ----- | ------------ | | `DK1` | West Denmark | | `DK2` | East Denmark | | `SE1` | Luleå | | `SE2` | Sundsvall | | `SE3` | Stockholm | | `SE4` | Malmø | | `NO1` | Oslo | | `NO2` | Kristiansand | | `NO3` | Trondheim | | `NO4` | Tromsø | | `NO5` | Bergen | # Addresses and capabilities Source: https://docs.minstroem.app/consumer-api/addresses Find your addresses and the data available for each. Start with [List addresses](/consumer-api/reference/list-addresses). Use an address's returned `id` when requesting its data. If you have no addresses, the response is `{"data":[]}`. ## Check what's available Each address includes `capabilities`. Check that the relevant flag is `true` before requesting a series. | Flag | Data | | -------------------- | ------------------------------- | | `consumption` | Electricity consumption | | `solarExport` | Electricity exported from solar | | `consumptionCosts` | Calculated consumption costs | | `solarExportRevenue` | Calculated solar-export revenue | | `prices` | Historical electricity prices | | `forecastPrices` | Hourly price forecasts | Availability varies by address. A capability can be available even when some readings are missing. If you update your address or meter connection in the app, list your addresses again. ## Address details `label` and `formattedAddress` are display names. `gridOperatorName` identifies your grid operator, and `supplierName` identifies your current electricity supplier. Names and `region` may be `null` when unavailable. `timeZone` describes the calendar used for [time intervals](/consumer-api/time-and-ranges). Timestamps are returned in UTC. ## Historical data Historical readings may remain available after a meter connection ends. The returned data can cover less than the period requested. # Authentication and security Source: https://docs.minstroem.app/consumer-api/authentication Create a key in the iOS app and keep it secret. Every request requires an **active Min Strøm Plus subscription** and a **valid API key**. ## Send the key Include your key in the `Authorization` header: ```http theme={null} Authorization: Bearer YOUR_API_KEY ``` For a quick test: ```bash theme={null} curl --fail-with-body --silent --show-error \ --header "Authorization: Bearer ${MINSTROEM_API_TOKEN}" \ "https://api.minstroem.app/consumer/v1/me/addresses" ``` ## Manage your key * You have one key at a time, shown only when created or replaced. * Keys expire one year after creation or replacement. * Replace a lost or exposed key in iOS, then update your integrations. The old key stops working. * Revoke a key in iOS when you no longer need it. API access requires active Plus. If your subscription ends, the key is retained and can work again when Plus is restored, provided it is still valid. ## Keep it secret Store the key in an environment variable or secret store. Keep it out of source code, URLs, screenshots, and logs, and never send it in a support message. Use HTTPS for every request. See [Errors and limits](/consumer-api/errors-and-limits) if your key is rejected. # Data interpretation Source: https://docs.minstroem.app/consumer-api/data-interpretation Understand missing readings, estimates, and calculated amounts. ## Missing is not zero Readings are returned in time order. Some intervals may be missing, or the result may be empty. A missing reading means the value is unknown, not zero. For a request covering 10:00–13:00 UTC, this synthetic hourly response contains **no information** about 11:00–12:00: ```json theme={null} { "addressId": "2b4bf7a8-b5d0-45ab-8d42-3a5688bba167", "from": "2026-09-05T10:00:00Z", "to": "2026-09-05T13:00:00Z", "aggregation": "hour", "timeZone": "Europe/Copenhagen", "data": [ { "start": "2026-09-05T10:00:00Z", "end": "2026-09-05T11:00:00Z", "energyKWh": 1.2, "isEstimate": false }, { "start": "2026-09-05T12:00:00Z", "end": "2026-09-05T13:00:00Z", "energyKWh": 0, "isEstimate": false } ] } ``` The returned energy sums to 1.2 kWh, but that is not a verified total for the three-hour period. The second row reports a known zero; the missing middle row does not. A `200` response means the request succeeded, **not that the period is complete**. Keep missing intervals unknown in charts and reports, including when working with daily or larger totals. ## Estimates and nulls `isEstimate: true` marks estimated data. Forecast responses always carry this flag. `null` means a value is unavailable. For example: * Unknown variable price charges are null, not zero. * Cost/revenue effective rates are null when energy is zero, even when fixed fees or monetary amounts exist. * Missing grid or supplier names are null. Do not silently substitute zero for a null component. ## Energy, currency, and VAT `energyKWh` is measured in kWh. Monetary responses state `currency` and `vatIncluded`. Prices and consumption costs include VAT. Solar-export revenue excludes VAT. Rates are currency per kWh; fixed fees and totals are amounts in the stated currency: DKK, SEK, or NOK. Prices reflect the available price components for your address and may differ from the amount on your bill. ## Calculated costs and revenue Consumption `totalCost` includes fixed fees; solar `netRevenue` is the amount after fixed fees. The effective `totalPricePerKWh` excludes fixed fees and is `null` at zero energy. Rates and amounts can be negative. For example, 2 kWh, a total cost of 4.60 DKK, and fixed fees of 0.10 DKK give an effective rate of 2.25 DKK/kWh. See the [cost](/consumer-api/reference/consumption-costs) and [revenue](/consumer-api/reference/solar-export-revenue) references for field definitions. ## Price precision and billing Historical and forecast `totalPricePerKWh` and `variableChargesPerKWh` are rounded to three decimal places. Trailing zeros may be omitted: 1.2 and 1.200 represent the same value. For example, a rate of 1.2344 appears as 1.234. Multiplying the rounded price by 100 kWh gives 123.40 rather than 123.44. Use the cost or revenue endpoint for calculated amounts. Reported totals cover the available data and may differ from your complete bill. # Errors and limits Source: https://docs.minstroem.app/consumer-api/errors-and-limits Stable error codes, request IDs, and shared request budgets. ## Error responses Errors include a readable explanation and a code: ```json theme={null} { "error": true, "reason": "An active Min Strøm Plus subscription is required.", "errorCode": "plus_required" } ``` Use the HTTP status and `errorCode` to handle errors in your integration. `reason` explains the problem in plain language. | Status | Code | Action | | ------ | -------------------------- | ----------------------------------------------------------------------- | | 400 | `invalid_parameter` | Check the endpoint's parameters, timestamps, and interval values. | | 400 | `invalid_range` | Make the start earlier than the end. | | 400 | `range_too_large` | Split the range using aligned boundaries; limits apply after expansion. | | 401 | `invalid_token` | Check your bearer header and key; replace a lost key in iOS. | | 401 | `credential_expired` | Replace the expired key in iOS. | | 403 | `plus_required` | Restore an active Plus subscription. | | 403 | `forbidden` | Access is denied. Check the resource you requested. | | 404 | `resource_not_found` | Re-list your addresses and use a returned ID. | | 422 | `feature_unavailable` | Check the address's capability flags. | | 429 | `rate_limited` | Wait at least `Retry-After` seconds. | | 500 | `internal_error` | Retry with backoff; contact support if persistent. | | 502 | `upstream_unavailable` | Data is temporarily unavailable; retry later. | | 503 | `entitlement_unavailable` | Plus verification is unavailable; retry later. | | 503 | `rate_limiter_unavailable` | Request limiting is unavailable; retry later. | ## Request and cache headers Responses include `X-Request-ID` for troubleshooting and `Cache-Control: private, no-store`. You may supply a UUID in the `X-Request-ID` request header. Include the response request ID and endpoint when contacting [support](mailto:engberg@minstroem.app). Never include your key or authorization header. ## Request limits The standard limits are **60 requests per minute** and **2,000 per day**, shared by your integrations. Check the response headers for your current allowance. Limits reset at the start of each UTC minute and at midnight UTC. Replacing your key keeps the same allowance. Requests with a valid key and active Plus count toward both limits, including requests that return errors or `429`. Requests rejected for authentication or Plus access do not count. Wait before retrying to avoid using up your allowance. ## Read the quota headers Quota headers describe your remaining allowance: | Header | Meaning | | ------------------------------------------------------------ | ---------------------------------- | | `X-RateLimit-Limit-Minute` / `X-RateLimit-Limit-Day` | Request limits | | `X-RateLimit-Remaining-Minute` / `X-RateLimit-Remaining-Day` | Remaining attempts, never negative | | `X-RateLimit-Reset-Minute` / `X-RateLimit-Reset-Day` | Reset instants as Unix seconds | | `Retry-After` | Seconds to wait on a 429 | For example, `Retry-After: 42` means wait at least 42 seconds before another attempt. If both limits are reached, wait for the later reset. Quota headers may be absent on authentication errors or temporary service failures. Creating or replacing a key in the app has a separate limit of five attempts per minute. # Forecast prices Source: https://docs.minstroem.app/consumer-api/forecasts Upcoming hourly electricity-price estimates. [Get forecast prices](/consumer-api/reference/forecast-prices) returns the available hourly estimates for DK1, DK2, SE3, and SE4. Check your address's `forecastPrices` capability before requesting them. Forecasts cover upcoming hours after the latest confirmed price, starting no earlier than the current hour. The available horizon varies. As confirmed prices arrive, the forecast period moves forward. The response has `isEstimate: true`. Each price has a `start` and `end` timestamp. If no forecasts are available, `data` is empty. See the [endpoint reference](/consumer-api/reference/forecast-prices) for the request and example response. # Quick start Source: https://docs.minstroem.app/consumer-api/quickstart Create a key and fetch your first consumption series. Choose **Download API spec** from the page menu to download the Consumer API's OpenAPI specification for import into tools such as Postman. ## 1. Create your API key In the Min Strøm iOS app, open **Profile**, then **API-adgang** (API access). Choose **Opret API-nøgle** (Create API key). An active Min Strøm Plus subscription is required. Copy the complete key and store it securely. It is shown only once. If you lose it, use **Erstat API-nøgle** (Replace API key) to issue a replacement; the old key stops working. ## 2. Configure your terminal The examples use Bash and curl. This prompt keeps the key itself out of the command you type into shell history: ```bash theme={null} read -r -s -p "Min Strøm API key: " MINSTROEM_API_TOKEN printf '\n' export MINSTROEM_API_TOKEN export MINSTROEM_API_URL='https://api.minstroem.app/consumer/v1' ``` Keep your key out of source code, URLs, screenshots, and support messages. See [Authentication and security](/consumer-api/authentication) for storing it safely. ## 3. Find your address Use [List addresses](/consumer-api/reference/list-addresses) to find your address(es). The reference includes the request details and example response. ```bash theme={null} curl --fail-with-body --silent --show-error \ --header "Authorization: Bearer ${MINSTROEM_API_TOKEN}" \ "${MINSTROEM_API_URL}/me/addresses" ``` The `data` array contains your addresses. Choose an entry whose `capabilities.consumption` is `true` and copy its `id`. Set it for subsequent requests: ```bash theme={null} export MINSTROEM_ADDRESS_ID='2b4bf7a8-b5d0-45ab-8d42-3a5688bba167' ``` The ID above is synthetic. Replace it with an ID returned for your account. ## 4. Read consumption Choose a period for which your address has data. The [consumption reference](/consumer-api/reference/consumption) describes the parameters and response fields. This example requests a single UTC hour: ```bash theme={null} curl --fail-with-body --silent --show-error --get \ --header "Authorization: Bearer ${MINSTROEM_API_TOKEN}" \ --data-urlencode 'from=2026-09-05T10:00:00Z' \ --data-urlencode 'to=2026-09-05T11:00:00Z' \ --data-urlencode 'aggregation=hour' \ "${MINSTROEM_API_URL}/me/addresses/${MINSTROEM_ADDRESS_ID}/consumption" ``` Values are returned as `energyKWh`. The response may be empty if no readings are available. Do not assume that a successful request covers the entire requested period. Use `--include` with curl when you need to inspect HTTP status, rate-limit headers, and `X-Request-ID`. Curl 7.76 or newer supports `--fail-with-body`. When finished with this terminal session: ```bash theme={null} unset MINSTROEM_API_TOKEN ``` # Get consumption Source: https://docs.minstroem.app/consumer-api/reference/consumption GET /me/addresses/{addressId}/consumption Get electricity consumption. Hourly requests cover up to 366 days; daily, monthly, or yearly requests cover up to five years. Limits apply after range normalization. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/consumption?from={from}&to={to}&aggregation={aggregation} ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Get consumption costs Source: https://docs.minstroem.app/consumer-api/reference/consumption-costs GET /me/addresses/{addressId}/consumption-costs Get calculated electricity costs, including VAT and fixed fees. Available for Danish addresses. Request up to 366 days after range normalization. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/consumption-costs?from={from}&to={to}&aggregation={aggregation} ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Get forecast prices Source: https://docs.minstroem.app/consumer-api/reference/forecast-prices GET /me/addresses/{addressId}/forecast-prices Get upcoming hourly price estimates for DK1, DK2, SE3, and SE4. Forecasts follow the latest confirmed price, starting no earlier than the current hour. The available forecast period varies. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/forecast-prices ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Forecasts](/consumer-api/forecasts) for help reading the response. # List addresses Source: https://docs.minstroem.app/consumer-api/reference/list-addresses GET /me/addresses List your addresses and the data available for each. ```http theme={null} GET /consumer/v1/me/addresses ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Get historical prices Source: https://docs.minstroem.app/consumer-api/reference/prices GET /me/addresses/{addressId}/prices Get confirmed electricity prices by hour or quarter-hour. Request up to 366 days at hourly resolution or 90 days at quarter-hour resolution, after range normalization. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/prices?from={from}&to={to}&resolution={resolution} ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Get solar export Source: https://docs.minstroem.app/consumer-api/reference/solar-export GET /me/addresses/{addressId}/solar-export Get electricity exported from solar. Hourly requests cover up to 366 days; daily, monthly, or yearly requests cover up to five years. Limits apply after range normalization. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/solar-export?from={from}&to={to}&aggregation={aggregation} ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Get solar-export revenue Source: https://docs.minstroem.app/consumer-api/reference/solar-export-revenue GET /me/addresses/{addressId}/solar-export-revenue Get calculated solar-export revenue after fixed fees, excluding VAT. Available for Danish addresses. Request up to 366 days after range normalization. ```http theme={null} GET /consumer/v1/me/addresses/{addressId}/solar-export-revenue?from={from}&to={to}&aggregation={aggregation} ``` Follow [Quick start](/consumer-api/quickstart) to try the curl example. See [Time and ranges](/consumer-api/time-and-ranges) and [Data interpretation](/consumer-api/data-interpretation) for help using the results. # Time and ranges Source: https://docs.minstroem.app/consumer-api/time-and-ranges UTC timestamps, calendar intervals, and bounded requests. Historical series use `from`, `to`, and either `aggregation` or `resolution`. See each endpoint's reference for its parameters. ## Timestamp format Send RFC 3339 timestamps with an explicit `Z` or numeric offset. Fractional seconds are accepted: * `2026-09-05T10:00:00Z` * `2026-09-05T12:00:00+02:00` — the same instant * `2026-09-05T10:00:00.125Z` Supply each required parameter once, with `from` earlier than `to`. Use curl's `--data-urlencode` for query values, especially numeric offsets containing `+`. Response timestamps are UTC. The `timeZone` field, `Europe/Copenhagen`, describes the calendar used for interval boundaries. ## Inclusive start, exclusive end An interval covers `[start, end)`. Requested ranges cover `[from, to)`. Bounds expand outward to complete requested intervals. An already aligned exclusive `to` does not expand again. For example, an hourly request from `10:15Z` to `11:10Z` on the same day becomes `10:00Z` to `12:00Z`. A request ending exactly at `11:00Z` ends there. The response's `from` and `to` show these adjusted bounds, even when some readings are missing. Each row's `start` and `end` describe its own interval. ## Calendar boundaries and daylight saving Days, months, and years follow the `Europe/Copenhagen` calendar. Days around daylight-saving changes have different lengths: | Local day | UTC bounds | Duration | | --------------- | ------------------------------------------------ | -------- | | 29 March 2026 | `2026-03-28T23:00:00Z` to `2026-03-29T22:00:00Z` | 23 hours | | 25 October 2026 | `2026-10-24T22:00:00Z` to `2026-10-25T23:00:00Z` | 25 hours | In autumn, `2026-10-25T00:00:00Z` and `2026-10-25T01:00:00Z` are distinct hours even though both display as 02:00 locally with different offsets. Key readings by absolute timestamps, not a local hour label. Do not assume every day contains 24 hourly readings. ## Intervals and limits Caps apply **after normalization**, using local calendar days or years. | Resource | Values | Maximum normalized range | | --------------------------------- | ------------------------------ | ------------------------ | | Consumption / solar export | `hour` | 366 days | | Consumption / solar export | `day`, `month`, `year` | Five years | | Consumption costs / solar revenue | `hour`, `day`, `month`, `year` | 366 days | | Historical prices | `hour` | 366 days | | Historical prices | `fifteenMinutes` | 90 days | Usage, costs, and revenue use the query name `aggregation`. Historical prices use `resolution`; spelling and case matter. Expansion can push a short-looking request over its cap. A yearly cost request crossing New Year expands to two whole years and is rejected, even if its original bounds were only days apart. Request each year separately. The available forecast period is described in [Forecasts](/consumer-api/forecasts). ## Fetch adjacent windows Split large historical requests into aligned windows: 1. Request `[A, B)`. 2. Request `[B, C)` at the same interval. 3. Combine rows by absolute `start` timestamp. Choose calendar-aligned boundaries before splitting. Splitting at 10:30 and relying on normalization can cause both responses to include the same 10:00 hourly bucket. Retrying or refreshing a window can also return revised data; replace the matching interval rather than adding it again. # Troubleshooting Source: https://docs.minstroem.app/consumer-api/troubleshooting Help with keys, addresses, and missing data. ## My key is rejected Check your `Authorization: Bearer …` header. * `invalid_token`: check that you copied the complete, current key. * `credential_expired`: replace the key in iOS. * `plus_required`: restore an active Plus subscription. * `entitlement_unavailable`: subscription verification is temporarily unavailable; try again later. If you have lost your key, replace it in iOS and update your integration. ## I can't find my address [List your addresses](/consumer-api/reference/list-addresses) and use an `id` from that response. Check your addresses in the app if the list is empty or an address is missing. ## A capability is unavailable Check the address's [capability flags](/consumer-api/addresses) and its meter connection in the app. After making changes, list your addresses again. ## Data is missing Try a period for which you can see readings in the app. A response may cover only part of the requested period, and an empty result can be valid. Keep missing readings separate from zero readings. See the [example](/consumer-api/data-interpretation#missing-is-not-zero). Forecast availability can also vary; check again later. ## Requests fail intermittently For `429`, wait at least the number of seconds in `Retry-After`. For temporary `500`, `502`, or `503` errors, retry a few times with increasing delays, then stop. Repeated attempts can use up your request allowance. Contact [engberg@minstroem.app](mailto:engberg@minstroem.app) with the endpoint, UTC time, status, error code, and `X-Request-ID`. Keep your key and personal data out of the message. # Enterprise API (B2B) Source: https://docs.minstroem.app/enterprise-api/overview Integrate Min Strøm electricity data into your business. The Enterprise API is intended for business-to-business integrations. Access is arranged directly with Min Strøm, with a separate API key and secret. The Enterprise API uses the `/thirdParty` endpoints. See the authentication guide and endpoint reference below to get started. Generate the bearer token using your existing API key and secret. Browse prices, charges, address lookup, and request counts. Tell us about your business and the integration you would like to build. Looking to access your own household's data with Min Strøm Plus? Start with the [Consumer API](/introduction). Consumer API keys cannot authenticate Enterprise requests, or vice versa. # Consumer API Source: https://docs.minstroem.app/introduction Your energy data. Your own integrations. Min Strøm Min Strøm ## Your data, on your terms The Min Strøm Consumer API gives **Min Strøm Plus** subscribers read-only access to their own addresses, electricity consumption, solar export, calculated costs, and prices. Create an API key in the iOS app, then use it in your own integration. Your key identifies your account. Create a key, find your address(es), and fetch consumption using curl. The Enterprise API (B2B) has a separate access process and authentication. ## What you can read * Address summaries and the capabilities available for each address. * Electricity consumption and solar-export series. * Calculated consumption costs and solar-export revenue. * Confirmed historical prices and available hourly forecast prices. Available data varies by address. A successful response may contain fewer readings than the requested period: missing data is not zero.