Équipements et personnes

Le site, son personnel, ses zones et ses machines — la carte fixe à laquelle se rattache chaque relevé de température.

Voici les choses qui ne bougent pas : le restaurant lui-même, les personnes qui y travaillent, les zones dans lesquelles il est découpé, et les machines qui maintiennent les denrées à une température. Rien de tout cela n'est un contrôle.

Cela décide pourtant de ce que veulent dire les contrôles. Une température est un nombre sans verdict attaché tant que vous n'avez pas lu les seuils sur l'équipement où elle a été prise, et un relevé n'appartient à une partie du bâtiment que parce que l'équipement dit dans quelle zone il se trouve. Ratez cette page et tous les chiffres en aval sont faux en silence.

CollectionPortéeCe qu'est un enregistrement
restaurantsrestaurants:readLe site lui-même : nom, adresse, jours de fermeture, paramètres.
usersusers:readUn compte du personnel qui enregistre des contrôles.
areasareas:readUne zone dans laquelle le site est découpé — cuisine, chambre froide, bar.
equipmentequipment:readUn réfrigérateur, un congélateur, un équipement de la chaîne du froid, avec ses seuils.
sensorssensors:readUne sonde sans fil, par adresse MAC.
cooking-equipmentcooking-equipment:readUn four ou un autre équipement de cuisson, avec ses seuils.

Toutes les six partagent l'enveloppe d'instantané : id, deleted, capturedAt, receivedAt, sequence et le reste entourent le data décrit ci-dessous.

restaurants

Le site auquel votre clé est limitée, sous forme d'enregistrement. Un par restaurant : cette collection tient donc en général sur une seule page.

ChampTypeSignification
namestring, obligatoireLe nom du site, tel qu'il est affiché dans l'application.
addressstring, obligatoireL'adresse postale, en une seule chaîne de caractères.
closingDaysstring[], obligatoireLes jours où le site est fermé. Des chaînes simples, que le schéma ne contraint pas.
exceptionalClosuresobject[]Les fermetures ponctuelles, chacune un objet avec from et to.
detailedAddressobject | nullL'adresse découpée en parties, quand l'application la détient ainsi.
deliveryAddressstring | nullOù les marchandises sont livrées, quand cela diffère d'address.
deliveryDetailedAddressobject | nullLa même, en parties.
preferredLanguagestring | nullLa langue dans laquelle le restaurant travaille.
multiAreaboolean | nullSi le site est découpé en plus d'une zone.
settingsobject | nullLes paramètres de l'application. La forme appartient à l'application et elle bouge.
{
  "id": "e5a1d3c9-7b40-4a28-9df6-18c0b2e46a75",
  "collection": "restaurants",
  "deleted": false,
  "capturedAt": "1789300481002",
  "receivedAt": "1789300489517",
  "sequence": "7",
  "data": {
    "name": "Le Comptoir de Nanterre",
    "address": "12 rue des Anciennes Mairies, 92000 Nanterre",
    "closingDays": ["sunday"],
    "preferredLanguage": "fr",
    "multiArea": true
  }
}

L'exemple ne montre que la moitié opérationnelle. À côté, l'enregistrement porte la moitié commerciale : subscription, subscriptions, companyName, billingAddress, billingEmail, tvaNumber, trialEndDate, customerId, discount. Ils existent, ils sont dans le document OpenAPI, et cette page ne vous les expliquera pas.

Lisez les champs opérationnels et laissez les champs commerciaux tranquilles. Ils décrivent le contrat du restaurant avec nous, pas sa cuisine. Ce n'est pas une API de facturation, ils changent pour des raisons qui n'ont rien à voir avec la sécurité alimentaire, et une intégration qui renvoie à un client l'état de son abonnement est un ticket de support en devenir.

closingDays est une liste de chaînes simples. Le schéma ne leur impose aucune forme : lisez-les et affichez-les ; n'aiguillez pas dessus et ne supposez ni orthographe ni casse particulière.

users

Les comptes du personnel qui enregistrent les contrôles. C'est vers eux que pointe le userId d'un enregistrement de température.

ChampTypeSignification
firstNamestring, obligatoireLe prénom, tel qu'il a été saisi.
lastNamestring, obligatoireLe nom de famille, tel qu'il a été saisi.
emailstring, obligatoireL'adresse e-mail du compte.
phoneNumberstring | nullUn numéro de contact, quand il a été donné.
modulesstring[]Les parties de l'application que cette personne utilise. Des chaînes libres.
preferredNotificationTimestring | nullQuand cette personne a demandé à être rappelée.
isChildrenboolean | nullUn indicateur interne. Le schéma ne lui donne aucun sens ; ne construisez rien dessus.
isDeletedboolean | nullL'indicateur de retrait propre à l'application — et il peut être null ici, contrairement à ailleurs.
{
  "id": "2774953d-8d9b-4a68-8ec4-1209edd90777",
  "collection": "users",
  "deleted": false,
  "capturedAt": "1789315002664",
  "receivedAt": "1789315010218",
  "sequence": "31",
  "data": {
    "firstName": "Amina",
    "lastName": "Berthier",
    "email": "amina.berthier@example.test",
    "phoneNumber": null,
    "modules": ["temperatures", "cleaning"],
    "isDeleted": false
  }
}

