Aller au contenu principal
API DECI · pour les services SIG des SDIS

API DECI : importer les points d'eau incendie d'un SDIS

Vos points d'eau dans KiloDelta, sans rien ressaisir.

Je suis sapeur-pompier dans le Vaucluse et je développe KiloDelta seul. Une colonne qui monte en renfort sur un feu de forêt arrive dans un département dont elle ne connaît ni les poteaux ni les réserves. Cette API permet à votre service SIG d'envoyer son catalogue DECI en une requête. Les PEI apparaissent ensuite dans l'application, avec leur état et leur débit.

19
départements déjà couverts
223 897
points d'eau en ligne
9
types d'ouvrage acceptés
30j
gardés sur le téléphone
POST /api/v1/deci/import JSON UTF-8 en-tête X-Api-Key
76 29 35 14 64 17 84 71 21 56 79 86 22 39 24 81 16 43 82
19 départements · 223 897 PEI taille de la bulle = nombre de PEI
En bref
  • Une clé par SDIS, rattachée à votre service, qui ne sait faire qu'une chose : écrire vos PEI.
  • Un POST JSON par département. Chaque envoi remplace le catalogue précédent.
  • Quatre champs obligatoires par PEI : ref, lat, lon, type. Envoyez aussi etat, sinon le PEI est affiché indisponible.
  • Votre SDIS publie déjà ses PEI en open data ? Donnez-moi l'adresse, je les récupère moi-même.
1 · Pourquoi

Ce que vos PEI deviennent dans l'application.

Un pompier ouvre la carte, il voit vos points d'eau. Il n'a rien à configurer : l'application télécharge les PEI du département quand il déplace la carte. Voici où ils servent.

Sur la carte

Une forme par type d'ouvrage, une bordure pour l'état, une couleur pour le débit ou le volume. Au zoom fort, un capuchon indique le réseau.

La fiche au tap

État, débit à 1 bar, pressions, volume, commune, adresse. Un bandeau signale un PEI privé ou en emploi restreint.

Dès l'accueil

Le point d'eau le plus proche s'affiche sous la météo, avec sa distance. Un tap et la carte se cale dessus.

Sans réseau

Un département chargé reste consultable 30 jours hors ligne. Vos PEI entrent aussi dans le pack hors ligne du département.

Défendabilité

Le calcul de défendabilité des maisons regarde le débit réel des PEI autour. Sans débit, il prend une valeur médiane.

Au poignet

Le cadran KiloDelta pour montre Garmin peut demander les points d'eau autour de sa position.

Deux façons d'arriver sur la carte

Cette page

Vous envoyez

Votre SIG exporte le catalogue au format décrit plus bas et l'envoie avec votre clé, à la fréquence que vous voulez. C'est vous qui décidez quand la donnée change.

Sans clé

Je viens chercher

Si vos PEI sont déjà publiés en open data, j'écris l'adaptateur et je les récupère chaque semaine. C'est le cas aujourd'hui sur Hydraclic, PIGMA, GeoBretagne, data.calvados.fr et Ma carte IGN.

2 · Couverture

Les départements déjà dans l'application.

Cette liste est lue en base à chaque affichage de la page. Elle compte les PEI actifs, ceux qui ont été retirés par un envoi ou une mise à jour ne sont plus comptés.

  1. Seine-Maritime 76 21 274
  2. Finistère 29 20 210
  3. Ille-et-Vilaine 35 GeoBretagne 17 225
  4. Calvados 14 data.calvados.fr 14 701
  5. Pyrénées-Atlantiques 64 PIGMA 14 472
  6. Charente-Maritime 17 Hydraclic 13 280
  7. Vaucluse 84 Hydraclic 13 217
  8. Saône-et-Loire 71 13 207
  9. Côte-d'Or 21 11 883
  10. Morbihan 56 11 632
  11. Deux-Sèvres 79 11 535
  12. Vienne 86 PIGMA 11 287
  13. Côtes-d'Armor 22 10 828
  14. Jura 39 7 969
  15. Dordogne 24 PIGMA 7 200
  16. Tarn 81 6 699
  17. Charente 16 PIGMA 6 411
  18. Haute-Loire 43 Ma carte IGN 6 105
  19. Tarn-et-Garonne 82 4 762
  20. Total 223 897

