Rechercher des données
Ce guide explique comment récupérer le bon type de données selon votre usage, en utilisant l'API de recherche de Stonal avec des filtres, de la pagination et des schémas de recherche avancés.
Vous devrez obtenir un jeton d'accès personnel pour utiliser l'API de recherche.
Démarrage
Authentification
Voici un exemple de requête autour de l'API de recherche, où nous allons récupérer des BUILDING_GROUP et des BUILDING.
Vous devez passer une requête ressemblant à ceci :
#!/bin/sh -ex
# Your organization
STONAL_ORG=DEMO
# Fetch your token from here: https://app.stonal.io/users/app
STONAL_TOKEN=9631e269-e21e-4ce6-92a9-c6f7ed1fa98a
curl \
https://api.stonal.io/datalake/v1/organizations/$STONAL_ORG/assets/search \
-v \
-X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $STONAL_TOKEN" \
-d @query.json -o output.json
Requête initiale
{
"search": {
"type": {
"equals": [
"BUILDING",
"BUILDING_GROUP"
]
}
},
"properties": {
"simple": ["LAT", "LNG"]
},
"fields": [
"name",
"type",
"uid",
"externalIds"
],
"paginate": {
"size": 2
}
}
La sortie sera semblable à ceci :
{
"assets": [
{
"uid": "f6472f1a-9473-4fbf-9e1c-1c063eebb430",
"name": "Building Group 1",
"type": "BUILDING_GROUP",
"externalIds": {
"SOURCE_NAME": "BG001"
},
"properties": {
"simple": {
"LAT": "46.800",
"LNG": "1.6959"
}
}
},
{
"uid": "b81ce341-86f0-4cfe-a806-1d4a0f9a12ed",
"name": "Building 1",
"type": "BUILDING",
"externalIds": {
"SOURCE_NAME": "B001"
},
"properties": {
"simple": {
"LAT": "46.500",
"LNG": "1.7959"
}
}
}
],
"paginate": {
"size": 2,
"cursor": "123456"
}
}
Requêtes suivantes
Ensuite, pour récupérer le lot suivant de 10 objets, vous devez émettre la même requête avec le paginate.cursor défini à
la valeur reçue, c.-à-d. "123456".
{
"search": {
"type": {
"equals": [
"BUILDING",
"BUILDING_GROUP"
]
}
},
"fields": [
"name",
"type",
"uid",
"externalIds",
"parent"
],
"paginate": {
"size": 2,
"cursor": "123456"
}
}
La sortie sera semblable à ceci :
{
"assets": [
{
"uid": "dd127caf-5b9b-4116-884e-b42505ac1bd6",
"name": "Building Group 2",
"type": "BUILDING_GROUP",
"externalIds": {
"CODE": "BG002"
}
},
{
"uid": "2c2ca7be-78f1-4734-a4c6-bbc773c9027b",
"name": "Building 2",
"type": "BUILDING",
"externalIds": {
"CODE": "B002"
},
"parent": {
"uid": "dd127caf-5b9b-4116-884e-b42505ac1bd6"
}
}
],
"paginate": {
"size": 2,
"cursor": "234567"
}
}
Pour aller plus loin
Il existe de nombreuses autres façons d'interroger les données. Et vous pouvez combiner n'importe lequel de ces filtres.
Rechercher par identifiants externes
Vous pouvez effectuer une recherche à l'aide d'un seul identifiant externe, soit issu de l'objet lui-même, soit de ses relations.
Rechercher un objet précis par l'un de ses identifiants externes.
"search": {
"asset": {
"externalIds": {
"SOURCE_NAME": "BG001"
}
}
}
Rechercher les objets dont le parent correspond à l'identifiant externe donné.
"search": {
"parent": {
"externalIds": {
"SOURCE_NAME": "BG001"
}
}
}
Naviguer dans la hiérarchie
Les objets sont organisés selon une hiérarchie (voir Hiérarchie des objets). Vous pouvez utiliser les filtres de relation suivants pour naviguer vers le haut et vers le bas de l'arborescence. Un seul filtre de relation peut être utilisé par requête.
Trouver les enfants directs d'un parent
Utilisez parent pour trouver tous les objets qui sont des enfants directs d'un objet parent donné.
"search": {
"parent": { "uid": "dd127caf-5b9b-4116-884e-b42505ac1bd6" }
}
Trouver tous les descendants d'un ancêtre
Utilisez parentRecursive pour trouver tous les objets imbriqués sous un ancêtre donné, à n'importe quelle profondeur.
"search": {
"parentRecursive": { "externalIds": { "CODE": "SITE_001" } }
}
Trouver les parents directs d'un enfant
Utilisez child pour trouver les objets qui sont des parents directs d'un objet enfant donné.
"search": {
"child": { "uid": "b81ce341-86f0-4cfe-a806-1d4a0f9a12ed" }
}
Trouver tous les ancêtres d'un descendant
Utilisez childRecursive pour trouver tous les objets ancêtres d'un descendant donné, à n'importe quelle profondeur. C'est utile pour remonter la hiérarchie depuis un objet feuille (par exemple un équipement) afin de trouver son bâtiment, son groupe de bâtiments, etc.
{
"search": {
"childRecursive": { "uid": "$equipmentUid" },
"type": { "equals": ["BUILDING", "BUILDING_SECTION"] }
},
"fields": ["name", "type"],
"paginate": { "size": 10 }
}
Vous pouvez aussi utiliser externalIds pour identifier le descendant :
"search": {
"childRecursive": {
"externalIds": { "TRIRIGA": "EQP1008473" }
}
}
childRecursive renvoie tous les ancêtres mais exclut des résultats l'objet enfant interrogé lui-même. Tous les autres filtres (type, name, fields, properties, paginate) s'appliquent normalement aux ancêtres renvoyés.
Correspondance sur un motif
Vous pouvez rechercher des types correspondant à un motif d'expression régulière.
Rechercher des espaces
SPACE est un autre nom pour les pièces dans la plateforme Stonal.
Ceci renverra des objets de types SPACE et SPACE|* :
"search": {
"type": {
"matches": [
"SPACE",
"SPACE\\|.*"
]
}
}
Veuillez noter que ceci s'appliquera à tous les espaces de l'organisation. Si vous souhaitez le limiter à un bâtiment particulier, vous devriez le combiner avec un filtre parent comme ceci :
"search": {
"type": {
"matches": [
"SPACE",
"SPACE\\|.*"
]
},
"parent": {
"externalIds": {
"SOURCE_NAME": "BG001"
}
}
}
Exclure par type
Un seul de notMatches ou notEquals est accepté (de même que matches et equals)
Par correspondance sur un motif
Exclure des équipements spécifiés (ceux ayant un type commençant par EQUIPMENT|C|CA|) lors du listage des équipements d'un groupe de bâtiments
"search": {
"type": {
"matches": ["EQUIPMENT\\|.*"],
"notMatches": ["EQUIPMENT\\|C\\|CA\\|.*"]
},
"parentRecursive": {
"externalIds": { "CODE": "SITE_001" }
}
}
Par égalité stricte
Exclure des équipements spécifiés (ceux ayant un type égal à EQUIPMENT|C|CA|CA01 ou EQUIPMENT|A|AA) lors du listage des équipements d'un groupe de bâtiments
"search": {
"type": {
"matches": ["EQUIPMENT\\|.*"],
"notEquals": ["EQUIPMENT|C|CA|CA01", "EQUIPMENT|A|AA"]
},
"parentRecursive": {
"externalIds": { "CODE": "SITE_001" }
}
}
Filtrer sur la donnée courante d'une propriété
Les objets portent des propriétés : des points de données comme l'adresse, la surface locative, la date de construction ou le nombre de locataires. Chaque propriété est identifiée par un code (par ex. ADDRESS, RENTAL_AREA, BUILDING_DATE, TENANT_COUNT).
Les codes de propriété pour chaque type d'objet sont listés dans le produit DQC. Voir Récupérer un sous-ensemble de propriétés pour plus de détails.
Ajoutez un bloc search.properties pour filtrer les objets selon les valeurs de leurs propriétés.
search.properties filtre quels objets sont renvoyés. Le properties de niveau racine contrôle quelles données apparaissent dans la réponse. Ils peuvent être utilisés ensemble.
Exemple : bâtiments du 8e arrondissement de Paris ayant plus de 2 locataires
{
"search": {
"properties": {
"conditions": [
{ "op": "gt", "property": "TENANT_COUNT", "value": "2" },
{ "op": "contains", "property": "ADDRESS", "value": "75008 Paris" }
]
},
"type": {
"equals": ["BUILDING"]
}
},
"fields": ["uid", "name", "type"],
"properties": {
"simple": ["TENANT_COUNT", "ADDRESS"]
},
"paginate": { "size": 50 }
}
Structure d'une condition
Une condition est un objet comportant les champs suivants :
| Champ | Description |
|---|---|
op | L'opérateur à appliquer (voir Opérateurs ci-dessous) |
property | Le code de propriété sur lequel filtrer (pour les conditions feuilles) |
value | La valeur à comparer (pour les opérateurs à valeur unique) |
values | Une liste de valeurs à comparer (pour les opérateurs in/notIn) |
conditions | Une liste de conditions imbriquées (pour les opérateurs de groupe and/or) |
Plusieurs conditions au niveau racine sont combinées avec un ET. Utilisez des groupes or/and pour une logique explicite :
{ "op": "or", "conditions": [
{ "op": "contains", "property": "ADDRESS", "value": "75008 Paris" },
{ "op": "gt", "property": "TENANT_COUNT", "value": "10" }
]}
Les groupes peuvent être imbriqués :
{
"conditions": [
{ "op": "eq", "property": "MAIN_ASSET_NATURE", "value": "Bureau" },
{ "op": "or", "conditions": [
{ "op": "gt", "property": "RENTAL_AREA", "value": "500" },
{ "op": "gt", "property": "TENANT_COUNT", "value": "10" }
]}
]
}
Opérateurs
Comparaison
Les comparaisons de texte sont insensibles à la casse et aux accents (« chatelet » correspond à « Châtelet »).
| Opérateur | Description | Champs requis |
|---|---|---|
eq | Égal | value |
neq | Différent | value |
in | Correspond à une valeur quelconque d'une liste | values (non vide) |
notIn | Ne correspond à aucune des valeurs | values (non vide) |
{ "op": "eq", "property": "MAIN_ASSET_NATURE", "value": "Bureau" }
{ "op": "in", "property": "MAIN_ASSET_NATURE", "values": ["Commerce", "Logement"] }
Texte
| Opérateur | Description | Champs requis |
|---|---|---|
contains | Correspondance de sous-chaîne (insensible à la casse/aux accents) | value |
notContains | Exclut la correspondance de sous-chaîne | value |
regex | Correspondance par expression régulière | value (regex valide) |
notRegex | Exclut la correspondance par regex | value (regex valide) |
{ "op": "contains", "property": "ADDRESS", "value": "Rue du chat" }
Numérique et date
Toutes les valeurs sont passées sous forme de chaînes mais doivent être un nombre valide (par ex. "100") ou une date ISO 8601 (par ex. "2024-01-15").
| Opérateur | Description | Champs requis |
|---|---|---|
gt | Strictement supérieur à | value (nombre ou date) |
gte | Supérieur ou égal à | value (nombre ou date) |
lt | Strictement inférieur à | value (nombre ou date) |
lte | Inférieur ou égal à | value (nombre ou date) |
{
"conditions": [
{ "op": "gte", "property": "RENTAL_AREA", "value": "100" },
{ "op": "lte", "property": "RENTAL_AREA", "value": "500" }
]
}
{ "op": "gt", "property": "BUILDING_DATE", "value": "2000-01-01" }
Présence
| Opérateur | Description | Champs requis |
|---|---|---|
isNull | Aucune valeur courante pour cette propriété | aucun (value/values doivent être absents) |
isNotNull | A une valeur courante | aucun (value/values doivent être absents) |
{ "op": "isNull", "property": "ADDRESS" }
Groupes logiques
| Opérateur | Description | Champs requis |
|---|---|---|
and | Toutes les conditions imbriquées doivent correspondre | conditions (au moins 2) |
or | Au moins une doit correspondre | conditions (au moins 2) |
Négation et données manquantes
Les opérateurs de négation (neq, notIn, notContains, notRegex) excluent les objets qui n'ont aucune valeur pour la propriété. Pour les inclure, combinez avec isNull :
{ "op": "or", "conditions": [
{ "op": "notIn", "property": "MAIN_ASSET_NATURE", "values": ["Commerce", "Parking"] },
{ "op": "isNull", "property": "MAIN_ASSET_NATURE" }
]}
Récupérer un sous-ensemble de champs
Les champs sont des attributs directement associés à un objet. Vous pouvez spécifier quels champs récupérer.
Valeurs autorisées : uid, name, updatedAt, deletedAt, type, externalIds, representations, parent
L'identifiant unique uid est toujours renvoyé.
{
"search": {
"asset": { "uid": "2cb3683a-90f6-48de-aaa0-08f45c7bf808" }
},
"fields": ["name", "updatedAt", "externalIds"]
}
Récupérer un sous-ensemble de propriétés
Les propriétés sont associées à des données chronologiques liées à un objet.
Vous pouvez récupérer la donnée de référence d'une propriété spécifiée à l'instant courant.
Les éléments de la liste simple font référence au code de la propriété.
Ce code peut être trouvé dans notre produit DQC pour chaque type d'objet
Dans cet exemple, nous sommes sur un BUILDING, sa propriété nommée Adresse a ADDRESS pour code.
Capture d'écran depuis DQC sur une URL du type https://app.stonal.io/dqc/$ORGANIZATION_CODE/asset-types/EQUIPMENT/assets/$ASSET_UID

