MENU navbar-image

Introduction

API for accessing Swiss building registry (GWR) data, electricity tariffs from grid operators (VNB), and related infrastructure information.

This documentation aims to provide all the information you need to work with our API.

<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>

Authenticating requests

To authenticate requests, include an Authorization header with the value "Bearer {YOUR_API_TOKEN}".

All authenticated endpoints are marked with a requires authentication badge in the documentation below.

You can retrieve your API token by logging into your account and navigating to Settings β†’ API Tokens. Use Laravel Sanctum Bearer tokens for authentication.

Buildings

List buildings by municipality (BFS)

requires authentication

Returns a paginated list of GWR buildings for a given municipality (BFS number). Code label resolution is disabled by default for performance; enable with resolve_codes=1.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings?municipality=261&per_page=200&lang=de&resolve_codes=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"per_page\": 17,
    \"lang\": \"fr\",
    \"resolve_codes\": false
}"
const url = new URL(
    "http://localhost:8000/api/buildings"
);

const params = {
    "municipality": "261",
    "per_page": "200",
    "lang": "de",
    "resolve_codes": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "per_page": 17,
    "lang": "fr",
    "resolve_codes": false
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   string     

integer BFS municipality number. Example: 261

per_page   integer  optional    

Number of items per page. Min: 1, Max: 1000. Default: 200. Example: 200

lang   string  optional    

Language for code labels when resolve_codes=1. Options: de, fr, it. Default: de. Example: de

resolve_codes   boolean  optional    

Whether to resolve code labels. Default: 0. Example: true

Body Parameters

municipality   number     

Example: 4326.41688

per_page   integer  optional    

Must be at least 1. Must not be greater than 1000. Example: 17

lang   string  optional    

Example: fr

Must be one of:
  • de
  • fr
  • it
resolve_codes   boolean  optional    

Example: false

Get lightweight map data for buildings by municipality

requires authentication

Returns minimal building data optimized for map visualizations. Only includes buildings with valid coordinates (latitude/longitude).

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/map-data?municipality=261&per_page=200&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"per_page\": 17,
    \"page\": 35
}"
const url = new URL(
    "http://localhost:8000/api/buildings/map-data"
);

const params = {
    "municipality": "261",
    "per_page": "200",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "per_page": 17,
    "page": 35
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/map-data

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   string     

integer BFS municipality number. Example: 261

per_page   integer  optional    

Number of items per page. Min: 1, Max: 1000. Default: 200. Example: 200

page   integer  optional    

Page number. Min: 1. Default: 1. Example: 1

Body Parameters

municipality   number     

Example: 4326.41688

per_page   integer  optional    

Must be at least 1. Must not be greater than 1000. Example: 17

page   integer  optional    

Must be at least 1. Example: 35

Get building information by EGID

requires authentication

Returns detailed information about a building from the GWR (GebΓ€ude- und Wohnungsregister) database. All code fields are automatically resolved to their human-readable labels in the specified language.

If address or solar potential data is missing, it will be automatically synchronized before returning the response.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/1234567890?lang=de&sync=" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/1234567890"
);

const params = {
    "lang": "de",
    "sync": "0",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "egid": "1234567890",
    "gdekt": "ZH",
    "ggdenr": "261",
    "ggdename": "Zürich",
    "egrid": "2680000.0,1240000.0",
    "gbez": "Wohnhaus",
    "gkode": "01",
    "gkode_label": "Wohngebäude",
    "gstat": "01",
    "gstat_label": "Bestehend",
    "gkat": "01",
    "gkat_label": "Einfamilienhaus",
    "gbauj": 1990,
    "garea": 150.5,
    "gvol": 450,
    "address": {
        "street": "Hauptstrasse 45",
        "postal_code": "6260",
        "city": "Reiden"
    },
    "solar_roofs": [
        {
            "attributes": {
                "building_id": "229760",
                "suitability": "high"
            },
            "geometry": {
                "rings": [
                    [
                        [
                            2640325.75,
                            1232914.625
                        ]
                    ]
                ]
            }
        }
    ],
    "solar_facades": [
        {
            "attributes": {
                "building_id": "229760",
                "suitability": "medium"
            },
            "geometry": {
                "rings": [
                    [
                        [
                            2640325.75,
                            1232914.625
                        ]
                    ]
                ]
            }
        }
    ],
    "created_at": "2025-01-01T00:00:00+00:00",
    "updated_at": "2025-01-01T00:00:00+00:00"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Building not found"
}
 

Request      

GET api/buildings/{egid}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

string The building EGID (EidgenΓΆssische GebΓ€udeidentifikator). Example: 1234567890

Query Parameters

lang   string  optional    

The language for code labels. Options: de (German), fr (French), it (Italian). Default: de. Example: de

sync   boolean  optional    

