Telescope Energy
API reference

Customer API

Forecast consumers, analysts, and operational applications

Base URL: https://telescope.energy/api/v2

Send a customer API key as a Bearer token in the Authorization header.

Download OpenAPI · Authentication · Troubleshooting

MethodEndpointTask
GET/api/v2/customer/catalogList published forecast offerings
GET/api/v2/customer/forecasts/{offering}/currentRead the current forecast
GET/api/v2/customer/forecasts/{offering}/dataRead a delivery range at a fixed cutoff or constant lead
GET/api/v2/customer/forecasts/{offering}/versionsList immutable forecast history
GET/api/v2/customer/forecast-versions/{id}Read one reproducible forecast version

Use the catalog to select a product and read its current units and delivery horizon.

Examples use illustrative identifiers and dates. Python uses the standard library; TypeScript runs server-side with fetch support.

Set TELESCOPE_API_KEY and choose products available to your account.

List published forecast offerings

GET /api/v2/customer/catalog

Lists the products available to your customer account, with their variants, units, series, outputs and delivery horizons.

Required scope: catalog:read.

Request

curl 'https://telescope.energy/api/v2/customer/catalog' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY"

Response

200 OK

Illustrative excerpt; fields and arrays are shortened. See the downloadable OpenAPI for schemas and expanded examples.

{
  "products": [
    {
      "slug": "afrr-de",
      "title": "Automatic Frequency Restoration Reserve (aFRR) · DE",
      "description": "Probabilistic forecasts for German aFRR capacity prices, energy prices, and activated reserve power.",
      "category": "Balancing",
      "variants": [
        {
          "key": "capacity-price",
          "label": "Capacity Price",
          "isDefault": true,
          "publicationStatus": "published",
          "offeringKey": "afrr-capacity-price-de",
          "timezone": "Europe/Berlin",
          "resolution": "PT4H",
          "unit": "EUR_MWH",
          "outputs": [
            { "key": "p10", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.1 },
            { "key": "p50", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.5 },
            { "key": "p90", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.9 }
          ],
          "series": [
            { "key": "positive", "label": "Positive", "direction": "positive" },
            { "key": "negative", "label": "Negative", "direction": "negative" }
          ],
          "firstDeliveryDayOffset": 1,
          "maxHorizonDays": 7,
          "updatePolicy": { "mode": "gate_closure", "gateDaysBeforeDelivery": 1, "gateLocalTime": "09:00" },
          "historySince": "2026-07-27",
          "latestReleasedAt": "2026-07-26T17:00:00.000Z"
        },
        {
          "key": "energy-price",
          "label": "Energy Price",
          "isDefault": false,
          "publicationStatus": "published",
          "offeringKey": "afrr-energy-price-de",
          "timezone": "Europe/Berlin",
          "resolution": "PT15M",
          "unit": "EUR_MWH",
          "outputs": [
            { "key": "p10", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.1 },
            { "key": "p50", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.5 },
            { "key": "p90", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.9 }
          ],
          "series": [
            { "key": "positive", "label": "Positive", "direction": "positive" },
            { "key": "negative", "label": "Negative", "direction": "negative" }
          ],
          "firstDeliveryDayOffset": 1,
          "maxHorizonDays": 7,
          "updatePolicy": { "mode": "gate_closure", "gateDaysBeforeDelivery": 1, "gateLocalTime": "09:00" },
          "historySince": "2026-07-27",
          "latestReleasedAt": "2026-07-26T17:00:00.000Z"
        }
      ]
    }
  ]
}
FieldMeaning
products[].slugUse in customer forecast URLs for the default variant.
products[].variants[].offeringKeyUse in customer forecast URLs to choose a specific variant.
products[].variants[].timezone / resolutionLocal delivery-day boundaries and interval resolution.
products[].variants[].series / outputsValue dimensions, units and output types.
variants[].historySince / latestReleasedAtOn each variant: earliest published delivery date and most recent release time (RFC 3339), or null. These do not guarantee complete coverage.

Usage notes

  • Read delivery and output metadata from the selected variant.
  • firstDeliveryDayOffset and maxHorizonDays are the first and last allowed delivery-day offsets from today, in the product time zone.
  • Refresh the catalog to detect configuration changes.
  • Account rate limit: 120 read requests per minute, with a burst capacity of 30. The token bucket refills continuously and is shared across all API keys of the account and both Customer and Producer read endpoints. Authenticated, authorized requests consume quota even if subsequent validation fails; retries also count. An exhausted bucket returns 429 RATE_LIMIT_EXCEEDED with Retry-After in whole seconds. Wait before retrying; reuse the same Idempotency-Key and payload for a submission retry.

