Aller au contenu principal

Ingestion des données

Ce guide explique comment ingérer et gérer des objets tels que les bâtiments, les espaces et les équipements à l'aide de l'API d'ingestion de Stonal.

info

Vous devrez obtenir un jeton d'accès personnel pour utiliser les API d'ingestion.

Toutes les requêtes d'ingestion utilisent l'API d'ingestion avec la structure suivante :

📄 ingest.sh
#!/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 \
-v \
-X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $STONAL_TOKEN" \
-d @payload.json

Objets de niveau racine

BUILDING_GROUP, BUILDING

Ce sont les objets de plus haut niveau de votre hiérarchie. Un BUILDING_GROUP représente un site contenant plusieurs bâtiments, et BUILDING représente un bâtiment logique tel qu'il est géré dans votre ERP.

📄 root-assets.json
{
"assets": [
{
"externalIds": {
"CODE": "SITE_001"
},
"type": "BUILDING_GROUP",
"name": "Residence du Parc",
"properties": {
"simple": {
"ADDRESS": "123 Rue de la Paix, Paris, France"
}
}
},
{
"externalIds": {
"CODE": "SITE_001_BAT_001"
},
"type": "BUILDING",
"name": "Bâtiment A",
"parent": {
"externalIds": {
"CODE": "SITE_001"
}
}
}
]
}

Sections de bâtiment et de niveau

BUILDING_SECTION, LEVEL_SECTION

Les sections de bâtiment et de niveau fournissent des divisions logiques au sein de la structure de votre bâtiment. Une BUILDING_SECTION représente une section de bâtiment (telle qu'une cage d'escalier, une entrée ou une aile), tandis qu'une LEVEL_SECTION représente une division verticale au sein d'un étage.

📄 building-level-sections.json
{
"assets": [
{
"externalIds": {
"CODE": "SITE_001_ENTRANCE_A"
},
"type": "BUILDING_SECTION",
"name": "Entrée A",
"parent": {
"externalIds": {
"CODE": "SITE_001_BAT_001"
}
}
},
{
"externalIds": {
"CODE": "SITE_001_LEVEL_RDC_SECTION_A"
},
"type": "LEVEL_SECTION",
"name": "Section A - RDC",
"parent": {
"externalIds": {
"CODE": "SITE_001_LEVEL_RDC"
}
},
"groupedBy": [
{
"externalIds": {
"CODE": "SITE_001_ENTRANCE_A"
}
}
]
}
]
}
astuce

Le champ groupedBy d'une LEVEL_SECTION peut la relier à une BUILDING_SECTION, vous permettant d'associer les sections d'étage aux sections de bâtiment correspondantes (par exemple, des cages d'escalier ou des entrées qui s'étendent sur plusieurs étages).

Structure physique du bâtiment

PLAN|INDOOR, LEVEL, SPACE

Les objets physiques décrivent la géométrie réelle de vos bâtiments. Un PLAN|INDOOR regroupe plusieurs étages, un LEVEL représente un seul étage, et SPACE représente les pièces.

📄 physical-assets.json
{
"assets": [
{
"externalIds": {
"CODE": "SITE_001_INDOOR_001"
},
"type": "PLAN|INDOOR",
"name": "Plan Bâtiment A",
"parent": {
"externalIds": {
"CODE": "SITE_001"
}
},
"groupedBy": [
{
"externalIds": {
"CODE": "SITE_001_BAT_001"
}
}
]
},
{
"externalIds": {
"CODE": "SITE_001_LEVEL_RDC"
},
"type": "LEVEL",
"name": "Rez-de-chaussée",
"parent": {
"externalIds": {
"CODE": "SITE_001_INDOOR_001"
}
}
},
{
"externalIds": {
"CODE": "SITE_001_SPACE_001"
},
"type": "SPACE",
"name": "Bureau 101",
"parent": {
"externalIds": {
"CODE": "SITE_001_LEVEL_RDC"
}
},
"groupedBy": [
{
"externalIds": {
"CODE": "SITE_001_ZONE_001"
}
}
]
}
]
}
astuce

Le champ groupedBy d'un PLAN|INDOOR le relie à un BUILDING logique. Cela vous permet d'associer les plans physiques à la structure de bâtiments de votre ERP.

Objets logiques

RENTED_UNIT, ZONE

Les objets logiques organisent les espaces à des fins métier. Un RENTED_UNIT représente un logement qui peut être loué (lié à des contrats), et une ZONE regroupe plusieurs espaces (un appartement, un ensemble de bureaux, etc.).

📄 logical-assets.json
{
"assets": [
{
"externalIds": {
"CODE": "SITE_001_APT_101"
},
"type": "RENTED_UNIT",
"name": "Appartement 101",
"parent": {
"externalIds": {
"CODE": "SITE_001_BAT_001"
}
}
},
{
"externalIds": {
"CODE": "SITE_001_ZONE_001"
},
"type": "ZONE",
"name": "Appartement T3",
"parent": {
"externalIds": {
"CODE": "SITE_001_LEVEL_RDC"
}
},
"groupedBy": [
{
"externalIds": {
"CODE": "SITE_001_APT_101"
}
}
]
}
]
}
astuce

Le champ groupedBy d'une ZONE la relie à un RENTED_UNIT, vous permettant d'associer les espaces physiques aux lots louables et à leurs contrats.

Équipements et ouvertures

EQUIPMENT, OPENING

Les ouvertures représentent les portes, les fenêtres et autres passages au sein d'un espace. Les équipements sont des éléments installés dans les ouvertures (portes, fenêtres) ou directement dans les espaces (radiateurs, etc.).