Le vôtre n'y est pas ? Demandez une clé, ou envoyez-moi l'adresse de votre jeu de données s'il est public. Un département ne peut avoir qu'une source : s'il est déjà alimenté depuis une plateforme publique et que vous préférez envoyer vous-même, dites-le dans la demande, je fais la bascule à la main.

3 · Obtenir une clé

Une clé par SDIS, qui ne sert qu'à ça.

  1. Vous faites la demande. Le formulaire s'ouvre avec le module « DECI » déjà choisi et un message à compléter : nom du SDIS, département(s), e-mail technique, et l'adresse de vos données si elles sont déjà publiques.
  2. Je crée la clé. Elle est rattachée à votre SDIS et ne porte qu'un droit, deci:import. Elle écrit dans une source réservée à votre service, jamais mélangée aux autres. Elle ne peut pas toucher aux PEI d'un autre SDIS.
  3. Je vous la transmets. Elle a la forme kd_live_<12 caractères hexa>.<40 caractères hexa>. Je ne garde que l'empreinte du secret (SHA-256) : si vous la perdez, je ne peux pas la retrouver, j'en crée une autre.
  4. Vous testez votre fichier ici, avec l'outil plus bas, avant le premier envoi.

Une clé qui a fuité se désactive côté serveur : elle est alors refusée avec un 401. Prévenez-moi et je vous en donne une nouvelle.

4 · Envoyer

Un seul appel, tout le département.

HTTP
POST https://kilodelta.fr/api/v1/deci/import
X-Api-Key: kd_live_<id>.<secret>
Content-Type: application/json
curl
curl -X POST https://kilodelta.fr/api/v1/deci/import \
  -H "X-Api-Key: $KD_DECI_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @peis.json
Python (requests)
import os, requests

with open("peis.json", "rb") as f:
    body = f.read()   # octets UTF-8, tels quels

r = requests.post(
    "https://kilodelta.fr/api/v1/deci/import",
    data=body,
    headers={"X-Api-Key": os.environ["KD_DECI_KEY"],
             "Content-Type": "application/json"},
    timeout=300,
)
print(r.status_code, r.json())

Ce qu'il faut savoir avant d'appuyer sur Entrée

Un envoi remplace tout

Les PEI de votre source absents du corps sont retirés. Il n'y a donc pas de pagination : un département part en un seul envoi. Deux envois partiels à la suite, et le second efface le premier.

Le garde-fou

Si aucun PEI du corps n'est valide (corps vide, ou tout rejeté), rien n'est retiré. La réponse le signale avec empty_no_delete.

UTF-8, sans BOM

Un corps qui n'est pas en UTF-8 est refusé avant d'être lu (400). Un BOM en tête fait échouer la lecture du JSON (422). Les vieux exports Latin-1 sont les premiers suspects.

Une fois par jour suffit

Chaque envoi change la version du département et relance le téléchargement dans les applications. Envoyez après une mise à jour de votre base, pas en boucle.

Il n'y a pas de limite de débit sur cet endpoint et le traitement est synchrone : la réponse arrive quand tout est écrit. Prévoyez un délai d'attente large côté client. Pour le premier envoi d'un gros catalogue, prévenez-moi, je regarde passer l'import.

5 · Format

Un objet par PEI, à plat.

Le corps est un objet JSON avec un tableau peis. Un tableau seul à la racine ([ {…}, {…} ]) est aussi accepté. À la racine, code_dept est facultatif : s'il manque, le département est déduit des deux premiers caractères du commune_code du premier PEI valide.

Corse et outre-mer : renseignez toujours code_dept. La déduction sur deux caractères donne bien 2A ou 2B, mais 97 pour un code INSEE en 971 ou 974.