Read the current forecast

GET /api/v2/customer/forecasts/{offering}/current

Retrieves the latest published forecast for every requested delivery day.

Required scope: forecasts:read.

Parameters

ParameterLocationTypeRequiredDescription
offeringPathstringYesProduct slug for its default variant, or variants.offeringKey for a specific variant.
horizonQuerystringNoConsecutive delivery days, P1D through P8D, subject to the offering horizon. Defaults to P1D.
startQueryYYYY-MM-DDNoFirst local delivery day; defaults to the offering offset.

Request

curl 'https://telescope.energy/api/v2/customer/forecasts/afrr-activations-de/current?horizon=P1D' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY"

Response

200 OK

Illustrative excerpt; fields and arrays are shortened. See the downloadable OpenAPI for schemas and expanded examples.

{
  "offering": "afrr-activations-de",
  "requested": { "horizon": "P1D", "startDay": "2026-07-27" },
  "resolved": { "from": "2026-07-26T22:00:00.000Z", "to": "2026-07-27T22:00:00.000Z", "timezone": "Europe/Berlin" },
  "resolution": "PT15M",
  "unit": "MW",
  "outputs": [
    { "key": "p10", "valueType": "number", "unit": "MW", "quantileLevel": 0.1 },
    { "key": "p50", "valueType": "number", "unit": "MW", "quantileLevel": 0.5 },
    { "key": "p90", "valueType": "number", "unit": "MW", "quantileLevel": 0.9 }
  ],
  "series": [
    { "key": "positive", "label": "Positive", "direction": "positive" },
    { "key": "negative", "label": "Negative", "direction": "negative" }
  ],
  "deliveryDays": [
    { "deliveryDay": "2026-07-27", "forecastVersionId": "n97abc123", "version": 4, "status": "rolling", "coverageRatio": 1, "releasedAt": "2026-07-26T17:00:00.000Z" }
  ],
  "values": [
    { "validTime": "2026-07-26T22:00:00.000Z", "seriesKey": "negative", "outputKey": "p50", "value": 420.1 },
    { "validTime": "2026-07-26T22:00:00.000Z", "seriesKey": "positive", "outputKey": "p50", "value": 385.6 }
  ]
}
FieldMeaning
deliveryDays[].forecastVersionIdStore this identifier if you need to reproduce a decision.
deliveryDays[].statuspreliminary: may be updated before finalization; final: finalized forecast; rolling: regularly updated forecast. Released version IDs remain immutable.
resolvedRequested delivery range expressed as RFC 3339 timestamps, with the product time zone.
valuesRows sorted by validTime, seriesKey and outputKey.

Usage notes

  • If any requested day is unavailable, the entire request returns 404 FORECAST_NOT_PUBLISHED.
  • Omit start to use the product’s first configured delivery day. Every requested day must fall within the product horizon; otherwise the request returns 422 DELIVERY_DAYS_OUTSIDE_OFFERING_HORIZON.
  • Timestamps use RFC 3339. Use the unit on the corresponding output.
  • Use the data endpoint for historical selection and the version endpoint to retrieve a saved version.
  • Account rate limit: 120 read requests per minute, with a burst capacity of 30. The token bucket refills continuously and is shared across all API keys of the account and both Customer and Producer read endpoints. Authenticated, authorized requests consume quota even if subsequent validation fails; retries also count. An exhausted bucket returns 429 RATE_LIMIT_EXCEEDED with Retry-After in whole seconds. Wait before retrying; reuse the same Idempotency-Key and payload for a submission retry.

Read a delivery range at a fixed cutoff or constant lead

GET /api/v2/customer/forecasts/{offering}/data

Retrieves historical forecasts using either one knowledge timestamp or a constant decision lead. The range includes both deliveryFrom and deliveryTo, in the product time zone.

Required scope: forecasts:read.

Parameters

ParameterLocationTypeRequiredDescription
offeringPathstringYesProduct slug for its default variant, or variants.offeringKey for a specific variant.
deliveryFromQueryYYYY-MM-DDYesFirst local delivery day, inclusive.
deliveryToQueryYYYY-MM-DDYesLast local delivery day, inclusive; at most 366 days per range.
asOfQuerystringNoFixed availability cutoff; must not be in the future. Supply either asOf or both relativeTo and leadMinutes.
limitQueryinteger · 1–8NoMaximum delivery days per page. Defaults to 7.
cursorQuerystringNoOpaque continuation cursor bound to the original request.
relativeToQuerygateClosure, validTimeNoExplicit reference for the lead: gateClosure (market gate closure) or validTime (delivery interval start). Required with leadMinutes; cannot be combined with asOf.
leadMinutesQueryinteger ≥ 0NoNon-negative whole minutes before the reference time. Required with relativeTo; zero includes releases exactly at the reference time.