Whether to sync missing address/solar data from external APIs (OSB, GeoAdmin). Default: 0 (disabled). Set to 1 to enable on-demand sync. When disabled, returns only locally stored data. Example: false

EVU Tariffs

List all grid operators

requires authentication

Returns a paginated list of all active grid operators (Verteilnetzbetreiber) with their tariff URL status and information about the latest successful tariff submission.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/evu-tariffs/operators?per_page=50&status=found&search=EKZ" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/evu-tariffs/operators"
);

const params = {
    "per_page": "50",
    "status": "found",
    "search": "EKZ",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "ch_uid": "CHE-108.954.688",
            "name": "Elektrizitätswerke des Kantons Zürich (EKZ)",
            "website_url": "www.ekz.ch",
            "tariff_url": "https://ekz.ch/api/tariffs.json",
            "tariff_url_status": "found",
            "tariff_url_verified_at": "2026-01-15T10:00:00+00:00",
            "is_active": true,
            "latest_submission": {
                "fetched_at": "2026-01-15T10:00:00+00:00",
                "tariff_year": 2026,
                "tariff_count": 12
            },
            "elcom_synced_at": "2026-01-01T00:00:00+00:00"
        }
    ],
    "links": {
        "first": "https://example.com/api/evu-tariffs/operators?page=1",
        "last": "https://example.com/api/evu-tariffs/operators?page=10",
        "prev": null,
        "next": "https://example.com/api/evu-tariffs/operators?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 10,
        "per_page": 50,
        "to": 50,
        "total": 500
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Request      

GET api/evu-tariffs/operators

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

per_page   integer  optional    

Number of items per page. Min: 1, Max: 100. Default: 50. Example: 50

status   string  optional    

Filter by tariff URL status. Options: pending, found, not_found, manual, invalid. Example: found

search   string  optional    

Search by operator name or CH UID. Example: EKZ

Get a single grid operator

requires authentication

Returns detailed information about a specific grid operator (Verteilnetzbetreiber) by its CH UID, including the latest submission status and tariff URL information.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "ch_uid": "CHE-108.954.688",
    "name": "Elektrizitätswerke des Kantons Zürich (EKZ)",
    "website_url": "www.ekz.ch",
    "tariff_url": "https://ekz.ch/api/tariffs.json",
    "tariff_url_status": "found",
    "tariff_url_verified_at": "2026-01-15T10:00:00+00:00",
    "is_active": true,
    "latest_submission": {
        "fetched_at": "2026-01-15T10:00:00+00:00",
        "tariff_year": 2026,
        "tariff_count": 12
    },
    "elcom_synced_at": "2026-01-01T00:00:00+00:00"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "error": "Grid operator not found",
    "code": "operator_not_found"
}
 

Request      

GET api/evu-tariffs/operators/{chUid}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

chUid   string     

string The CH UID (Unternehmens-Identifikationsnummer) of the grid operator. Example: CHE-108.954.688

Get tariffs for a grid operator

requires authentication

Returns the cached tariffs for a specific grid operator in the standard format according to StromVV Art. 7b. The response includes all tariff types:

Tariff forms can be:

Example request:
curl --request GET \
    --get "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688/tariffs?year=2026" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688/tariffs"
);

const params = {
    "year": "2026",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "dsoName": "Elektrizitätswerke des Kantons Zürich (EKZ)",
    "dsoNumber": 10895468800,
    "tariffs": [
        {
            "customerVoltageLevel": 7,
            "tariffName": "Haushalt Standard",
            "tariffType": "electricity",
            "tariffForm": "multilevel",
            "startDate": "2026-01-01",
            "endDate": "2026-12-31",
            "comment": null,
            "customerType": "household",
            "prices": {
                "multilevel": {
                    "levels": [
                        {
                            "name": "HT",
                            "price": 0.22,
                            "unit": "CHF/kWh"
                        },
                        {
                            "name": "NT",
                            "price": 0.18,
                            "unit": "CHF/kWh"
                        }
                    ]
                }
            }
        },
        {
            "customerVoltageLevel": 7,
            "tariffName": "Netznutzung Haushalt",
            "tariffType": "grid",
            "tariffForm": "constant",
            "startDate": "2026-01-01",
            "endDate": "2026-12-31",
            "comment": null,
            "customerType": "household",
            "prices": {
                "constant": {
                    "price": 0.08,
                    "unit": "CHF/kWh"
                }
            }
        }
    ],
    "_meta": {
        "ch_uid": "CHE-108.954.688",
        "fetched_at": "2026-01-15T10:00:00+00:00",
        "tariff_year": 2026,
        "source_url": "https://ekz.ch/api/tariffs.json"
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404, Operator not found):


{
    "error": "Grid operator not found",
    "code": "operator_not_found"
}
 

Example response (404, No tariffs available):


{
    "error": "No tariffs found for this operator",
    "code": "tariffs_not_found",
    "operator": "CHE-108.954.688",
    "year": 2026
}
 

Request      

GET api/evu-tariffs/operators/{chUid}/tariffs

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

chUid   string     

string The CH UID of the grid operator. Example: CHE-108.954.688

Query Parameters

year   integer  optional    

Filter by tariff year. Default: current year. Example: 2026

Proxy dynamic tariff data

requires authentication

Proxies requests to the dynamic tariff URL of a grid operator to retrieve real-time pricing data. This endpoint is only available for operators that offer dynamic tariffs (tariffForm: "dynamic").

The response format depends on the grid operator's implementation but typically includes current and/or upcoming electricity prices with timestamps.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688/dynamic" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/evu-tariffs/operators/CHE-108.954.688/dynamic"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "timestamp": "2026-01-15T14:00:00+01:00",
    "prices": [
        {
            "start": "2026-01-15T14:00:00+01:00",
            "end": "2026-01-15T15:00:00+01:00",
            "price": 0.185,
            "unit": "CHF/kWh"
        },
        {
            "start": "2026-01-15T15:00:00+01:00",
            "end": "2026-01-15T16:00:00+01:00",
            "price": 0.215,
            "unit": "CHF/kWh"
        }
    ]
}
 