Nb : le code peut aussi avoir un format uuid
Dans cet exemple, nous sommes sur un EQUIPMENT, sa propriété nommée Date dernier renouvellement a 43f1f705-b3b3-4ff3-9ca3-a5c5ed638eef pour code.
Capture d'écran depuis DQC sur une URL du type https://app.stonal.io/dqc/$ORGANIZATION_CODE/asset-types/EQUIPMENT/assets/$ASSET_UID

{
"search": {
"type": { "equals": ["BUILDING"] }
},
"properties": {
"simple": ["ADDRESS", "BUILDING_DATE"]
}
}
{
"assets": [
{
"uid": "1321987a-b94f-4180-ab93-94432be0855f",
"properties": {
"simple": {
"ADDRESS": "28 Cr Albert 1er, 75008 Paris",
"BUILDING_DATE": "2001-09-29"
}
}
}
]
}
Mise à jour différentielle
Vous pouvez rechercher les données qui ont été mises à jour depuis une date particulière.
"search": {
"updatedAtAfter": "2025-09-12T00:00:00"
}
Détecter les objets supprimés
Dans la réponse de recherche, vous pouvez aussi inclure les objets supprimés correspondant aux filtres spécifiés.
"search": {
"updatedAtAfter": "2025-09-12T00:00:00",
"includeDeleted": true
}
Photos des objets
Ceci s'applique principalement aux objets BUILDING_GROUP et BUILDING.
Si l'objet possède un PHOTO_ID, nous pouvons y accéder directement en utilisant ce modèle d'URL :
https://api.stonal.io/document-storage/v1/organizations/$org/documents/$photoId/content
Nous fournissons également un redimensionnement et une génération de miniatures pour les photos à l'aide d'imagor afin que vous puissiez l'utiliser directement dans votre API frontend :
https://cdn-api.stonal.io/imagor/unsafe/fit-in/200x/api.stonal.io/document-storage/v1/organizations/$org/documents/$photoId/content
Le unsafe dans l'URL signifie que vous n'avez pas besoin de signer l'URL, mais son usage est sûr.