Skip to content

Sync data ​

This guide shows how to keep a copy of your Telescope properties in your own system, such as a data warehouse, a database or an internal app. For Power BI, follow the Power BI guide instead.

Pagination ​

List endpoints return up to 100 items per page, with the most recently created first:

json
{
  "next": "https://api.telescope.eco/external/properties/?cursor=cD0yMDI2...",
  "previous": null,
  "results": [{ "id": "...", "name": "...", "updated_at": "..." }]
}

Keep requesting next until it is null. The page size is fixed.

  • Treat the cursor as opaque. Don't build or change it yourself.
  • Only follow next to Telescope. The safest way is to read the cursor query parameter from next and send it to the base URL you configured, together with your other query parameters. Then your API key can never be sent to another host.

A reliable sync ​

Every run fetches the full list and replaces your copy:

  1. Fetch every page of /external/properties/.
  2. Upsert each property by id into your copy.
  3. Remove the rest. The API doesn't report deletions, so delete the properties in your copy that this run didn't return.

Points worth getting right:

  • Remove only after the last page. If a run fails halfway, a property you didn't get may be on a page you never fetched.
  • Changes during a run are safe. Pages are ordered by when each property was created, so editing a property doesn't move it to another page. A property created during a run arrives with the next one.
  • Run it on a schedule, for example nightly. Each run also brings the latest hazard and biodiversity results, buildings and energy certificates.

Nested results ​

A property's updated_at changes only when the property itself changes. New or changed hazard results, biodiversity results, buildings and energy certificates don't change it. Each hazard and biodiversity result has its own updated_at, so you can tell which results changed since your last run.

To get one property's current results between runs, fetch it with GET /external/properties/{id}/.

Example in Python ​

python
from urllib.parse import parse_qs, urlparse

import requests

BASE_URL = "https://api.telescope.eco"
session = requests.Session()
session.headers["X-API-Key"] = "your-secret"


def list_all(path: str, **params) -> list[dict]:
    results = []
    while True:
        response = session.get(f"{BASE_URL}{path}", params=params, timeout=60)
        response.raise_for_status()
        page = response.json()
        results.extend(page["results"])
        if not page["next"]:
            return results
        # Only the cursor is taken from `next`, so the key never leaves BASE_URL
        params["cursor"] = parse_qs(urlparse(page["next"]).query)["cursor"][0]


def sync(ids_in_your_copy: set[str]) -> None:
    properties = list_all("/external/properties/")
    for prop in properties:
        upsert_property(prop)  # your storage, keyed by prop["id"]
    # Reached only after the last page, so a failed run removes nothing
    for property_id in ids_in_your_copy - {prop["id"] for prop in properties}:
        delete_property(property_id)

Portfolios ​

GET /external/portfolios/ lists root portfolios only. To get the whole tree, request each portfolio's detail, which includes its direct children, and repeat for each child:

text
GET /external/portfolios/                 → root portfolios
GET /external/portfolios/{id}/            → that portfolio's child portfolios and properties

Each property also carries its portfolio_id, so you can attach properties to the tree without walking it through the portfolio details.

Filter what you fetch ​

The property list takes filters, for example to only fetch properties with a relevant landslide hazard at high exposure:

text
GET /external/properties/?hazard=landslide&exposure=HIGH,VERY_HIGH&hazard_relevant=true

See property filters for all of them.

Generate a typed client ​

The OpenAPI schema works with code generators such as OpenAPI Generator or openapi-python-client. Many generators send Authorization: Bearer by default. Configure them to send the key in the X-API-Key header instead, with no prefix.