ChampTypeLimiteRôle
ref requistexte32 car.Identifiant métier du PEI (ex. INSEE + numéro d'ordre). Sert de clé de mise à jour quand id est absent.
lat requisnombre6 décimalesLatitude WGS84 en degrés décimaux (EPSG:4326). Pas de Lambert 93.
lon requisnombre6 décimalesLongitude WGS84 en degrés décimaux.
type requistextelisteType d'ouvrage, voir le tableau suivant. Un type inconnu fait ignorer le PEI.
etat recommandétextelistedisponible, emploi_restreint ou indisponible. Absent ou inconnu : le PEI est enregistré indisponible.
identier0 à 4 294 967 295Identifiant entier stable de votre SIG (gid, objectid…). S'il est fourni, c'est lui la clé de mise à jour.
commune_codetexte5 car.Code INSEE de la commune. Sert à déduire le département.
commune_nomtexte120 car.Nom de la commune, affiché dans la fiche.
debit_1barnombreentier, m³/hDébit à 1 bar. Fixe la couleur des poteaux, bouches, poteaux relais, bornes agricoles.
pressionnombrebar, 2 déc.Pression dynamique.
pression_statiquenombrebar, 2 déc.Pression statique. À 8 bar ou plus, le capuchon passe en jaune (réseau surpressé).
volume_panombreentier, m³Volume utile. Fixe la couleur des citernes, points d'aspiration, PENA, colonnes d'aspiration.
adressetexte255 car.Voie ou lieu-dit. street_address est accepté à la place.
domainetexteUne valeur qui commence par « priv » donne un PEI privé, tout le reste un PEI public. status est accepté à la place.

Les nombres peuvent être envoyés en texte ("60"), ils sont lus pareil. Les champs en trop sont ignorés. Le type et l'état ne tiennent pas compte de la casse ni des espaces autour.

Les 9 types d'ouvrage

Valeur de typeDans l'applicationCouleur selonMarqueur
poteau Poteau débit rond
bouche Bouche débit losange
poteau_relais Poteau relais débit anneau pointillé
borne_agricole Borne agricole débit pentagone
colonne_seche Colonne sèche débit rectangle étroit
citerne Citerne / bâche volume carré
point_aspiration Point d'aspiration volume triangle
pena_baignable PENA volume triangle inversé
colonne_aspiration Colonne fixe d'aspiration volume hexagone

La clé de mise à jour

D'un envoi à l'autre, un PEI est reconnu par son id si vous le fournissez, sinon par une empreinte calculée sur ref. Choisissez une règle et gardez-la : passer de l'une à l'autre fait retirer puis recréer tout le catalogue. Si votre SIG a un identifiant entier stable, donnez-le dans id. Sur un gros catalogue, c'est plus sûr que l'empreinte, qui peut exceptionnellement tomber deux fois sur la même valeur. L'outil de test plus bas signale ces doublons.

Un PEI retiré puis renvoyé plus tard revient avec le même identifiant côté KiloDelta.

6 · Exemple

Trois PEI, trois cas.

Un poteau complet, une bouche en emploi restreint sans débit connu, une citerne privée. Les valeurs sont inventées pour l'exemple.

peis.json
{
  "code_dept": "26",
  "peis": [
    {
      "ref": "26362-0147",
      "id": 90147,
      "commune_code": "26362",
      "commune_nom": "Valence",
      "lat": 44.933412,
      "lon": 4.892307,
      "type": "poteau",
      "etat": "disponible",
      "debit_1bar": 72,
      "pression": 1.4,
      "pression_statique": 4.2,
      "adresse": "Avenue Victor Hugo",
      "domaine": "public"
    },
    {
      "ref": "26362-0588",
      "id": 90588,
      "commune_code": "26362",
      "commune_nom": "Valence",
      "lat": 44.915871,
      "lon": 4.921654,
      "type": "bouche",
      "etat": "emploi_restreint",
      "adresse": "Rue Faventines",
      "domaine": "public"
    },
    {
      "ref": "26362-R012",
      "id": 91012,
      "commune_code": "26362",
      "commune_nom": "Valence",
      "lat": 44.94712,
      "lon": 4.905581,
      "type": "citerne",
      "etat": "disponible",
      "volume_pa": 120,
      "domaine": "privé"
    }
  ]
}

Depuis un export GeoJSON

L'endpoint ne prend pas de GeoJSON directement. Si votre SIG exporte une FeatureCollection de points en EPSG:4326, une ligne de jq fait la conversion. Adaptez les noms de propriétés à votre export.

jq
jq '{code_dept: "26", peis: [.features[] | {
      ref:        .properties.numero,
      commune_code: .properties.insee,
      lat:        .geometry.coordinates[1],
      lon:        .geometry.coordinates[0],
      type:       .properties.type_kd,
      etat:       .properties.etat_kd,
      debit_1bar: .properties.debit
    }]}' export.geojson > peis.json

