Skip to content

Create properties ​

POST /external/properties/ adds a property to a portfolio from your own systems, for example when a new asset is registered in your property register. You send the matrikkelnummer, and Telescope finds the plot, starts the analyses and fetches the buildings and energy certificates.

Before you start

  • Creating must be enabled for your organization. Ask your Telescope contact to turn it on. Until then, requests return 403 with the code external_api_create_not_allowed. Reading works either way.
  • Norway only. Properties are found by their Norwegian matrikkelnummer.
  • Portfolios come from the app. The API can't create portfolios. Create them in Telescope, then find their IDs with GET /external/portfolios/.

Quick example ​

sh
curl -X POST https://api.telescope.eco/external/properties/ \
  -H "X-API-Key: $TELESCOPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "internal_reference_id": "P-1001",
    "portfolio_id": "b2a4c7e0-1d2f-4f39-8e2a-5c6d7e8f9a01",
    "name": "Storgata 1",
    "address": "Storgata 1",
    "postal_code": "0155",
    "postal_area": "Oslo",
    "country": "Norway",
    "matrikkelnummer": "0301-208/101",
    "value_estimate": 85000000
  }'
python
import requests

response = requests.post(
    "https://api.telescope.eco/external/properties/",
    headers={"X-API-Key": "your-secret"},
    json={
        "internal_reference_id": "P-1001",
        "portfolio_id": "b2a4c7e0-1d2f-4f39-8e2a-5c6d7e8f9a01",
        "name": "Storgata 1",
        "address": "Storgata 1",
        "postal_code": "0155",
        "postal_area": "Oslo",
        "country": "Norway",
        "matrikkelnummer": "0301-208/101",
        "value_estimate": 85_000_000,
    },
    timeout=60,
)
response.raise_for_status()
prop = response.json()
print(response.status_code, prop["id"])  # 201 when created, 200 when updated
powershell
$body = @{
    internal_reference_id = "P-1001"
    portfolio_id          = "b2a4c7e0-1d2f-4f39-8e2a-5c6d7e8f9a01"
    name                  = "Storgata 1"
    address               = "Storgata 1"
    postal_code           = "0155"
    postal_area           = "Oslo"
    country               = "Norway"
    matrikkelnummer       = "0301-208/101"
    value_estimate        = 85000000
} | ConvertTo-Json

Invoke-RestMethod -Method Post `
    -Uri "https://api.telescope.eco/external/properties/" `
    -Headers @{ "X-API-Key" = $env:TELESCOPE_API_KEY } `
    -ContentType "application/json" `
    -Body $body

The response is the full property, in the same format as GET /external/properties/{id}/, with status 201 Created for a new property or 200 OK for an updated one.

Request fields ​

FieldRequiredTypeDescription
portfolio_idYesUUIDThe portfolio to add the property to. Must belong to your organization. Ignored when the property already exists, see below.
countryYestextMust be Norway.
matrikkelnummerYestextThe plot's Norwegian cadastral identifier, like 0301-208/101/0/0. Used to find the plot. See Matrikkelnummer.
internal_reference_idNo, but recommendedtext, max 255Your own ID for the property. If a property with this reference already exists, it is updated instead of creating a new one.
nameNotext, max 255Display name in Telescope. Defaults to the address, or the matrikkelnummer without one.
addressNotext, max 255Street address, like Storgata 1. Stored for display only; it is never used to find the plot.
postal_codeNotext, max 255Postal code of the address.
postal_areaNotext, max 255Postal area or city of the address.
value_estimateNointeger or nullEstimated value in NOK, from 0 to 999,999,999,999.

Send JSON with Content-Type: application/json. Unknown fields are ignored.

Matrikkelnummer ​

The matrikkelnummer is how Telescope finds the property's plot, and with it the geometry that every analysis runs on. Write it as municipality-gnr/bnr/fnr/snr:

InputStored as
0301-208/101/0/00301-208/101/0/0
0301-208/1010301-208/101/0/0

