Aller au contenu principal
sdai.ch
Ouvrir le menu
Toute la documentation

DocumentationAPI publique

Guide

Référence de l'API

Les points d'entrée, la pagination par curseur, les formats de valeurs et les codes d'erreur.

Base d'URL et authentification

Tous les points d'entrée sont sous https://sdai.ch/api/v1 et attendent l'en-tête Authorization: Bearer <clé>. La spécification complète est publiée sur openapi.json.

Les points d'entrée

Méthode et cheminCe qu'il rend
GET /mel'organisation, le plan et le nom de la clé appelante
GET /batimentsvos bâtiments, paginés
GET /batiments/{id}un bâtiment
GET /batiments/{id}/zonesles zones de détection d'un bâtiment
GET /batiments/{id}/terminauxles terminaux asservis d'un bâtiment
GET /batiments/{id}/equipementsle parc d'un bâtiment, avec des filtres type et etat optionnels
GET /matricesvos matrices, avec un filtre batiment_id optionnel
GET /matrices/{id}une matrice avec sa grille complète

Les filtres type et etat du parc comparent la valeur à l'identique, sur des chaînes libres : une valeur inconnue rend une liste vide, une valeur vide rend un 400. Un batiment_id qui n'est pas chez vous rend un 404, jamais une liste vide.

Pagination

Les listes se parcourent par curseur, jamais par numéro de page :

  • ?limit= entre 1 et 100, 50 par défaut. Une valeur hors bornes rend un 400, jamais un repli silencieux sur la valeur par défaut.
  • ?cursor= reçoit la valeur next_cursor de la réponse précédente, telle quelle.
  • next_cursor vaut null sur la dernière page.
# première page
curl -H "Authorization: Bearer $CLE" "https://sdai.ch/api/v1/batiments?limit=50"
# page suivante
curl -H "Authorization: Bearer $CLE" "https://sdai.ch/api/v1/batiments?limit=50&cursor=cmr8kd..."

Le curseur est opaque : ne cherchez pas à le construire ni à l'interpréter. Il vous protège d'un défaut classique de la pagination par numéro de page, où une création concurrente décale les pages suivantes et vous fait sauter une ligne sans que rien ne le signale.

Formats de valeurs

  • Enveloppe en anglais (data, next_cursor), champs métier en français et en minuscules avec tirets bas : batiment_id, type_detection, is_example.
  • Dates en ISO 8601 UTC, par exemple 2026-05-12T09:00:00.000Z. Une date absente vaut null, jamais une chaîne vide.
  • Listes fermées : seuls categorie_test_integral (CAT_I, CAT_II, CAT_III) et l'action d'une cellule de matrice (FERME, OUVERT, ACTIVE, ARRETE, DEBLOQUE, RAPPEL) ont un jeu de valeurs garanti.
  • Champs libres : statut, type, etat, categorie, type_detection, etat_securite, type_commande et categorie_asservissement sont saisis dans l'application. Traitez toute valeur inattendue comme normale plutôt que de la rejeter.

Deux points à connaître sur les bâtiments

  • nombre_detecteurs, nombre_zones et nombre_boucles sont des champs déclaratifs de la fiche du bâtiment, saisis à la main. Ce ne sont pas des compteurs calculés. Pour un compte réel, paginez /zones ou /equipements.
  • is_example vaut true sur le bâtiment de démonstration créé à l'inscription. Il est inclus dans les listes : à vous de le filtrer si vous ne le voulez pas.

La grille d'une matrice

GET /matrices/{id} rend la matrice avec ses axes explicites :

{ "data": {
  "id": "...", "batiment_id": "...", "nom": "Matrice principale", "version": 3,
  "statut": "APPROUVEE",
  "zones":     [ { "id": "...", "code": "Z01", "type_detection": "FUMEE", "ordre": 1 } ],
  "terminaux": [ { "id": "...", "code": "T01", "etat_securite": "FERME", "ordre": 1 } ],
  "asservissements": [
    { "zone_id": "...", "terminal_id": "...", "type_commande": "AUTO_SIMPLE",
      "action": "FERME", "delai_secondes": 30, "critere": null, "remarque": null }
  ],
  "truncated": false
} }

Trois choses en découlent :

  1. Les axes viennent du bâtiment, pas des cellules. Une zone qui ne commande aucun terminal figure quand même dans zones. C'est voulu : une ligne vide de la matrice est une information, pas une absence.
  2. La grille est creuse. Seules les intersections commandées apparaissent dans asservissements. Reconstruisez la grille en croisant zones et terminaux, puis en plaçant les cellules.
  3. Le plafond est annoncé. Au maximum 5000 cellules sont rendues. Au-delà, truncated passe à true. Il n'y a jamais de troncature silencieuse.

Les axes rendus ici sont volontairement réduits à ce qu'il faut pour étiqueter une ligne ou une colonne. Pour la fiche complète d'une zone ou d'un terminal, appelez /batiments/{id}/zones ou /batiments/{id}/terminaux.

Erreurs

Toutes les erreurs ont la même forme :

{ "error": { "code": "not_found", "message": "Resource not found.", "request_id": "req_..." } }

Traitez le code par programme : bad_request, unauthorized, plan_required, not_found, rate_limited, server_error. Le request_id est aussi renvoyé dans l'en-tête X-Request-Id : citez-le si vous nous écrivez à support@sdai.ch.

Deux réponses sont volontairement indistinctes :

  • Le 401 ne dit pas si la clé est inconnue, révoquée ou expirée.
  • Le 404 ne dit pas si la ressource n'existe pas ou si elle appartient à une autre organisation.

Dans les deux cas, distinguer renseignerait un tiers sur ce qu'il n'a pas le droit de savoir.

Limites de la version 1

  • Lecture seule.
  • Les défauts, les rapports et les contrôles ne sont pas encore exposés.
  • L'organisation se déduit toujours de la clé : aucun point d'entrée n'accepte d'identifiant d'organisation.

Un besoin qui ne rentre pas dans ce cadre ? Écrivez-nous à support@sdai.ch, cela oriente la suite.

Documentation informative rédigée par sdai.ch. Les captures et libellés peuvent varier selon votre plan et vos droits. Seuls les textes officiels (AEAI, SES, SIA) font foi sur le plan normatif.

Prêt à mettre ces guides en pratique ?

30 jours d'essai gratuit, sans carte bancaire. Créez votre premier bâtiment et votre première matrice en moins de quinze minutes.