Ce sont des données personnelles. email, phoneNumber et les deux champs de nom identifient une personne réelle, et ils sont dans cette API pour une seule raison : un enregistrement de sécurité alimentaire doit dire qui a effectué le contrôle. C'est leur unique rôle ici.

Stockez donc l'id et résolvez un nom d'affichage quand vous en avez besoin. Ne recopiez pas les coordonnées dans vos propres tables, vos journaux, vos événements d'analyse ou un outil tiers sous prétexte qu'elles se trouvaient dans la charge utile. Le restaurant est le responsable de traitement pour son personnel, et chaque copie que vous faites est une copie dont il doit désormais rendre compte.

isDeleted peut être null sur cette collection alors qu'il est obligatoire ailleurs : traitez un indicateur absent comme « non retiré » plutôt que de le laisser passer pour un faux par accident. La différence entre lui et le deleted de l'enveloppe est expliquée sur la page du catalogue.

areas

Une zone du restaurant. Deux champs, et bien plus importante que deux champs ne le laissent croire.

ChampTypeSignification
namestring, obligatoireLa zone telle que le restaurant la nomme — cuisine, chambre froide, bar.
isDeletedboolean, obligatoireL'indicateur de retrait de l'application. Voyez la page du catalogue.
{
  "id": "9c2b17ae-4d80-4f55-b3e1-0a6c8f4d2b19",
  "collection": "areas",
  "deleted": false,
  "capturedAt": "1789301120440",
  "receivedAt": "1789301126871",
  "sequence": "12",
  "data": {
    "name": "Chambre froide",
    "isDeleted": false
  }
}

areaId est ce qui permet de tout grouper par zone. Les équipements, les équipements de cuisson, les friteuses et les tâches de nettoyage en portent tous un, et c'est le seul lien entre un relevé et une partie du bâtiment. Il n'y a pas d'areaId sur les enregistrements eux-mêmes : vous y arrivez par l'équipement.

areaId peut être null partout où il apparaît. Un réfrigérateur sans zone est normal — cela veut dire que personne ne la lui a attribuée, en général sur un site d'une seule pièce où multiArea est faux. Groupez ceux-là sous « non attribué » plutôt que de les jeter.

equipment

Réfrigérateurs, congélateurs et autres équipements de la chaîne du froid. L'enregistrement qui décide si une température était acceptable.

ChampTypeSignification
indexinteger, obligatoireLa position que le restaurant lui a donnée dans sa propre liste. Un ordre d'affichage, pas un identifiant.
typestring, obligatoireLe genre d'équipement dont il s'agit. Une chaîne non contrainte — lisez-la, n'aiguillez pas dessus.
namestring, obligatoireLe nom que la cuisine lui donne.
minnumber | nullLa température la plus basse acceptable.
maxnumber | nullLa température la plus haute acceptable.
areaIdstring | nullLa zone où il se trouve.
equipmentSensorIdstring | nullLa sonde qui y est installée, quand il y en a une.
statestring | nullL'état actuel de l'équipement, sous forme de chaîne non contrainte.
outOfRangeCountnumber | nullUn décompte des relevés hors plage que l'application tient à jour.
isDeletedboolean, obligatoireL'indicateur de retrait de l'application.
{
  "id": "84ce5c13-3237-40d4-901a-cbba59a6406f",
  "collection": "equipment",
  "deleted": false,
  "capturedAt": "1789302455901",
  "receivedAt": "1789302461330",
  "sequence": "58",
  "data": {
    "index": 2,
    "type": "freezer",
    "name": "Congélateur bas",
    "min": -22,
    "max": -18,
    "areaId": "9c2b17ae-4d80-4f55-b3e1-0a6c8f4d2b19",
    "equipmentSensorId": "b31f7d64-0e29-42ca-9a57-51d3c8e07f28",
    "state": "ok",
    "outOfRangeCount": 0,
    "isDeleted": false
  }
}

min et max sont le seul verdict que vous obtiendrez. Un enregistrement de température porte une valeur, une heure et l'équipement sur lequel elle a été prise — rien qui dise si c'était bon. -14,4 °C est une crise dans un réfrigérateur et un mardi ordinaire dans un congélateur, et c'est cet enregistrement qui fait la différence entre les deux. Tous les chiffres de conformité que vous construisez passent par cette jointure.

Ils peuvent aussi être null. Quand min ou max est absent, vous n'avez pas de seuil, et la réponse honnête pour ce relevé est « inconnu », pas « dans la plage ». Dites-le dans votre interface plutôt que de basculer par défaut sur le vert.

Les seuils sont ceux d'aujourd'hui, pas ceux qui s'appliquaient. L'instantané vous donne les min et max du jour ; un relevé de mars a été jugé sur ce qui était réglé en mars, et le restaurant peut les changer à tout moment. Si vous réévaluez d'anciens relevés avec les chiffres d'aujourd'hui — ce qui est tout ce que cette API permet — présentez le résultat comme votre recalcul, pas comme ce que la cuisine a vu.