Example response (400, No dynamic tariff available):


{
    "error": "Operator does not have a dynamic tariff URL configured",
    "code": "proxy_error"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "error": "Grid operator not found",
    "code": "operator_not_found"
}
 

Example response (502, Upstream error):


{
    "error": "Failed to fetch dynamic tariff data from operator",
    "code": "proxy_error"
}
 

Request      

GET api/evu-tariffs/operators/{chUid}/dynamic

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

chUid   string     

string The CH UID of the grid operator. Example: CHE-108.954.688

BDEW Profiles

List all BDEW profile codes

requires authentication

Returns a list of all available BDEW standard load profile codes (e.g., H0, G0-G6, L0-L2). Each profile code represents a category of electricity consumption patterns.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/bdew-profiles" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/bdew-profiles"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "code": "H0",
            "name": "Household",
            "category": "household",
            "description": "Standard household profile",
            "metadata": {}
        },
        {
            "code": "G25",
            "name": "Commercial",
            "category": "commercial",
            "description": "Commercial profile",
            "metadata": {}
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Request      

GET api/bdew-profiles

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Get all variations for a BDEW profile code

requires authentication

Returns all 9 variations (3 seasons Γ— 3 day types) for a specific BDEW profile code. Each variation contains 96 normalized values representing 15-minute intervals for a day.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/bdew-profiles/H0" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/bdew-profiles/H0"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "code": "H0",
  "name": "Household",
  "category": "household",
  "variations": [
    {
      "profile_code": "H0",
      "season": "winter",
      "day_type": "weekday",
      "values": [0.0104, 0.0099, ...],
      "is_dynamized": true,
      "description": null,
      "metadata": {}
    },
    {
      "profile_code": "H0",
      "season": "winter",
      "day_type": "saturday",
      "values": [0.0104, 0.0099, ...],
      "is_dynamized": true,
      "description": null,
      "metadata": {}
    }
  ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Profile code not found"
}
 

Request      

GET api/bdew-profiles/{code}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

code   string     

string The BDEW profile code (e.g., H0, G25, L25). Example: H0

Get daily template for a BDEW profile code by date

requires authentication

Returns the correct BDEW load profile template for a specific date. The season (winter/summer/transition) and day type (weekday/saturday/sunday) are automatically determined from the date.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/bdew-profiles/H0/daily?date=2025-01-15" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"date\": \"2026-02-05\"
}"
const url = new URL(
    "http://localhost:8000/api/bdew-profiles/H0/daily"
);

const params = {
    "date": "2025-01-15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "date": "2026-02-05"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
  "code": "H0",
  "date": "2025-01-15",
  "season": "winter",
  "day_type": "wednesday",
  "values": [0.0104, 0.0099, ...],
  "is_dynamized": true,
  "description": null,
  "metadata": {}
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Profile code not found"
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "date": [
            "The date field is required."
        ]
    }
}
 

Request      

GET api/bdew-profiles/{code}/daily

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

code   string     

string The BDEW profile code (e.g., H0, G25, L25). Example: H0

Query Parameters

date   string     

string The date in YYYY-MM-DD format. Example: 2025-01-15

Body Parameters

date   string     

Must be a valid date in the format Y-m-d. Example: 2026-02-05

Get yearly profile for a BDEW profile code

requires authentication

Returns a complete year's worth of BDEW load profile data with all 365/366 days. Each day includes 96 quarter-hour values, with dynamization applied where applicable. Holidays are treated as Sundays, and Dec 24/31 use Saturday templates.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/bdew-profiles/H25/year?year=2025" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
const url = new URL(
    "http://localhost:8000/api/bdew-profiles/H25/year"
);