Dans un GeoJSON, l'ordre est longitude puis latitude. Les valeurs de type et d'etat doivent être celles des listes ci-dessus : si votre base utilise des codes (PI, BI, PA…), faites la correspondance dans votre requête d'export.

7 · Tester un fichier

Voyez le résultat avant d'envoyer.

Déposez votre fichier ou collez son contenu. L'outil applique les mêmes règles que le serveur et vous montre ce qui serait retenu, ignoré, et comment vos PEI s'afficheraient. Rien ne quitte votre navigateur : aucune requête n'est faite, aucune clé n'est demandée.

Le résultat s'affiche ici.

8 · Réponse

Un compte rendu, pas un simple « OK ».

Un envoi accepté répond 200 avec le bilan de l'import. Par exemple, pour un deuxième envoi :

200 OK
{
  "ok": true,
  "source_id": 57,
  "code_dept": "26",
  "received": 4812,
  "added": 6,
  "updated": 4801,
  "removed": 3,
  "skipped": 5,
  "reasons": {
    "bad_coords": 2,
    "unknown_type": 3
  },
  "unknown_types": [
    "hydrant_prive"
  ],
  "unknown_etats": []
}
ChampSens
source_idLa source réservée à votre SDIS pour ce département. Elle est créée au premier envoi.
code_deptLe département retenu, fourni ou déduit.
receivedNombre d'éléments dans peis.
added / updatedPEI créés / mis à jour.
removedPEI de votre source absents de cet envoi, retirés.
skippedPEI ignorés à la lecture. Le détail est dans reasons.
unknown_types / unknown_etatsLes valeurs que je n'ai pas reconnues, pour corriger votre correspondance.

Les raisons possibles

reasonsCe qui s'est passé
missing_refref absente ou vide. PEI ignoré.
bad_coordslat ou lon absente, non numérique, hors bornes, ou les deux à 0. PEI ignoré.
unknown_typetype absent ou hors liste (la valeur est dans unknown_types). PEI ignoré.
not_objectUn élément de peis n'est pas un objet. Ignoré.
upsert_errorLe PEI a été lu mais n'a pas pu être écrit en base. Il n'est compté ni dans added, ni dans updated, ni dans skipped.
empty_no_deleteAucun PEI valide : le garde-fou a joué, rien n'a été retiré.

Un etat inconnu n'écarte pas le PEI : il est enregistré indisponible et la valeur apparaît dans unknown_etats.

9 · Sur la carte

Comment vos champs deviennent une couleur.

En intervention, le pompier doit lire en une seconde s'il peut engager un PEI. La couleur de la bordure vient de l'état, puis du débit (ou du volume pour les ressources statiques). L'emploi restreint est traité comme disponible pour la couleur, la restriction est affichée dans la fiche. Ce que voit le pompier, forme par forme et zoom par zoom, est détaillé sur la page Carte des points d'eau incendie (PEI).

Fort≥ 60 m³/h ou ≥ 120 m³
Moyen30 à 59 m³/h ou 30 à 119 m³
Faible< 30 m³/h ou < 30 m³
Débit non renseignédisponible, sans débit ni volume
Indisponiblecroix rouge, ne pas engager

Le bleu n'est pas un défaut. Un PEI disponible sans débit s'affiche en bleu, « disponible, débit non renseigné ». Pas en jaune : je ne veux pas faire croire à un débit faible quand il est seulement inconnu. Pour les calculs, le débit est alors estimé à la médiane.

Essayez

Laissez vide pour « non renseigné ».
color_code 4 · cap_code 0
Disponible, fort débit

Poteau disponible à 72 m³/h : 60 m³/h ou plus.