Request

curl 'https://telescope.energy/api/v2/customer/forecasts/day-ahead-price-de-lu/data?deliveryFrom=2026-08-01&deliveryTo=2026-08-03&asOf=2026-07-31T10:00:00Z&limit=2' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY"

Response

200 OK

Illustrative excerpt; fields and arrays are shortened. See the downloadable OpenAPI for schemas and expanded examples.

{
  "offering": "day-ahead-price-de-lu",
  "requested": { "deliveryFrom": "2026-08-01", "deliveryTo": "2026-08-03", "asOf": "2026-07-31T10:00:00.000Z", "limit": 2 },
  "page": { "deliveryFrom": "2026-08-01", "deliveryTo": "2026-08-02", "deliveryDayCount": 2 },
  "resolution": "PT15M",
  "timezone": "Europe/Berlin",
  "unit": "EUR_MWH",
  "outputs": [
    { "key": "p10", "valueType": "number", "unit": "EUR_MWH" },
    { "key": "p50", "valueType": "number", "unit": "EUR_MWH" },
    { "key": "p90", "valueType": "number", "unit": "EUR_MWH" }
  ],
  "series": [
    { "key": "value", "label": "Value" }
  ],
  "deliveryDays": [
    {
      "deliveryDay": "2026-08-01",
      "available": true,
      "forecastVersionId": "n97abc123",
      "version": 3,
      "status": "final",
      "coverageRatio": 1,
      "releasedAt": "2026-07-31T09:45:00.000Z"
    },
    { "deliveryDay": "2026-08-02", "available": false, "reason": "NO_VERSION_AT_AS_OF" }
  ],
  "values": [
    { "validTime": "2026-07-31T22:00:00.000Z", "seriesKey": "value", "outputKey": "p50", "value": 81.4 }
  ],
  "pagination": { "hasMore": true, "nextCursor": "eyJ2ZXJzaW9uIjoxLCJvZmZlcmluZ1NsdWciOiJkYXktYWhlYWQtcHJpY2UtZGUtbHUifQ" }
}

For relative selection, a gap example and a complete pagination loop, see Historical data & backtesting.

FieldMeaning
deliveryDaysAvailability and coverage per day; fixed asOf results also identify each day’s version.
valuesNormalized rows sorted by time, series and output.
intervalsRelative queries only: cutoff, availability and version for each expected interval. Join to values by validTime.
evaluatedAtRelative queries only: evaluation time fixed for the pagination sequence.
pagination.nextCursorOpaque cursor for the next page; null when complete.

Usage notes

  • Supply either asOf or both relativeTo and leadMinutes. Mixing modes or omitting a partner parameter returns 422.
  • asOf selects the latest version published at or before that timestamp for each day. A missing day has available: false and reason: NO_VERSION_AT_AS_OF.
  • relativeTo=gateClosure uses the local market gate minus leadMinutes. Provider submission lead is not subtracted. Products without a gate return 422 GATE_CLOSURE_NOT_SUPPORTED.
  • relativeTo=validTime uses each interval’s start minus leadMinutes. Zero lead includes releases exactly at the cutoff.
  • An interval uses the latest eligible publication containing it. All its series and outputs come from that version. Incomplete intervals are not filled using older versions.
  • Later publications never fill historical gaps. A day may contain multiple versions; retain interval version IDs for reproducibility.
  • Relative gaps use NO_VERSION_AT_AS_OF, NO_VALUE_AT_AS_OF, INCOMPLETE_INTERVAL or CUTOFF_NOT_REACHED. Missing intervals have no values rows. available on a day means at least one complete interval; check coverageRatio.
  • Follow nextCursor with the original product, date range and selection parameters. Relative pages retain evaluatedAt; restart without a cursor to evaluate again.
  • For 422 FORECAST_RANGE_TOO_COMPLEX, reduce limit. Contact support if a single day still fails.
  • Account rate limit: 120 read requests per minute, with a burst capacity of 30. The token bucket refills continuously and is shared across all API keys of the account and both Customer and Producer read endpoints. Authenticated, authorized requests consume quota even if subsequent validation fails; retries also count. An exhausted bucket returns 429 RATE_LIMIT_EXCEEDED with Retry-After in whole seconds. Wait before retrying; reuse the same Idempotency-Key and payload for a submission retry.

