Skip to content

Queries

Query endpoints are designed for bulk workflows such as:

  • Campaign exports
  • Lead generation
  • CRM enrichment
  • Regional analytics pipelines
  • Data downloads / batch processing

Compared to viewport (/bbox/*) endpoints, query endpoints are optimized for large-scale extraction and support:

  • Region selectors (exactly one required)
  • Mongo-like filters
  • Field projection (options.select)
  • Cursor-based pagination via options.after_building_id (recommended)

Authentication: All requests require subscription_key as a query parameter.
See authentication for details.


API Base URL

https://ua-api-solar-lake-enterprise.azurewebsites.net

POST /query/buildings — Extract buildings by region and filters

This endpoint returns buildings matching a region selector and optional filters.

It is the recommended endpoint for bulk extraction workflows.

Endpoint

POST /query/buildings

Authentication via:

?subscription_key=YOUR_KEY

Request body structure

{
  "region": { ... },      // required: exactly one selector
  "filter": { ... },      // optional
  "options": { ... }      // optional (projection + paging)
}

region (required)

Exactly one region selector must be provided.

Supported selectors:

Selector Description Value type
postcode_in List of German postcodes array[string]
ags_in List of municipality AGS codes array[string]
h3_4_inh3_10_in List of H3 IDs at a fixed resolution array[string]

Notes:

  • H3 IDs may be provided as decimal or hex.
  • Choose the selector that best matches your workflow:
    • Campaign by postcode → postcode_in
    • Municipality export → ags_in
    • Grid/cell workflows → h3_*_in (fixed resolution)

filter (optional)

Filters use a Mongo-like syntax.

Supported operators:

  • Equality: $eq, $ne (shorthand { "pv": false } is allowed)
  • Comparisons: $gt, $gte, $lt, $lte
  • Set membership: $in, $nin (value must be a list)

Examples:

{ "pv": false }
{ "roof_area": { "$gte": 100 } }
{
  "roof_area": { "$gt": 80 },
  "building_type": { "$in": ["single-family house", "terraced house"] }
}

Only allowlisted, documented fields are filterable. Invalid fields/operators return 422.


options (optional)

options controls projection and pagination.

Field Type Description
select array[string] Fields to include in the response (projection)
skip integer Offset pagination (allowed, but not recommended for large exports)
limit integer Page size (default 5000, max may apply)
after_building_id string Cursor paging token (recommended)

Projection is strongly recommended for bulk exports:

  • It reduces payload size
  • It speeds up queries
  • It avoids unnecessary geometry / roof arrays unless needed

The API always includes building_id automatically, even if not listed in select.


Response structure

{
  "returned": 5000,
  "next_after_building_id": "01c02e568d94065d29c7fd9e",
  "items": [
    { "building_id": "..." },
    { "building_id": "..." }
  ]
}
  • returned = number of items in this page
  • items = list of buildings (projection-friendly; always includes building_id)
  • next_after_building_id:
    • present if another page is available
    • omit / null when you reached the end

Examples

1) Postcode campaign export (with filter + projection)

curl -X POST "https://ua-api-solar-lake-enterprise.azurewebsites.net/query/buildings?subscription_key=YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "region": { "postcode_in": ["90461", "90471"] },
        "filter": {
          "pv": false,
          "roof_area": { "$gte": 80 },
          "building_type": { "$in": ["single-family house", "terraced house"] }
        },
        "options": {
          "select": ["building_id", "postcode", "roof_area", "pv", "sales_opportunity_score"],
          "limit": 5000
        }
      }'

2) Municipality export (AGS selector)

{
  "region": { "ags_in": ["09564000"] },
  "options": {
    "select": ["building_id", "ags", "postcode", "roof_area", "pv"],
    "limit": 5000
  }
}

3) H3-based export at a fixed resolution

{
  "region": {
    "h3_7_in": ["608532992465305599", "608532995971743743"]
  },
  "filter": {
    "pv": false,
    "roof_area": { "$gte": 80 }
  },
  "options": {
    "select": ["building_id", "h3_7", "postcode", "roof_area", "pv"],
    "limit": 5000
  }
}

Cursor pagination avoids large skip offsets and is the preferred method for exporting many records.

First page

{
  "region": { "postcode_in": ["90461"] },
  "filter": { "pv": false },
  "options": {
    "select": ["building_id", "postcode", "roof_area"],
    "limit": 5000
  }
}

Example response:

{
  "returned": 5000,
  "next_after_building_id": "41d36aa651cea1ea53641e6b",
  "items": [...]
}

Next page

Use the cursor from the previous response:

{
  "region": { "postcode_in": ["90461"] },
  "filter": { "pv": false },
  "options": {
    "select": ["building_id", "postcode", "roof_area"],
    "limit": 5000,
    "after_building_id": "41d36aa651cea1ea53641e6b"
  }
}

Continue until:

  • next_after_building_id is missing, or
  • returned becomes 0

Practical guidance & limits

Keep region selectors reasonable in size

Very large region lists may be rejected or slowed down by server-side safeguards.

If you need to export a huge area:

  • Split the request by postcode batches (e.g., 1–5 at a time)
  • Or use H3 selectors at a coarser resolution to reduce partition fan-out

Always use projection for bulk exports

Avoid requesting full building documents unless you truly need:

  • Roof segment arrays (roof_*)
  • Detailed economics fields
  • Geometry for every record

A typical campaign export often needs only:

  • building_id, postcode
  • roof_area, pv, sales_opportunity_score
  • maybe a few other fields

Errors

422 — Validation Error

Common causes:

  • Missing region
  • More than one selector provided in region
  • Invalid filter operator / filter type
  • Non-allowlisted filter field
  • Invalid after_building_id format

403 — Access Denied

Missing or invalid subscription_key