Au zoom fort, un capuchon indique le réseau (NF S 62-200) : rouge sous pression permanente, bleu non pressurisé (citernes, points d'aspiration, PENA, colonnes), jaune quand la pression statique atteint 8 bar (à défaut, la pression dynamique).

10 · Erreurs

Les codes que vous pouvez recevoir.

CodeMessageCause
200Envoi traité. Lisez quand même skipped et reasons.
400Corps qui n'est pas en UTF-8, ou qui contient des caractères de contrôle. Refusé avant la lecture.
401X-Api-Key absente.
X-Api-Key invalide ou inactive.
En-tête manquant, clé mal recopiée, ou clé désactivée.
403Cette clé n'a pas le droit deci:import.
Cette clé n'est rattachée à aucune entité.
La clé existe mais ne sert pas à ça. Écrivez-moi.
422parse: corps JSON invalideJSON mal formé, ou BOM en tête de fichier.
422parse: clé "peis" (tableau) attendueNi objet avec peis, ni tableau à la racine.
422Département indéterminé : fournis "code_dept" ou des "commune_code" INSEE.Pas de code_dept et aucun PEI valide avec un code INSEE.

Les erreurs 401, 403 et 422 ont toutes la même forme :

403 Forbidden
{
  "status": 403,
  "error": 403,
  "messages": {
    "error": "Cette clé n'a pas le droit deci:import."
  }
}
11 · Vérifier

Relire ce que l'application reçoit.

Ce sont les endpoints que l'application appelle. Ils sont publics, sans clé. Remplacez 26 par votre département.

État du département
curl "https://kilodelta.fr/api/v1/deci/manifest?depts=26"

{
  "items": [
    {
      "dept": "26",
      "count": 4807,
      "updated_at": "2026-09-30 06:12:41",
      "version": "3f9a1c2e"
    }
  ]
}

count doit correspondre à added + updated de votre dernier envoi. version change à chaque envoi : c'est elle qui dit aux téléphones de retélécharger.

Positions compactes
curl "https://kilodelta.fr/api/v1/deci/positions?dept=26"

// chaque ligne : [id KiloDelta, lat, lon, type_code, color_code, cap_code]
{ "v": "3f9a1c2e", "dept": "26", "peis": [ [418233, 44.933412, 4.892307, 0, 4, 0], … ] }
Fiche d'un PEI
curl "https://kilodelta.fr/api/v1/deci/peis/418233"

La fiche renvoie tout ce que le pompier voit au tap. Votre ref y figure sous le nom external_k, votre adresse sous street_address, avec etat_label, type_label et le color_code calculé.

Ces réponses sont mises en cache (5 minutes pour manifest, plus longtemps pour les positions et les fiches, avec un ETag). Un curl direct voit tout de suite la nouvelle version. La carte en haut de cette page compte vos PEI dès le rechargement.

12 · Questions

Ce qu'on me demande.

Nos PEI deviennent-ils publics ?
Oui. Les endpoints de lecture n'ont pas d'authentification, comme un jeu de données open data. N'envoyez que ce que vous accepteriez de publier. La domanialité est transmise : un PEI privé affiche dans la fiche « accès conditionné à l'accord du propriétaire ».
Comment retirer un PEI ?
Enlevez-le du fichier : il est retiré au prochain envoi. S'il revient plus tard avec le même identifiant, il réapparaît. Pour retirer tout le département, écrivez-moi : un envoi vide ne supprime rien, c'est voulu.
Et si notre base n'a pas de débit ?
Envoyez sans. Vos PEI disponibles s'afficheront en bleu, « débit non renseigné ». C'est le cas de plusieurs catalogues publics aujourd'hui, et c'est mieux qu'un débit inventé.
Pourquoi un PEI sans état est-il affiché indisponible ?
Parce que je ne veux pas présenter comme engageable un point dont personne n'a déclaré l'état. Si votre base ne gère pas d'état, envoyez "etat": "disponible" pour les PEI que vous publiez : c'est vous qui le dites, pas moi qui le suppose.
Nous avons plusieurs départements.
Faites un envoi par département, avec code_dept renseigné. La même clé sert pour tous : une source est créée par département au premier envoi.
Notre SIG sait publier en WFS. Faut-il quand même utiliser l'API ?
Non. Si le flux est public, envoyez-moi son adresse : je récupère déjà de cette façon les catalogues publiés sur PIGMA, GeoBretagne, data.calvados.fr, Hydraclic et Ma carte IGN, une fois par semaine. L'API est utile quand vous voulez maîtriser le moment de la mise à jour, ou quand rien n'est publié.

Une question sur le format ? Écrivez-moi à nuno.castro@kilodelta.fr ou passez par le formulaire. Je réponds moi-même, et si un cas n'est pas prévu, j'adapte l'import.

Demander une clé