List immutable forecast history

GET /api/v2/customer/forecasts/{offering}/versions

Lists released forecast versions, newest first, so you can find a snapshot to retrieve again.

Required scope: forecasts:read.

Parameters

ParameterLocationTypeRequiredDescription
offeringPathstringYesProduct slug for its default variant, or variants.offeringKey for a specific variant.
limitQueryinteger · 1–100NoMaximum released versions, newest first. Defaults to 30.

Request

curl 'https://telescope.energy/api/v2/customer/forecasts/afrr-capacity-price-de/versions?limit=20' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY"

Response

200 OK

Illustrative excerpt; fields and arrays are shortened. See the downloadable OpenAPI for schemas and expanded examples.

{
  "versions": [
    {
      "forecastVersionId": "n97abc123",
      "offering": "afrr-capacity-price-de",
      "deliveryDay": "2026-07-27",
      "version": 4,
      "releasedAt": "2026-07-26T17:00:00.000Z",
      "coverageRatio": 1,
      "valueCount": 36,
      "status": "preliminary"
    }
  ]
}
FieldMeaning
versions[].forecastVersionIdVersion identifier for the forecast-version endpoint.
versions[].deliveryDay / releasedAtLocal delivery date and publication timestamp.
versions[].status / coverageRatioPublication status and coverage.

Usage notes

  • This endpoint returns metadata. Retrieve a version by its forecastVersionId to obtain values.
  • An unavailable product returns 404 OFFERING_NOT_FOUND.
  • Account rate limit: 120 read requests per minute, with a burst capacity of 30. The token bucket refills continuously and is shared across all API keys of the account and both Customer and Producer read endpoints. Authenticated, authorized requests consume quota even if subsequent validation fails; retries also count. An exhausted bucket returns 429 RATE_LIMIT_EXCEEDED with Retry-After in whole seconds. Wait before retrying; reuse the same Idempotency-Key and payload for a submission retry.

Read one reproducible forecast version

GET /api/v2/customer/forecast-versions/{id}

Retrieves the saved values of one immutable published forecast version.

Required scope: forecasts:read.

Parameters

ParameterLocationTypeRequiredDescription
idPathstringYesResource identifier returned by the catalog or list endpoint.

Request

curl 'https://telescope.energy/api/v2/customer/forecast-versions/n97abc123' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY"

Response

200 OK

Illustrative excerpt; fields and arrays are shortened. See the downloadable OpenAPI for schemas and expanded examples.

{
  "forecastVersion": {
    "forecastVersionId": "n97abc123",
    "offering": "afrr-capacity-price-de",
    "deliveryDay": "2026-07-27",
    "version": 4,
    "releasedAt": "2026-07-26T17:00:00.000Z",
    "coverageRatio": 1,
    "valueCount": 36,
    "status": "preliminary",
    "resolution": "PT4H",
    "timezone": "Europe/Berlin",
    "unit": "EUR_MWH",
    "outputs": [
      { "key": "p10", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.1 },
      { "key": "p50", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.5 },
      { "key": "p90", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.9 }
    ],
    "series": [
      { "key": "positive", "label": "Positive", "direction": "positive" },
      { "key": "negative", "label": "Negative", "direction": "negative" }
    ],
    "values": [
      { "validTime": "2026-07-26T22:00:00.000Z", "seriesKey": "positive", "outputKey": "p50", "value": 68.4 }
    ]
  }
}
FieldMeaning
forecastVersionVersion identifier, delivery day, release time and coverage.
forecastVersion.valuesValues identified by validTime, seriesKey and outputKey.

Usage notes

  • A missing or invalid identifier returns 404 FORECAST_VERSION_NOT_FOUND.
  • Retrieving the same version preserves the forecast even after newer versions are published.
  • Account rate limit: 120 read requests per minute, with a burst capacity of 30. The token bucket refills continuously and is shared across all API keys of the account and both Customer and Producer read endpoints. Authenticated, authorized requests consume quota even if subsequent validation fails; retries also count. An exhausted bucket returns 429 RATE_LIMIT_EXCEEDED with Retry-After in whole seconds. Wait before retrying; reuse the same Idempotency-Key and payload for a submission retry.

Errors and next steps

Errors contain error.code, error.message, optional error.details and requestId. The same request ID is returned in X-Request-ID. See Troubleshooting for recovery steps and retain the request ID when reporting a failure.

Forecast data explained

Copyright © 2026