📄 equipments-openings.json
{
"assets": [
{
"externalIds": {
"CODE": "SITE_001_OPENING_001"
},
"type": "OPENING",
"name": "Porte entrée Bureau 101",
"parent": {
"externalIds": {
"CODE": "SITE_001_SPACE_001"
}
}
},
{
"externalIds": {
"CODE": "SITE_001_DOOR_001"
},
"type": "EQUIPMENT",
"name": "Porte bois",
"parent": {
"externalIds": {
"CODE": "SITE_001_OPENING_001"
}
}
}
]
}

Format de la réponse

Une ingestion réussie renvoie les objets créés/mis à jour avec leur uid généré :

➡️ output
{
"assets": [
{
"uid": "272e9b9c-31f1-4a6b-86af-a8737031a2bc",
"externalIds": {
"CODE": "SITE_001"
},
"type": "BUILDING_GROUP",
"name": "Residence du Parc",
"properties": {
"source": "DEFAULT",
"simple": {
"ADDRESS": "123 Rue de la Paix, Paris, France"
}
}
}
]
}

Cas d'usage

Mettre à jour un objet

info

Nous pouvons référencer un objet en utilisant : uid ou l'un des externalIds. Idem lorsqu'on référence des relations : parent, groups, groupedBy ou groupingAssetsToAdd

Mettre à jour le parent d'un objet

Ici, nous changeons simplement le parent d'un objet

📄 updating-asset-parent.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"parent": { "uid": "d3e98110-e494-4cac-a508-38058681fa62" }
}]
}

Pour supprimer un parent, nous devons explicitement le définir à null

📄 removing-asset-parent.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"parent": null
}]
}

Ajouter ou modifier l'externalId d'un objet

info

Lorsque nous voulons modifier un identifiant externe, nous devons spécifier l'uid de l'objet.

📄 adding-or-updating-an-external_id.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"externalIds": {
"CODE": "SITE_001",
"PIH": "00001"
}
}]
}

Mettre à jour la date d'expiration d'un objet

📄 adding-or-updating-an-expiration_date.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"expirationDate": "2040-10-09"
}]
}

Mettre à jour la date d'effet d'un objet

📄 adding-or-updating-an-effective_date.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"effectiveDate": "2010-01-01"
}]
}

Déclarer des propriétés pour un bâtiment

La déclaration de données peut se faire lors de la création d'un objet ou plus tard lors de sa mise à jour.

info

Définit automatiquement effectiveDate à la date courante et expirationDate à la date système maximale

info

Les clés de l'objet 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 dqc_building_properties.png

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

dqc_equipment_properties.png

📄 adding-address-and-date-for-a-building.json
{
"assets": [{
"externalIds": {
"CODE": "BUILDING_001"
},
"properties": {
"source": "PREMIANCE", // Optionnal - by default it's set to "DEFAULT"
"simple": {
"ADDRESS": "28, cours Albert 1er, 75008 PARIS, France",
"BUILDING_DATE": "2025-11-25"
}
}
}]
}

Ignorer les propriétés inconnues

astuce

Si nous voulons ignorer les propriétés inconnues et créer celles qui existent (au lieu de lever une erreur et d'arrêter l'ingestion), nous pouvons définir le paramètre ignoreUnknowns à true dans options

📄 adding-data-for-existing-properties-and-ignore-unkown-properties.json
{
"options": {
"properties": {
"ignoreUnknowns": true
}
},
"assets": [
{
"uid": "2009d42d-0f31-4c0f-a395-b7688e3b667d",
"properties": {
"source": "PREMIANCE",
"simple": {
"NON_EXISTING": "A value", // Will be ignored
"ADDRESS": "28, cours Albert 1er, 75008 PARIS, FRANCE", // Will be created because this property exists
}
}
}
]
}

Les propriétés inconnues seront ignorées et non insérées, et par conséquent non renvoyées

➡️ output
{
"assets": [
{
"uid": "2009d42d-0f31-4c0f-a395-b7688e3b667d",
"externalIds": {
"CODE": "BUILDING_001"
},
"type": "BUILDING",
"name": "Bâtiment 1",
"properties": {
"source": "PREMIANCE",
"simple": {
"ADDRESS": "28, cours Albert 1er, 75008 PARIS, FRANCE"
}
}
}
]
}

Déclarer des propriétés temporelles

info

Si non spécifié, définit automatiquement startDate à la date courante et endDate à la date système maximale

📄 defining-tenants-by-dates-for-a-building.json
{
"assets": [{
"externalIds": {
"CODE": "BUILDING_001"
},
"properties": {
"precise": {
"TENANT_NAME": [
{
"rawValue": "Laboratoire A",
"endDate": "2029-01-31"
},
{
"rawValue": "Avocats B",
"startDate": "2029-02-01",
"endDate": "2035-01-01"
}
]
}
}
}]
}

Supprimer un objet

attention

Seul l'uid est autorisé pour spécifier l'objet à supprimer. L'utilisation des externalIds n'est pas autorisée pour la suppression.

info

Nous ne pouvons pas définir une valeur deletedAt qui dépasse 1 h après ou avant l'heure courante.

info

L'objet à supprimer ne doit avoir aucun objet enfant. Il peut encore avoir des objets parents, mais il ne peut pas référencer d'autres objets comme ses descendants.

📄 deleting-an-asset.json
{
"assets": [{
"uid": "1712974c-3758-4e67-8717-1aa2441efc29",
"deletedAt": "2025-02-21T23:30:58.284Z"
}]
}