const params = {
    "year": "2025",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
  "code": "H25",
  "year": 2025,
  "is_dynamized": true,
  "total_kwh": 1000000.00,
  "days": [
    {
      "date": "2025-01-01",
      "day_of_year": 1,
      "month": 1,
      "day_type": "sunday",
      "is_holiday": true,
      "holiday_name": "Neujahr",
      "dynamization_factor": 1.2421,
      "values": [22.15, 20.81, 19.76, ...]
    }
  ],
  "meta": {
    "total_days": 365,
    "is_leap_year": false,
    "generated_at": "2025-01-15T10:30:00Z"
  }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Profile code not found"
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "year": [
            "The year field is required."
        ]
    }
}
 

Request      

GET api/bdew-profiles/{code}/year

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

code   string     

string The BDEW profile code (e.g., H25, G25, L25). Example: H25

Query Parameters

year   string     

integer The year for the profile (2020-2035). Example: 2025

Body Parameters

year   string  optional    

List available years for a profile code

requires authentication

Returns the years that have pre-generated yearly profiles available.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/bdew-profiles/H25/years" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/bdew-profiles/H25/years"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):


{
    "code": "H25",
    "available_years": [
        2024,
        2025,
        2026
    ],
    "supported_range": {
        "min": 2020,
        "max": 2035
    }
}
 

Example response (404):


{
    "message": "Profile code not found"
}
 

Request      

GET api/bdew-profiles/{code}/years

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

code   string     

string The BDEW profile code (e.g., H25, G25). Example: H25

Transformer Stations

List transformer stations

requires authentication

Returns a list of transformer stations (Trafostationen) with various filtering options. You can filter by municipality (BFS number), postal code, status, or search within a radius using coordinates. Coordinates are taken directly from gwr_buildings.GKODE (Easting) and gwr_buildings.GKODN (Northing). The egrid field contains the raw EGRID value from gwr_buildings.EGRID.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/transformer-stations?municipality=261&postal_code=8001&status=confirmed&lat=47.3769&lng=8.5417&radius=1000&east=2680000&north=1240000" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"postal_code\": 4326.41688,
    \"lat\": -90,
    \"lng\": -180,
    \"east\": 4326.41688,
    \"north\": 4326.41688,
    \"radius\": 17,
    \"status\": \"confirmed\"
}"
const url = new URL(
    "http://localhost:8000/api/transformer-stations"
);

const params = {
    "municipality": "261",
    "postal_code": "8001",
    "status": "confirmed",
    "lat": "47.3769",
    "lng": "8.5417",
    "radius": "1000",
    "east": "2680000",
    "north": "1240000",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "postal_code": 4326.41688,
    "lat": -90,
    "lng": -180,
    "east": 4326.41688,
    "north": 4326.41688,
    "radius": 17,
    "status": "confirmed"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "egid": "1234567890",
            "status": "confirmed",
            "building": {
                "egid": "1234567890",
                "gbez": "Trafo Station 1",
                "ggdenr": "261",
                "ggdename": "Zürich",
                "egrid": "2680000.0,1240000.0"
            },
            "address": {
                "street": "Hauptstrasse 45",
                "postal_code": "6260",
                "city": "Reiden"
            },
            "solar_roofs": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "high"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "solar_facades": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "medium"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "coordinates": {
                "east": 2680000,
                "north": 1240000
            },
            "coordinates_wgs84": {
                "lat": 47.3769,
                "lng": 8.5417
            },
            "created_at": "2025-01-01T00:00:00+00:00",
            "updated_at": "2025-01-01T00:00:00+00:00"
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "lat": [
            "The lat field is required when lng is present."
        ]
    }
}
 

Request      

GET api/transformer-stations

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   integer  optional    

Filter by municipality BFS number (Gemeindenummer). Example: 261

postal_code   integer  optional    

Filter by postal code (PLZ). Example: 8001

status   string  optional    

Filter by status. Options: candidate, confirmed. Example: confirmed

lat   number  optional    

Latitude (WGS84) for radius search. Required together with lng and radius. Example: 47.3769

lng   number  optional    

Longitude (WGS84) for radius search. Required together with lat and radius. Example: 8.5417

radius   number  optional    

Search radius in meters (WGS84). Required together with lat and lng. Min: 1, Max: 50000. Example: 1000

east   number  optional    

Easting (CH1903+) for radius search. Required together with north and radius. Example: 2680000

north   number  optional    

Northing (CH1903+) for radius search. Required together with east and radius. Example: 1240000

Body Parameters

municipality   number  optional    

Example: 4326.41688

postal_code   number  optional    

Example: 4326.41688

lat   number  optional    

This field is required when lng or radius is present. Must be between -90 and 90. Example: -90

lng   number  optional    