Shorter forms are accepted and always stored in full. If the value isn't a matrikkelnummer at all, such as an address, the request fails with invalid_matrikkelnummer. If it is valid but no plot is found, it fails with property_geometry_not_found.

Long numbers

Plots with a gårdsnummer or bruksnummer longer than four digits, or a festenummer longer than three, can't be looked up yet and return property_geometry_not_found.

What happens after you create a property ​

  1. Telescope validates the request and looks up the plot from the matrikkelnummer. This happens before anything is saved, so a failed lookup creates nothing.
  2. The property is saved and returned right away. hazards and biodiversity are still empty, and buildings and energy_certificates usually are too.
  3. In the background, Telescope runs the property's analyses and fetches its buildings and energy certificates.
  4. Fetch the property again later with GET /external/properties/{id}/ to read the results as they arrive.

Create or update ​

internal_reference_id makes the endpoint safe to call repeatedly:

SituationResult
No internal_reference_id sentA new property is always created. Retrying a failed request can create duplicates.
No property has this reference yetA new property is created in portfolio_id. 201 Created.
One property has this referenceThat property is updated in place. 200 OK.
Several properties share this reference400 with code ambiguous_internal_reference_id. Fix the duplicates in the app first.

When a property is updated:

  • It stays in its current portfolio. portfolio_id is still required and validated, but the property isn't moved. Move it in the app.
  • Fields you leave out keep their current values. Fields you send replace them.
  • Analyses rerun only if the plot changed, that is when the new matrikkelnummer leads to a different geometry.
  • Buildings and energy certificates are fetched again only if the matrikkelnummer changed. The ones fetched for the old plot are removed, and ones added by hand in the app are kept. The new plot's buildings are only fetched if no buildings are left, and its energy certificates only if no certificates are left. So a building or certificate added by hand means the new ones of that kind aren't fetched.

Requests with the same reference are handled one at a time, so two systems sending the same property at once can't create two copies.

TIP

Always send internal_reference_id, using the ID from your source system. Then your integration can resend everything on every run without creating duplicates.

Bulk import from a CSV file ​

The endpoint creates one property per request. To import many, loop over your rows. Thanks to internal_reference_id, you can rerun the script after fixing failed rows.

python
import csv

import requests

session = requests.Session()
session.headers["X-API-Key"] = "your-secret"
PORTFOLIO_ID = "b2a4c7e0-1d2f-4f39-8e2a-5c6d7e8f9a01"

with open("properties.csv", newline="", encoding="utf-8") as file:
    for row in csv.DictReader(file):
        response = session.post(
            "https://api.telescope.eco/external/properties/",
            json={
                "internal_reference_id": row["reference"],
                "portfolio_id": PORTFOLIO_ID,
                "address": row["address"],
                "postal_code": row["postal_code"],
                "postal_area": row["postal_area"],
                "country": "Norway",
                "matrikkelnummer": row["matrikkelnummer"],
            },
            timeout=60,
        )
        if response.ok:
            print(f"{row['reference']}: {response.status_code}")
        else:
            print(f"{row['reference']}: failed, {response.json()}")

Errors ​

Validation errors return 400 with an entry per field. For example, a matrikkelnummer without a plot:

json
{
  "matrikkelnummer": {
    "detail": "Couldn't find a plot for this matrikkelnummer.",
    "code": "property_geometry_not_found"
  }
}
StatusFieldCodeMeaning
400matrikkelnummerrequired, blankThe matrikkelnummer is missing or empty.
400matrikkelnummerinvalid_matrikkelnummerThe value isn't a Norwegian matrikkelnummer.
400matrikkelnummerproperty_geometry_not_foundNo plot was found for it.
400countryinvalid_choiceThe country isn't Norway.
400portfolio_iddoes_not_existNo portfolio with this ID in your organization.
400internal_reference_idambiguous_internal_reference_idSeveral properties share this reference.
400value_estimatemin_value, max_value, invalidThe value is negative, too large or not a whole number.
401authentication_failedThe API key is missing or invalid.
403external_api_create_not_allowedCreating isn't enabled for your organization.

See Errors for the general error format.