type et state sont des chaînes non contraintes. Ce sont dans le schéma deux simples champs de texte libre, sans aucune liste derrière. Affichez-les, groupez dessus s'il le faut, et ne laissez jamais une valeur non reconnue traverser un aiguillage pour tomber dans le silence.

outOfRangeCount est le chiffre de l'application, pas le vôtre. Le schéma ne dit pas quelle fenêtre il couvre, et vous ne pouvez pas le reconstruire à partir des instantanés disponibles ici. Traitez-le comme un signal venu de l'application, et si vous avez besoin d'un décompte défendable, calculez le vôtre à partir des relevés et des seuils, et présentez-le comme le vôtre.

equipmentSensorId pointe de l'équipement vers sa sonde. L'enregistrement de la sonde pointe dans l'autre sens. Les deux côtés peuvent être null, et rien ne garantit que l'un soit renseigné parce que l'autre l'est.

sensors

Les sondes sans fil. Deux champs, tous les deux facultatifs.

ChampTypeSignification
macAddressstring | nullL'adresse matérielle de la sonde — c'est ainsi que vous distinguez un appareil physique d'un autre.
sensorEquipmentIdstring | nullL'équipement que cette sonde surveille.
{
  "id": "b31f7d64-0e29-42ca-9a57-51d3c8e07f28",
  "collection": "sensors",
  "deleted": false,
  "capturedAt": "1789302501764",
  "receivedAt": "1789302509002",
  "sequence": "61",
  "data": {
    "macAddress": "F4:12:9D:3A:77:0B",
    "sensorEquipmentId": "84ce5c13-3237-40d4-901a-cbba59a6406f"
  }
}

Notez les deux noms de champ, qui sont l'image l'un de l'autre et faciles à intervertir : l'équipement porte equipmentSensorId, la sonde porte sensorEquipmentId. Lisez le mauvais et vous obtenez undefined, sans erreur.

Il n'y a pas de nom ici, pas de niveau de batterie et pas de date de dernière vue. Ce qu'une sonde a remonté est sur temperature-readings, et ces relevés sont indexés sur equipmentId plutôt que sur la sonde — si bien qu'une sonde devenue muette ressemble exactement à une sonde qui n'avait rien à remonter.

cooking-equipment

Fours, armoires de maintien et le reste du côté chaud. Même idée qu'equipment, la mécanique de la chaîne du froid en moins.

ChampTypeSignification
indexinteger, obligatoireL'ordre d'affichage dans la liste du restaurant.
typestring, obligatoireLe genre d'équipement dont il s'agit. Chaîne non contrainte.
namestring, obligatoireLe nom que la cuisine lui donne.
minnumber | nullLa température la plus basse acceptable.
maxnumber | nullLa température la plus haute acceptable.
areaIdstring | nullLa zone où il se trouve.
isDeletedboolean, obligatoireL'indicateur de retrait de l'application.
{
  "id": "3d90f4c8-62b7-4e13-8a05-ff71d6b9c204",
  "collection": "cooking-equipment",
  "deleted": false,
  "capturedAt": "1789303880115",
  "receivedAt": "1789303887640",
  "sequence": "64",
  "data": {
    "index": 1,
    "type": "oven",
    "name": "Four à sole",
    "min": 63,
    "max": 260,
    "areaId": "9c2b17ae-4d80-4f55-b3e1-0a6c8f4d2b19",
    "isDeleted": false
  }
}

Pas de state, pas d'outOfRangeCount, pas de sonde : les équipements de cuisson sont lus par une personne, rien ne les surveille donc entre deux contrôles. Leurs relevés sont les cooking-temperature-records, qui pointent ici avec cookingEquipmentId — un nom de champ différent de celui de la chaîne du froid, et l'endroit habituel où un client ne lit rien en silence.

Lire la carte

Tout ce qui est sur cette page est petit, lent à bouger et nécessaire avant qu'aucune autre collection n'ait de sens.

  • Chargez-la en premier et gardez-la. Parcourez areas, equipment, cooking-equipment et sensors avant de parcourir la moindre collection d'enregistrements, et résolvez les noms et les seuils depuis votre propre copie plutôt qu'enregistrement par enregistrement.
  • Actualisez-la quand même. Les équipements sont renommés, les seuils sont corrigés, un réfrigérateur passe dans une autre zone. Une copie prise une fois et jamais reparcourue dérive sans jamais tomber en panne.
  • Gardez les identifiants, pas les copies — surtout pour les personnes. Stockez le userId et résolvez un nom au moment de l'affichage. Voyez la note sur les données personnelles ci-dessus.
  • Les deux indicateurs de suppression, partout. Le deleted de l'enveloppe et l'isDeleted de data sont deux choses différentes, et la page du catalogue explique lequel est lequel.

Dernière mise à jour 2026-09-20.