This field is required when lat or radius is present. Must be between -180 and 180. Example: -180

east   number  optional    

This field is required when north or radius is present. Example: 4326.41688

north   number  optional    

This field is required when east or radius is present. Example: 4326.41688

radius   number  optional    

Must be at least 1. Must not be greater than 50000. Example: 17

status   string  optional    

Example: confirmed

Must be one of:
  • candidate
  • confirmed

Educational Institutions

List educational institutions

requires authentication

Returns a list of educational institutions (SchulhΓ€user, KindergΓ€rten, etc.) with various filtering options. You can filter by municipality (BFS number), postal code, status, or search within a radius using coordinates. Coordinates are taken directly from gwr_buildings.GKODE (Easting) and gwr_buildings.GKODN (Northing).

Example request:
curl --request GET \
    --get "http://localhost:8000/api/educational-institutions?municipality=261&postal_code=8001&status=confirmed&lat=47.3769&lng=8.5417&radius=1000&east=2680000&north=1240000" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"postal_code\": 4326.41688,
    \"lat\": -90,
    \"lng\": -180,
    \"east\": 4326.41688,
    \"north\": 4326.41688,
    \"radius\": 17,
    \"status\": \"confirmed\"
}"
const url = new URL(
    "http://localhost:8000/api/educational-institutions"
);

const params = {
    "municipality": "261",
    "postal_code": "8001",
    "status": "confirmed",
    "lat": "47.3769",
    "lng": "8.5417",
    "radius": "1000",
    "east": "2680000",
    "north": "1240000",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "postal_code": 4326.41688,
    "lat": -90,
    "lng": -180,
    "east": 4326.41688,
    "north": 4326.41688,
    "radius": 17,
    "status": "confirmed"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "egid": "1234567890",
            "status": "confirmed",
            "building": {
                "egid": "1234567890",
                "gbez": "Schulhaus Muster",
                "ggdenr": "261",
                "ggdename": "Zürich",
                "egrid": "2680000.0,1240000.0"
            },
            "address": {
                "street": "Hauptstrasse 45",
                "postal_code": "6260",
                "city": "Reiden"
            },
            "solar_roofs": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "high"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "solar_facades": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "medium"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "coordinates": {
                "east": 2680000,
                "north": 1240000
            },
            "coordinates_wgs84": {
                "lat": 47.3769,
                "lng": 8.5417
            },
            "created_at": "2025-01-01T00:00:00+00:00",
            "updated_at": "2025-01-01T00:00:00+00:00"
        }
    ]
}
 

Request      

GET api/educational-institutions

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   integer  optional    

Filter by municipality BFS number (Gemeindenummer). Example: 261

postal_code   integer  optional    

Filter by postal code (PLZ). Example: 8001

status   string  optional    

Filter by status. Options: candidate, confirmed. Example: confirmed

lat   number  optional    

Latitude (WGS84) for radius search. Required together with lng and radius. Example: 47.3769

lng   number  optional    

Longitude (WGS84) for radius search. Required together with lat and radius. Example: 8.5417

radius   number  optional    

Search radius in meters (WGS84). Required together with lat and lng. Min: 1, Max: 50000. Example: 1000

east   number  optional    

Easting (CH1903+) for radius search. Required together with north and radius. Example: 2680000

north   number  optional    

Northing (CH1903+) for radius search. Required together with east and radius. Example: 1240000

Body Parameters

municipality   number  optional    

Example: 4326.41688

postal_code   number  optional    

Example: 4326.41688

lat   number  optional    

This field is required when lng or radius is present. Must be between -90 and 90. Example: -90

lng   number  optional    

This field is required when lat or radius is present. Must be between -180 and 180. Example: -180

east   number  optional    

This field is required when north or radius is present. Example: 4326.41688

north   number  optional    

This field is required when east or radius is present. Example: 4326.41688

radius   number  optional    

Must be at least 1. Must not be greater than 50000. Example: 17

status   string  optional    

Example: confirmed

Must be one of:
  • candidate
  • confirmed

Municipal Properties

List municipal properties

requires authentication

Returns a list of municipal properties (WerkhΓΆfe, Gemeindeverwaltung, Gemeindehaus, Feuerwehrmagazin, etc.) with various filtering options. You can filter by municipality (BFS number), postal code, status, or search within a radius using coordinates. Coordinates are taken directly from gwr_buildings.GKODE (Easting) and gwr_buildings.GKODN (Northing).

Example request:
curl --request GET \
    --get "http://localhost:8000/api/municipal-properties?municipality=261&postal_code=8001&status=confirmed&lat=47.3769&lng=8.5417&radius=1000&east=2680000&north=1240000" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"postal_code\": 4326.41688,
    \"lat\": -90,
    \"lng\": -180,
    \"east\": 4326.41688,
    \"north\": 4326.41688,
    \"radius\": 17,
    \"status\": \"candidate\"
}"
const url = new URL(
    "http://localhost:8000/api/municipal-properties"
);

