Telescope Energy
API reference

Producer API

Forecast providers and data engineering teams

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

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

Download OpenAPI · Authentication · Troubleshooting

MethodEndpointTask
GET/api/v2/producer/definitionsList allowed forecast definitions
POST/api/v2/producer/submissionsSubmit forecast snapshots
GET/api/v2/producer/submissionsList your accepted submissions
GET/api/v2/producer/submissions/{id}Inspect one accepted submission
GET/api/v2/producer/forecasts/{definition}/dataRead your point-in-time forecast range

Read the current definition before preparing a submission.

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 allowed forecast definitions

GET /api/v2/producer/definitions

Lists the forecast definitions available to your provider account. Each definition specifies the required time grid, series, outputs, units and submission policy.

Required scope: catalog:read.

Request

curl 'https://telescope.energy/api/v2/producer/definitions' \
  -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.

{
  "definitions": [
    {
      "key": "afrr-capacity-price-de",
      "title": "Automatic Frequency Restoration Reserve (aFRR) · DE",
      "market": "afrr",
      "zone": "DE",
      "target": "capacity-price",
      "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" }
      ],
      "horizon": { "firstDeliveryDayOffset": 1, "maxHorizonDays": 7 },
      "submissionRules": { "mode": "gate_closure", "gateDaysBeforeDelivery": 1, "gateLocalTime": "09:00", "submissionLeadMinutes": 5, "requireCompleteDeliveryDays": true }
    }
  ]
}
FieldMeaning
definitions[].keyUse this key in your submission.
definitions[]Resolution, time zone and forecast target.
definitions[].series / outputsEvery required series and output, including units and bounds.
definitions[].horizon / submissionRulesAllowed delivery dates, coverage and deadline rules.

Usage notes

  • Keys are case-sensitive. Refresh definitions before scheduled submissions.
  • See submission scheduling for rolling coverage and gate-closure deadlines.
  • 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.

Submit forecast snapshots

POST /api/v2/producer/submissions

Validates and accepts a complete forecast submission. If any value or delivery window is invalid, the entire submission is rejected and no forecast values are stored.

Required scope: submissions:write.

Parameters

ParameterLocationTypeRequiredDescription
Idempotency-KeyHeaderstringYesPersist one key per logical submission and reuse it only for identical retries.
definitionBodystringYesDefinition key returned by the producer catalog.
modelBodystringNoRegistered internal model key; omit for the managed default model.
generatedAtBodystringYesProducer-reported generation time; eligibility uses trusted receipt time.
deliveryWindowsBodyarrayYesLocal-day containers. Product-specific grid, coverage and horizon rules apply.
deliveryWindows[].deliveryDayBodystringYesLocal delivery day; validated against the product contract.
deliveryWindows[].valuesBodyarrayYesRequired intervals in ascending timestamp order.
deliveryWindows[].values[].validTimeBodystringYesRFC 3339 timestamp with seconds and Z or an explicit UTC offset.
deliveryWindows[].values[].outputsBodyobjectNoEvery configured output for a single-series definition.
deliveryWindows[].values[].seriesBodyobjectNoEvery configured series, each containing all outputs.

Supply exactly one of outputs or series per timestamp. Multi-series definitions require series. Prepare a complete payload with First submission.

Request

Save your complete payload as submission.json and set TELESCOPE_IDEMPOTENCY_KEY to the persisted key for this logical submission. Reuse both unchanged on retry.

curl --fail-with-body 'https://telescope.energy/api/v2/producer/submissions' \
  -H "Authorization: Bearer $TELESCOPE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $TELESCOPE_IDEMPOTENCY_KEY" \
  --data-binary @submission.json

Response

201 Created · 200 OK on replay

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

{
  "replayed": false,
  "runId": "m57abc123",
  "status": "accepted",
  "deliveryWindows": [
    { "deliveryDay": "2026-07-27", "expectedTimestamps": 6, "timestampCount": 6, "valueCount": 36, "coverageRatio": 1, "deadlineAt": "2026-07-27T08:45:00.000Z" }
  ],
  "definition": "afrr-capacity-price-de",
  "receivedAt": "2026-07-26T16:01:04.000Z"
}
FieldMeaning
runIdIdentifier of the accepted submission.
definition / receivedAtCanonical definition key and original receipt timestamp.
replayedTrue when this is the original result of an identical retry.
deliveryWindowsAccepted days, interval counts and coverage; gate-closure days also include deadlineAt.

