Business objects en nodes doorzoeken
De RealityConnect API biedt twee zoekroutes met een verschillend bereik: business object search zoekt binnen een twin naar POI’s, zones, assets en hun metadata, terwijl node search zoekt binnen de nodehiërarchie van uw organisatie (sites, mappen, twins en bestanden). Beide routes zijn experimenteel en kunnen wijzigen.
Endpoints
Section titled “Endpoints”| Methode | Pad | Scope | Doel |
|---|---|---|---|
GET | /v1/twin/{contextId}/search | Basic | Zoek business objects en metadata binnen een twin |
GET | /v1/nodes/search | ReadHierarchy | Zoek de nodehiërarchie van de organisatie |
Business objects doorzoeken
Section titled “Business objects doorzoeken”GET /v1/twin/{contextId}/search doorzoekt POI’s, zones, box assets, metingen en andere business objects binnen één twin (of een van de bijbehorende sites/drafts, geïdentificeerd door contextId), en matcht op naam, gereserveerde velden, asset-metadata en objectspecifieke eigenschappen.
Queryparameters
Section titled “Queryparameters”| Parameter | Type | Opmerkingen |
|---|---|---|
fieldFilters | array van JSON-objecten | Filters op gereserveerde sleutels. Zie hieronder. |
metadataFilters | array van JSON-objecten | Match op asset-metadata-eigenschappen van de twin. Zie hieronder. |
additionalPropertyFilters | array van JSON-objecten | Match op objecttype-specifieke eigenschappen (bijv. het icon-veld van een POI). Zie hieronder. |
page | integer | Positief, standaard 1. |
limit | integer | 1–50, standaard 50. |
searchNameQuery | string | Aparte naamfilter, onafhankelijk van de naam uit fieldFilters. |
nameMatch | exact | contains | Matchmodus voor searchNameQuery. Standaard contains. |
createdById | uuid | Filteren op maker. |
createdBefore / createdAfter | timestamp | Strikt vóór/na. Formaat YYYY-MM-DDTHH:mm:ss (geen tijdzoneverschuiving, geen milliseconden). |
updatedBefore / updatedAfter | timestamp | Zelfde formaat. |
sortBy | name | createdAt | updatedAt | Sorteerveld. |
sortDir | ASC | DESC | Sorteerrichting. |
Filters
Section titled “Filters”fieldFilters, metadataFilters en additionalPropertyFilters worden elk verzonden als één JSON-objectstring per filter, herhaald als queryparameter voor meerdere filters:
?fieldFilters={"key":"type","values":["poi"]}&fieldFilters={"key":"type","values":["zone"]}Elk filterobject heeft de vorm { "key": string, "values": string[] }. Meerdere waarden in de values-array van één filter worden met OR gecombineerd.
fieldFilters accepteert alleen deze gereserveerde sleutels — elke andere sleutel wordt stilzwijgend genegeerd:
| Sleutel | Match |
|---|---|
type | Type business object. Accepteert zowel de enum-waarde (Poi, Zone, BoxAsset, CubePrimitive, PlanePrimitive, DistanceMeasure, CoordinateMeasure, DiameterMeasure, SurfaceMeasure, OrthogonalMeasure, Cut, ModelAsset) als het genormaliseerde kebab-case-token — een gekoppelde, kleingeschreven versie van de PascalCase-naam, bijv. BoxAsset → box-asset. |
asset-type | Het assettype van het object (mapt naar assetTypeId). Exacte match. |
name | Alleen prefixmatch op de naam, geen fuzziness. |
id | Exacte match op object-id. |
Waarden voor fieldFilters zijn altijd platte strings of enum-tokens — de numerieke/bereiksyntax hieronder is hierop niet van toepassing.
metadataFilters en additionalPropertyFilters adresseren een schema-gedefinieerde metadata-eigenschap (metadataFilters) of een objecttype-specifieke eigenschap die geen deel uitmaakt van gemeenschappelijke metadata (additionalPropertyFilters, bijv. het icon-veld van een POI) via de sleutel. Elke waarde in values ondersteunt:
| Waardesyntax | Betekenis |
|---|---|
| Platte string | Exacte match. Meerdere platte strings in values worden met OR gecombineerd. |
* of lege string | Wordt overgeslagen — als dit de enige waarde is, matcht het filter alleen op de aanwezigheid van de sleutel. |
=123, !=123, >123, >=123, <123, <=123 | Numerieke vergelijking. Gehele getallen, decimalen en wetenschappelijke notatie (bijv. 1.5e+35) worden ondersteund. |
range:[1..10] | Inclusief numeriek bereik. |
range:(1..10) | Exclusief numeriek bereik. |
range:[1..10) / range:(1..10] | Gemengde inclusieve/exclusieve grenzen. |
true / false | Alleen additionalPropertyFilters — matcht letterlijk op een boolean-eigenschap. |
Filters combineren
Section titled “Filters combineren”fieldFilters, metadataFilters en additionalPropertyFilters worden gecombineerd met AND-semantiek: een resultaat moet voldoen aan elk filter. Binnen één filter worden de waarden in de bijbehorende values-array met OR gecombineerd — dus twee fieldFilters-objecten met dezelfde key gedragen zich als “één van beide waarden matcht”, terwijl filters op verschillende sleutels (of verschillende filterarrays) het resultaat steeds verder inperken.
Typefilter gecombineerd met een numeriek metadatabereik (POI’s met een geregistreerde inspectiedruk tussen 80 en 120):
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.pressure%22%2C%22values%22%3A%5B%22range%3A%5B80..120%5D%22%5D%7DAuthorization: Bearer {access_token}Assettype gecombineerd met een naamfilter, meest recent bijgewerkt eerst:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22asset-type%22%2C%22values%22%3A%5B%22pump%22%5D%7D&fieldFilters=%7B%22key%22%3A%22name%22%2C%22values%22%3A%5B%22vibration%22%5D%7D&sortBy=updatedAt&sortDir=DESCAuthorization: Bearer {access_token}Dit betekent: objecten waarvan het assettype pump is en waarvan de naam begint met “vibration”, gesorteerd op meest recent bijgewerkt.
Twee fieldFilters op dezelfde sleutel (OR’d) gecombineerd met een fieldFilters op een andere sleutel (AND’d) — POI’s of zones, beperkt tot het assettype pump:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%2C%22zone%22%5D%7D&fieldFilters=%7B%22key%22%3A%22asset-type%22%2C%22values%22%3A%5B%22pump%22%5D%7DAuthorization: Bearer {access_token}Een boolean additionalPropertyFilters-literal gecombineerd met een string-match in metadataFilters — actieve POI’s waarvan de icon-gerelateerde metadata een “warning”-status registreert:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&additionalPropertyFilters=%7B%22key%22%3A%22isActive%22%2C%22values%22%3A%5B%22true%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.status%22%2C%22values%22%3A%5B%22warning%22%5D%7DAuthorization: Bearer {access_token}Een volledig belaste aanvraag die alle drie de filterinvoer combineert, een aparte naamfilter, een datumbereik, paginering en sortering — met de volledige aanvraagvorm:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%2C%22zone%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.pressure%22%2C%22values%22%3A%5B%22range%3A%5B80..120%5D%22%5D%7D&additionalPropertyFilters=%7B%22key%22%3A%22isActive%22%2C%22values%22%3A%5B%22true%22%5D%7D&searchNameQuery=Pump&nameMatch=contains&updatedAfter=2026-01-01T00%3A00%3A00&updatedBefore=2026-12-31T23%3A59%3A59&page=1&limit=25&sortBy=updatedAt&sortDir=DESCAuthorization: Bearer {access_token}Sorteren
Section titled “Sorteren”sortBy | Sorteert op |
|---|---|
name | Objectnaam |
createdAt | Aanmaaktijdstip |
updatedAt | Tijdstip van laatste wijziging |
Elke sortBy-waarde combineert met elke sortDir-waarde:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=name&sortDir=ASCAuthorization: Bearer {access_token}GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=createdAt&sortDir=DESCAuthorization: Bearer {access_token}GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=updatedAt&sortDir=DESCAuthorization: Bearer {access_token}sortDir staat standaard op ASC wanneer deze wordt weggelaten. sortBy heeft geen gedocumenteerd standaardveld — laat je het weg, dan wordt er gesorteerd op interne relevantiescore (aflopend), met id (oplopend) als tiebreaker. Alleen fieldFilters met key: "name" beïnvloedt die score; elk ander filter is een zuivere ja/nee-match zonder effect op de rangschikking, dus in de praktijk levert het weglaten van sortBy zonder een name-filter resultaten op in id-volgorde. Dit is een implementatiedetail, geen gegarandeerd contract — stel sortBy altijd expliciet in wanneer een specifieke veldvolgorde belangrijk is voor uw integratie.
Numerieke en bereikfilters
Section titled “Numerieke en bereikfilters”Binnen metadataFilters- en additionalPropertyFilters-waarden kan een waarde een vergelijkingsoperator of een bereik dragen in plaats van letterlijk te matchen. Deze syntax is niet van toepassing op fieldFilters — die matchen altijd letterlijk/als enum (type, asset-type, name, id).
| Operator | Voorbeeld | Betekenis |
|---|---|---|
= | =123 | Gelijk aan |
!= | !=123 | Niet gelijk aan |
> | >123 | Groter dan |
>= | >=123 | Groter dan of gelijk aan |
< | <123 | Kleiner dan |
<= | <=123 | Kleiner dan of gelijk aan |
range:[a..b] | range:[80..120] | Inclusief op beide grenzen |
range:(a..b) | range:(80..120) | Exclusief op beide grenzen |
range:[a..b) | range:[80..120) | Inclusieve ondergrens, exclusieve bovengrens |
range:(a..b] | range:(80..120] | Exclusieve ondergrens, inclusieve bovengrens |
Gehele getallen, decimalen, negatieve getallen en wetenschappelijke notatie worden allemaal ondersteund, bijv. >=-40, =3.14, of range:[1.5e+35..2.0e+35].
Naamfilter vs. naamquery
Section titled “Naamfilter vs. naamquery”Er zijn twee manieren om te matchen op naam, en ze gedragen zich verschillend:
| Parameter | Matchstijl | Combineert met andere filters? |
|---|---|---|
fieldFilters={"key":"name",...} | Prefixmatch, geen fuzziness | Ja — combineert altijd met AND |
searchNameQuery + nameMatch | contains (standaard) of exact, geen fuzziness | Ja — combineert altijd met AND |
Gebruik fieldFilters met key: "name" voor een naam-only prefixmatch die combineert volgens dezelfde AND/OR-regels als type of asset-type. Gebruik searchNameQuery met nameMatch wanneer u een precieze substring- of exacte-naamzoekopdracht nodig heeft zonder fuzzy-tolerantie — bijvoorbeeld om te valideren dat een naam letterlijk bestaat.
Response
Section titled “Response”{ "results": [ { "id": "5e1c0b3a-2d9a-4b7d-8f0b-9a2c8f1b7a10", "name": "Fire extinguisher 12", "type": "Poi", "matchedFields": [ { "matchKey": "name", "highlight": "Fire <em>extinguisher</em> 12" } ], "createdAt": "2026-06-01T10:00:00.000Z", "updatedAt": "2026-06-01T10:00:00.000Z", "createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d" } ], "count": 1}matchedFields toont welk veld of welke metadata-eigenschap matchte, met de gematchte tekst omsloten door <em>. matchKey is ofwel een veldnaam op het hoogste niveau (bijv. name) ofwel @<metadata-path> voor een matchende geneste metadata- of eigenschapswaarde.
Details over highlighting
Section titled “Details over highlighting”Eén resultaat kan meerdere matchedFields-items bevatten — één per veld of metadata-eigenschap die matchte. Bijvoorbeeld, een gecombineerde fieldFilters-naammatch en een metadataFilters-aanvraag die zowel de naam van het object als een inspectie-metadatawaarde matcht, retourneert:
{ "id": "5e1c0b3a-2d9a-4b7d-8f0b-9a2c8f1b7a10", "name": "Pressure gauge 04", "type": "Poi", "matchedFields": [ { "matchKey": "name", "highlight": "<em>Pressure</em> gauge 04" }, { "matchKey": "@inspection.status", "highlight": "<em>Warning</em>: recalibration due" } ], "createdAt": "2026-06-01T10:00:00.000Z", "updatedAt": "2026-06-01T10:00:00.000Z", "createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d"}Highlight-fragmenten worden HTML-escaped voordat de <em>-markeringen worden ingevoegd, dus elke <, > of & in de gematchte tekst komt aan als <, > of & in plaats van ruwe markup — veilig om direct in HTML te renderen zonder een tweede escape-stap, maar decodeer het eerst als u de platte-tekstwaarde nodig heeft.
Edge cases
Section titled “Edge cases”| Situatie | Gedrag |
|---|---|
| Geen filters (of allemaal leeg) | Retourneert elk business object in de twin, tot aan limit, zonder rangschikking (match_all). |
Een niet-herkende fieldFilters-sleutel | Wordt stilzwijgend genegeerd — het filter draagt niets bij aan de query en veroorzaakt geen 400. |
Een metadataFilters/additionalPropertyFilters-waarde van * of "" | Wordt overgeslagen. Als elke waarde in de values-array van dat filter op deze manier wordt overgeslagen, vereist het filter nog steeds dat het object een eigenschap heeft bij die sleutel — het wordt een aanwezigheidscontrole zonder waardebeperking. |
Voorbeelden
Section titled “Voorbeelden”Naam-prefixzoekopdracht:
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22name%22%2C%22values%22%3A%5B%22extinguisher%22%5D%7DAuthorization: Bearer {access_token}Naam-contains-zoekopdracht gesorteerd op naam:
GET {api_url}/v1/twin/{contextId}/search?searchNameQuery=Pump&nameMatch=contains&sortBy=name&sortDir=ASCAuthorization: Bearer {access_token}Foutgevallen
Section titled “Foutgevallen”| Status | Oorzaak |
|---|---|
400 Bad Request | Een waarde van fieldFilters, metadataFilters of additionalPropertyFilters is geen geldige JSON, of komt niet overeen met de vorm { key, values }. |
Volledig voorbeeld
Section titled “Volledig voorbeeld”Herhaalde filterparameters (meerdere fieldFilters, metadataFilters of additionalPropertyFilters met verschillende JSON-waarden) kunnen niet worden opgebouwd met de dict-gebaseerde params van requests — een dict kan maar één waarde per sleutel bevatten. Bouw de querystring zelf op met urllib.parse.urlencode en een lijst van tuples:
import jsonimport requestsfrom urllib.parse import urlencode
API_URL = "https://<your-regional-api-url>"TOKEN = "<access_token>"CONTEXT_ID = "<twin-id>"
headers = {"Authorization": f"Bearer {TOKEN}"}
params = [ ("fieldFilters", json.dumps({"key": "type", "values": ["poi"]})), ("metadataFilters", json.dumps({"key": "inspection.pressure", "values": ["range:[80..120]"]})), ("sortBy", "name"), ("sortDir", "ASC"),]
response = requests.get( f"{API_URL}/v1/twin/{CONTEXT_ID}/search?{urlencode(params)}", headers=headers,).json()
for result in response["results"]: print(result["type"], result["name"], result["id"])Nodes doorzoeken
Section titled “Nodes doorzoeken”GET /v1/nodes/search doorzoekt de nodehiërarchie van uw organisatie — divisies, sites, mappen, twins, asset libraries en databestanden — in plaats van de business objects binnen een twin. De organisatie wordt bepaald op basis van het access token, niet als parameter meegegeven.
Queryparameters
Section titled “Queryparameters”| Parameter | Type | Opmerkingen |
|---|---|---|
nodeTypes | array van DataNodeType | Filter op een of meer nodetypes. Herhaal de parameter, bijv. ?nodeTypes=Site&nodeTypes=Folder. Waarden: Organization, Site, Pointcloud, Mesh, SiteFile, Folder, Project, Division, Artifact, DataBundle, Twin, AssetLibrary. |
excludeNodeTypes | array van DataNodeType | Sluit een of meer nodetypes uit. Zelfde herhalingssyntax. |
searchNameQuery | string | Filter op nodenaam. |
nameMatch | exact | contains | Matchmodus voor searchNameQuery. Standaard contains. |
parentId | uuid | Alleen directe children van deze node. |
ancestorId | uuid | Nakomelingen op elke diepte, exclusief de voorouder zelf. Gebruik dit voor geneste content onder een site of map; gebruik parentId voor alleen directe children. |
createdById | uuid | Filteren op maker. |
createdBefore / createdAfter | timestamp | Strikt vóór/na. Formaat YYYY-MM-DDTHH:mm:ss. |
updatedBefore / updatedAfter | timestamp | Zelfde formaat. |
bytesStored | integer | Exacte match. |
minBytesStored / maxBytesStored | integer | Inclusieve grenzen. |
childrenCount | integer | Exacte match. |
minChildrenCount / maxChildrenCount | integer | Inclusieve grenzen. |
includesThumbnail | 'true' | 'false' | Neem gesigneerde thumbnail-URL’s op indien beschikbaar. Standaard 'false'. |
page | integer | Standaard 1. |
limit | integer | 1–50, standaard 20. |
sortBy | name | createdAt | updatedAt | bytesStored | childrenCount | Sorteerveld. |
sortDir | ASC | DESC | Sorteerrichting. Standaard ASC. |
Response
Section titled “Response”{ "items": [ { "id": "a6f75b3c-f261-4b27-9a2a-9a6cc1234c53", "createdAt": "2026-06-01T10:00:00.000Z", "updatedAt": "2026-06-01T10:00:00.000Z", "name": "Building A", "type": "Site", "createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d", "parentId": "d2a1c4b7-3e10-4f2c-9a6b-7c1d8e2f3a45", "childrenCount": 4, "bytesStored": 15728640, "thumbnailSignedUrl": null } ], "total": 1}Voorbeelden
Section titled “Voorbeelden”Alle sites onder een voorouder-node:
GET {api_url}/v1/nodes/search?nodeTypes=Site&ancestorId=d2a1c4b7-3e10-4f2c-9a6b-7c1d8e2f3a45Authorization: Bearer {access_token}Mappen waarvan de naam begint met “Archive”, gesorteerd op naam:
GET {api_url}/v1/nodes/search?nodeTypes=Folder&searchNameQuery=Archive&nameMatch=contains&sortBy=name&sortDir=ASCAuthorization: Bearer {access_token}import requestsfrom urllib.parse import urlencode
API_URL = "https://<your-regional-api-url>"TOKEN = "<access_token>"ANCESTOR_ID = "<division-or-site-id>"
headers = {"Authorization": f"Bearer {TOKEN}"}
params = [ ("nodeTypes", "Site"), ("ancestorId", ANCESTOR_ID), ("sortBy", "name"), ("sortDir", "ASC"),]
response = requests.get( f"{API_URL}/v1/nodes/search?{urlencode(params)}", headers=headers,).json()
for node in response["items"]: print(node["type"], node["name"], node["id"])Volgende stap
Section titled “Volgende stap”Voor het maken van resources onder een node die door node search wordt geretourneerd, zie Een data bundle maken.