const params = {
    "municipality": "261",
    "postal_code": "8001",
    "status": "confirmed",
    "lat": "47.3769",
    "lng": "8.5417",
    "radius": "1000",
    "east": "2680000",
    "north": "1240000",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "postal_code": 4326.41688,
    "lat": -90,
    "lng": -180,
    "east": 4326.41688,
    "north": 4326.41688,
    "radius": 17,
    "status": "candidate"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "egid": "1234567890",
            "status": "confirmed",
            "building": {
                "egid": "1234567890",
                "gbez": "Gemeindehaus",
                "ggdenr": "261",
                "ggdename": "Zürich",
                "egrid": "2680000.0,1240000.0"
            },
            "address": {
                "street": "Hauptstrasse 45",
                "postal_code": "6260",
                "city": "Reiden"
            },
            "solar_roofs": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "high"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "solar_facades": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "medium"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "coordinates": {
                "east": 2680000,
                "north": 1240000
            },
            "coordinates_wgs84": {
                "lat": 47.3769,
                "lng": 8.5417
            },
            "created_at": "2025-01-01T00:00:00+00:00",
            "updated_at": "2025-01-01T00:00:00+00:00"
        }
    ]
}
 

Request      

GET api/municipal-properties

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   integer  optional    

Filter by municipality BFS number (Gemeindenummer). Example: 261

postal_code   integer  optional    

Filter by postal code (PLZ). Example: 8001

status   string  optional    

Filter by status. Options: candidate, confirmed. Example: confirmed

lat   number  optional    

Latitude (WGS84) for radius search. Required together with lng and radius. Example: 47.3769

lng   number  optional    

Longitude (WGS84) for radius search. Required together with lat and radius. Example: 8.5417

radius   number  optional    

Search radius in meters (WGS84). Required together with lat and lng. Min: 1, Max: 50000. Example: 1000

east   number  optional    

Easting (CH1903+) for radius search. Required together with north and radius. Example: 2680000

north   number  optional    

Northing (CH1903+) for radius search. Required together with east and radius. Example: 1240000

Body Parameters

municipality   number  optional    

Example: 4326.41688

postal_code   number  optional    

Example: 4326.41688

lat   number  optional    

This field is required when lng or radius is present. Must be between -90 and 90. Example: -90

lng   number  optional    

This field is required when lat or radius is present. Must be between -180 and 180. Example: -180

east   number  optional    

This field is required when north or radius is present. Example: 4326.41688

north   number  optional    

This field is required when east or radius is present. Example: 4326.41688

radius   number  optional    

Must be at least 1. Must not be greater than 50000. Example: 17

status   string  optional    

Example: candidate

Must be one of:
  • candidate
  • confirmed

Water Supply Buildings

List water supply buildings

requires authentication

Returns a list of water supply buildings (Wasserversorgung) with various filtering options. You can filter by municipality (BFS number), postal code, status, or search within a radius using coordinates. Coordinates are taken directly from gwr_buildings.GKODE (Easting) and gwr_buildings.GKODN (Northing).

Example request:
curl --request GET \
    --get "http://localhost:8000/api/water-supply-buildings?municipality=261&postal_code=8001&status=confirmed&lat=47.3769&lng=8.5417&radius=1000&east=2680000&north=1240000" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"municipality\": 4326.41688,
    \"postal_code\": 4326.41688,
    \"lat\": -90,
    \"lng\": -180,
    \"east\": 4326.41688,
    \"north\": 4326.41688,
    \"radius\": 17,
    \"status\": \"confirmed\"
}"
const url = new URL(
    "http://localhost:8000/api/water-supply-buildings"
);