Usage notes

  • Use exactly one of outputs or series per timestamp. Multiple configured series require series; include all configured outputs.
  • Unknown fields, duplicate timestamps, incomplete grids, non-finite values and values outside the configured bounds are rejected. Quantiles must be ordered within each series.
  • Bodies must not exceed 1 MiB (1,048,576 UTF-8 bytes) or 10,000 scalar forecast values across all timestamps, series and outputs. Oversized bodies return 413 SUBMISSION_TOO_LARGE; excess values return 422 TOO_MANY_VALUES or a SUBMISSION_REJECTED issue with that code. generatedAt must not be more than five minutes in the future.
  • Persist one Idempotency-Key per logical submission. Retry with exactly the same body and key. A changed body with the same key returns 409 IDEMPOTENCY_KEY_CONFLICT.
  • A validation failure returns 422 SUBMISSION_REJECTED with at most 100 details.issues containing path, code, message and optionally deliveryDay. details.issueCount reports the total; details.issuesTruncated indicates omitted issues. An identical retry returns the same stored issue summary. Correct the payload and use a new key.
  • Acceptance confirms receipt of your forecast. Customer publication is a separate step.
  • Account rate limit: 30 submissions per minute, with a burst capacity of 20. The token bucket refills continuously and is shared across all API keys of the account. 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 your accepted submissions

GET /api/v2/producer/submissions

Lists your accepted submissions, newest first.

Required scope: submissions:read.

Parameters

ParameterLocationTypeRequiredDescription
limitQueryinteger · 1–200NoMaximum accepted runs per page, newest first. Defaults to 50.
cursorQuerystringNoContinuation cursor returned by the previous page.

Request

curl 'https://telescope.energy/api/v2/producer/submissions?limit=25' \
  -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.

{
  "submissions": [
    {
      "runId": "m57abc123",
      "definition": "afrr-capacity-price-de",
      "model": { "key": null, "isDefault": true, "version": "1.0" },
      "idempotencyKey": "forecast-2026-07-27-v1",
      "generatedAt": "2026-07-26T16:00:00.000Z",
      "receivedAt": "2026-07-26T16:01:04.000Z",
      "status": "accepted",
      "valueCount": 36
    }
  ],
  "pagination": { "hasMore": false, "nextCursor": null }
}
FieldMeaning
submissions[].runIdUse this identifier to inspect a submission.
submissions[].generatedAt / receivedAtForecast generation and acceptance times as RFC 3339 timestamps.
submissions[].valueCountNumber of numeric output values accepted.
pagination.nextCursorContinue with this cursor; null marks the end.

Usage notes

  • Only submissions belonging to your provider account are returned.
  • 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.

Inspect one accepted submission

GET /api/v2/producer/submissions/{id}

Retrieves one of your accepted submissions, its delivery windows and forecast values.

Required scope: submissions:read.

Parameters

ParameterLocationTypeRequiredDescription
idPathstringYesResource identifier returned by the catalog or list endpoint.

Request

curl 'https://telescope.energy/api/v2/producer/submissions/m57abc123' \
  -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.

{
  "submission": {
    "run": {
      "runId": "m57abc123",
      "definition": "afrr-capacity-price-de",
      "model": { "key": null, "isDefault": true, "version": "1.0" },
      "idempotencyKey": "forecast-2026-07-27-v1",
      "generatedAt": "2026-07-26T16:00:00.000Z",
      "receivedAt": "2026-07-26T16:01:04.000Z",
      "status": "accepted",
      "valueCount": 36
    },
    "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" }
    ],
    "deliveryWindows": [
      { "deliveryDay": "2026-07-27", "expectedTimestamps": 6, "timestampCount": 6, "valueCount": 36, "coverageRatio": 1, "deadlineAt": "2026-07-27T08:45:00.000Z" }
    ],
    "values": [
      { "deliveryDay": "2026-07-27", "validTime": "2026-07-26T22:00:00.000Z", "seriesKey": "positive", "outputKey": "p50", "value": 68.4 }
    ]
  }
}
FieldMeaning
submission.runAccepted submission metadata.
submission.deliveryWindowsCoverage and interval counts per local day.
submission.valuesRows identified by validTime, seriesKey and outputKey.

Usage notes

  • A missing, invalid or inaccessible identifier returns 404 SUBMISSION_NOT_FOUND.
  • Timestamps use RFC 3339.
  • 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 your point-in-time forecast range

GET /api/v2/producer/forecasts/{definition}/data

Retrieves the forecast values your provider account had successfully submitted by a fixed time, over an inclusive range of local delivery dates.

Required scope: submissions:read.

Parameters

ParameterLocationTypeRequiredDescription
definitionPathstringYesResource identifier returned by the catalog or list endpoint.
deliveryFromQueryYYYY-MM-DDYesFirst local delivery day, inclusive.
deliveryToQueryYYYY-MM-DDYesLast local delivery day, inclusive; at most 366 days per range.
asOfQuerystringYesAvailability cutoff; must not be in the future.
limitQueryinteger · 1–8NoMaximum delivery days per page. Defaults to 7.
cursorQuerystringNoOpaque continuation cursor bound to the original request.
modelQuerystringNoInternal model key; omit for the managed default model.

Request

curl 'https://telescope.energy/api/v2/producer/forecasts/day-ahead-price-de-lu/data?deliveryFrom=2026-08-01&deliveryTo=2026-08-02&asOf=2026-07-31T10:00:00Z&model=fundamental-v3'   -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.

{
  "definition": "day-ahead-price-de-lu",
  "model": { "key": "fundamental-v3", "isDefault": false },
  "requested": { "deliveryFrom": "2026-08-01", "deliveryTo": "2026-08-02", "asOf": "2026-07-31T10:00:00.000Z", "limit": 7 },
  "page": { "deliveryFrom": "2026-08-01", "deliveryTo": "2026-08-02", "deliveryDayCount": 2 },
  "resolution": "PT15M",
  "timezone": "Europe/Berlin",
  "unit": "EUR_MWH",
  "outputs": [
    { "key": "p50", "valueType": "number", "unit": "EUR_MWH", "quantileLevel": 0.5 }
  ],
  "series": [
    { "key": "value", "label": "Value" }
  ],
  "deliveryDays": [
    {
      "deliveryDay": "2026-08-01",
      "available": true,
      "coverageRatio": 1,
      "runIds": [
        "m57newer",
        "m57older"
      ]
    },
    {
      "deliveryDay": "2026-08-02",
      "available": false,
      "coverageRatio": 0,
      "reason": "NO_ACCEPTED_FORECAST_AT_AS_OF",
      "runIds": []
    }
  ],
  "runs": [
    { "runId": "m57newer", "receivedAt": "2026-07-31T09:00:00.000Z", "modelVersion": "3.0" },
    { "runId": "m57older", "receivedAt": "2026-07-31T08:00:00.000Z", "modelVersion": "3.0" }
  ],
  "values": [
    { "validTime": "2026-07-31T22:00:00.000Z", "seriesKey": "value", "outputKey": "p50", "value": 81.4, "runId": "m57older" },
    { "validTime": "2026-07-31T22:15:00.000Z", "seriesKey": "value", "outputKey": "p50", "value": 82.1, "runId": "m57newer" }
  ],
  "pagination": { "hasMore": false, "nextCursor": null }
}
FieldMeaning
valuesValues with runId identifying the accepted submission for each row.
runsReferenced submissions and their acceptance times.
deliveryDaysAvailability and coverage per local day.
pagination.nextCursorUse this cursor for the next page; null marks the end.

Usage notes

  • Selection uses receivedAt, not generatedAt. All outputs and series for one interval come from the same accepted submission.
  • Results may combine several submissions. Customer publication does not affect this endpoint.
  • available means at least some values exist; check coverageRatio for completeness.
  • Follow nextCursor with the same definition, date range and asOf. Pages contain complete local days.
  • 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