const params = {
    "municipality": "261",
    "postal_code": "8001",
    "status": "confirmed",
    "lat": "47.3769",
    "lng": "8.5417",
    "radius": "1000",
    "east": "2680000",
    "north": "1240000",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "municipality": 4326.41688,
    "postal_code": 4326.41688,
    "lat": -90,
    "lng": -180,
    "east": 4326.41688,
    "north": 4326.41688,
    "radius": 17,
    "status": "confirmed"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Example response (200):


{
    "data": [
        {
            "id": 1,
            "egid": "1234567890",
            "status": "confirmed",
            "building": {
                "egid": "1234567890",
                "gbez": "Wasserwerk",
                "ggdenr": "261",
                "ggdename": "Zürich",
                "egrid": "2680000.0,1240000.0"
            },
            "address": {
                "street": "Hauptstrasse 45",
                "postal_code": "6260",
                "city": "Reiden"
            },
            "solar_roofs": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "high"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "solar_facades": [
                {
                    "attributes": {
                        "building_id": "229760",
                        "suitability": "medium"
                    },
                    "geometry": {
                        "rings": [
                            [
                                [
                                    2640325.75,
                                    1232914.625
                                ]
                            ]
                        ]
                    }
                }
            ],
            "coordinates": {
                "east": 2680000,
                "north": 1240000
            },
            "coordinates_wgs84": {
                "lat": 47.3769,
                "lng": 8.5417
            },
            "created_at": "2025-01-01T00:00:00+00:00",
            "updated_at": "2025-01-01T00:00:00+00:00"
        }
    ]
}
 

Request      

GET api/water-supply-buildings

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

municipality   integer  optional    

Filter by municipality BFS number (Gemeindenummer). Example: 261

postal_code   integer  optional    

Filter by postal code (PLZ). Example: 8001

status   string  optional    

Filter by status. Options: candidate, confirmed. Example: confirmed

lat   number  optional    

Latitude (WGS84) for radius search. Required together with lng and radius. Example: 47.3769

lng   number  optional    

Longitude (WGS84) for radius search. Required together with lat and radius. Example: 8.5417

radius   number  optional    

Search radius in meters (WGS84). Required together with lat and lng. Min: 1, Max: 50000. Example: 1000

east   number  optional    

Easting (CH1903+) for radius search. Required together with north and radius. Example: 2680000

north   number  optional    

Northing (CH1903+) for radius search. Required together with east and radius. Example: 1240000

Body Parameters

municipality   number  optional    

Example: 4326.41688

postal_code   number  optional    

Example: 4326.41688

lat   number  optional    

This field is required when lng or radius is present. Must be between -90 and 90. Example: -90

lng   number  optional    

This field is required when lat or radius is present. Must be between -180 and 180. Example: -180

east   number  optional    

This field is required when north or radius is present. Example: 4326.41688

north   number  optional    

This field is required when east or radius is present. Example: 4326.41688

radius   number  optional    

Must be at least 1. Must not be greater than 50000. Example: 17

status   string  optional    

Example: confirmed

Must be one of:
  • candidate
  • confirmed

Endpoints

GET api/user

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/user" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/user"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/user

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

GET api/health

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/health" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/health"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (200):

Show headers
cache-control: no-cache, private
content-type: application/json
x-ratelimit-limit: 600
x-ratelimit-remaining: 599
access-control-allow-origin: *
 

{
    "status": "ok",
    "time": "2026-02-05T20:01:50+00:00"
}
 

Request      

GET api/health

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Proxy all requests to OSB API

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/osb/|{+-0p" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/osb/|{+-0p"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/osb/{path?}

POST api/osb/{path?}

PUT api/osb/{path?}

PATCH api/osb/{path?}

DELETE api/osb/{path?}

OPTIONS api/osb/{path?}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

path   string  optional    

Example: |{+-0p

Proxy all requests to OSB API

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/osb-v2/|{+-0p" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/osb-v2/|{+-0p"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/osb-v2/{path?}

POST api/osb-v2/{path?}

PUT api/osb-v2/{path?}

PATCH api/osb-v2/{path?}

DELETE api/osb-v2/{path?}

OPTIONS api/osb-v2/{path?}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

path   string  optional    

Example: |{+-0p

Electricity Production Plants

Get combined building and electricity production plants data

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/123456/electricity-plants?plant_type=photovoltaic" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/electricity-plants"
);

const params = {
    "plant_type": "photovoltaic",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/{egid}/electricity-plants

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string  optional    

Building EGID. Example: 123456

Query Parameters

plant_type   string  optional    

Optional filter by plant type (photovoltaic, hydro, wind, biomass, etc.). Example: photovoltaic

Get electricity production plants for a building by EGID

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/electricity-plants?egid=123456&plant_type=photovoltaic" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/electricity-plants"
);

const params = {
    "egid": "123456",
    "plant_type": "photovoltaic",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/electricity-plants

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

egid   string  optional    

Building EGID. Example: 123456

plant_type   string  optional    

Optional filter by plant type (photovoltaic, hydro, wind, biomass, etc.). Example: photovoltaic

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/electricity-plants/search?municipality=Z%C3%BCrich&post_code=8001&bfs_number=261&plant_type=photovoltaic" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/electricity-plants/search"
);

const params = {
    "municipality": "ZΓΌrich",
    "post_code": "8001",
    "bfs_number": "261",
    "plant_type": "photovoltaic",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Get specific electricity production plant by XTF-ID

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/electricity-plants/ch.bfe.epa.123456" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/electricity-plants/ch.bfe.epa.123456"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/electricity-plants/{xtf_id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

xtf_id   string  optional    

XTF-ID of the plant. Example: ch.bfe.epa.123456

Get electricity production plant statistics for a municipality

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/municipalities/261/electricity-plant-statistics?plant_type=photovoltaic" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/municipalities/261/electricity-plant-statistics"
);

const params = {
    "plant_type": "photovoltaic",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/municipalities/{bfs_number}/electricity-plant-statistics

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

bfs_number   string  optional    

BFS municipality number. Example: 261

Query Parameters

plant_type   string  optional    

Optional filter by plant type (photovoltaic, hydro, wind, biomass, etc.). Example: photovoltaic

Municipality Enrichment

Enrich all buildings in a municipality.

requires authentication

Triggers a background job that enriches building data including:

Example request:
curl --request POST \
    "http://localhost:8000/api/municipalities/261/enrich" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"force\": false
}"
const url = new URL(
    "http://localhost:8000/api/municipalities/261/enrich"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "force": false
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/municipalities/{bfs_number}/enrich

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

bfs_number   integer     

Municipality BFS number. Example: 261

Body Parameters

force   boolean  optional    

Force re-enrichment even if already enriched. Default: false. Example: false

Get the status of a municipality enrichment batch.

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/municipalities/261/enrichment-status/9d4f8a3c-1b2e-4f5a-8c3d-9a7b6e4f2c1d" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/municipalities/261/enrichment-status/9d4f8a3c-1b2e-4f5a-8c3d-9a7b6e4f2c1d"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/municipalities/{bfs_number}/enrichment-status/{batch_id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

bfs_number   integer     

Municipality BFS number. Example: 261

batch_id   string     

Batch ID from enrich response. Example: 9d4f8a3c-1b2e-4f5a-8c3d-9a7b6e4f2c1d

PV Multi-Roof Configuration

List available PV roof and facade surfaces for a building

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/123456/pv-roofs" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/pv-roofs"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/{egid}/pv-roofs

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

Building EGID. Example: 123456

List all PV multi-roof configurations for a building

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations?status=architecto&per_page=20" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations"
);

const params = {
    "status": "architecto",
    "per_page": "20",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/{egid}/pv-multi-roof-configurations

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

Building EGID. Example: 123456

Query Parameters

status   string  optional    

Filter by status (draft, calculating, completed, failed) Example: architecto

per_page   integer  optional    

Number of items per page. Example: 20

Create or update a PV multi-roof configuration

requires authentication

Example request:
curl --request POST \
    "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"id\": 1,
    \"name\": \"Main PV System\",
    \"description\": \"Eius et animi quos velit et.\",
    \"status\": \"draft\",
    \"surfaces\": [
        \"architecto\"
    ]
}"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "id": 1,
    "name": "Main PV System",
    "description": "Eius et animi quos velit et.",
    "status": "draft",
    "surfaces": [
        "architecto"
    ]
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/buildings/{egid}/pv-multi-roof-configurations

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

Building EGID. Example: 123456

Body Parameters

id   integer  optional    

Configuration ID (for updates). Example: 1

name   string  optional    

Configuration name. Example: Main PV System

description   string  optional    

Configuration description Example: Eius et animi quos velit et.

status   string  optional    

Status (draft, calculating, completed, failed). Example: draft

surfaces   string[]     

Array of surface configurations

surface_id   string     

Example: architecto

enabled   boolean     

Example: false

type   string     

Example: facade

Must be one of:
  • roof
  • facade
tilt_deg   number     

Must be at least 0. Must not be greater than 90. Example: 22

azimuth_deg   number     

Must be at least -180. Must not be greater than 180. Example: 7

area_m2   number     

Must be at least 0.01. Example: 12

peak_power_kwp   number     

Must be at least 0. Example: 77

capacity_kwp_estimate   number     

Must be at least 0. Example: 8

suitability   integer     

Must be at least 1. Must not be greater than 5. Example: 3

technology   string     

Example: pv

Must be one of:
  • pv
annual_yield_kwh   integer  optional    

Must be at least 0. Example: 60

objektid   integer  optional    

Example: 16

building_id   string  optional    

Get a specific PV multi-roof configuration

requires authentication

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations/1?lang=de" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations/1"
);

const params = {
    "lang": "de",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/{egid}/pv-multi-roof-configurations/{configId}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

Building EGID. Example: 123456

configId   string     

Configuration ID. Example: 1

Query Parameters

lang   string  optional    

Language code (de, fr, it). Example: de

Get production profile for a specific configuration and year

requires authentication

Supports both TMY (Typical Meteorological Year) profiles and year-specific profiles. For TMY profiles, the data is mapped to the requested year's calendar.

Example request:
curl --request GET \
    --get "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations/1/profiles/2025" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "http://localhost:8000/api/buildings/123456/pv-multi-roof-configurations/1/profiles/2025"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated.",
    "code": "unauthenticated"
}
 

Request      

GET api/buildings/{egid}/pv-multi-roof-configurations/{configId}/profiles/{year}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

egid   string     

Building EGID. Example: 123456

configId   string     

Configuration ID. Example: 1

year   string     

Year. Example: 2025