Appareils et clés d'ingestion
Comment la montre d'un membre, son téléphone ou un agrégateur d'appareils écrit les pas, la fréquence cardiaque et les séances d'entraînement dans Kinora avec une clé personnelle.
Pour le pack Full Stack
Comment les données arrivent
Kinora ne récupère rien depuis Garmin, Fitbit, Apple Health ni aucun autre service. Les données arrivent parce que quelque chose les envoie : la propre clé d'un membre permet à un appareil, une application ou un agrégateur d'appareils d'écrire les chiffres d'activité et les séances d'entraînement de ce membre par une seule porte, /api/ingest.
- Les agrégateurs comme Terra, Rook et Spike relient une fois le compte de montre d'un membre, puis envoient ses données à une adresse que vous leur donnez. Un petit adaptateur à vous convertit leur contenu dans le format ci-dessous et le transmet avec la clé de ce membre.
- L'adaptateur ne fait pas partie du template : c'est la seule partie qui dépend du fournisseur que vous choisissez.
Dans le tableau de bord
- Dans Settings, la carte Connected Devices liste le catalogue d'appareils, chacun connecté ou non, avec sa dernière synchronisation et sa batterie. Le seed livre une montre de sport GPS, le Kinora Band Pro et une balance connectée.
- Connect a data source crée une clé : le membre lui donne un nom, et la clé complète s'affiche une seule fois, pour la copier. Ensuite, seuls ses 12 premiers caractères sont affichés.
- Une clé peut être révoquée à tout moment, et cesse de fonctionner immédiatement.
Les clés
- Une clé désigne exactement un compte. Elle écrit les chiffres d'activité et les séances de ce compte, et rien d'autre.
- En créer une demande
fitness.edit, que seul le rôle Member détient : un jeton de l'équipe répond403. - Une clé est
kin_suivi de 64 caractères hexadécimaux. Le serveur ne conserve que son empreinte SHA-256 et ses 12 premiers caractères : une base de données divulguée ne livre donc à personne une clé valide.
| Méthode | Chemin | Permission | Rôle |
|---|---|---|---|
GET | /api/fitness/devices/keys | fitness.view | Les clés non révoquées du compte, les plus récentes en premier |
POST | /api/fitness/devices/keys | fitness.edit | En crée une ({ name }, de 1 à 80 caractères) et répond avec la clé complète, lisible cette seule fois |
DELETE | /api/fitness/devices/keys/:id | fitness.edit | En révoque une ; 404 api_key_not_found pour une clé qui n'appartient pas au compte |
GET | /api/fitness/devices | fitness.view | Le catalogue d'appareils avec la connexion du compte à chacun |
POST | /api/fitness/devices/:key/toggle | fitness.edit | Connecte ou déconnecte un appareil |
POST | /api/fitness/devices/:key/sync | fitness.edit | Toujours 400 device_sync_unavailable : le serveur ne récupère rien |
Envoyer des données
Chaque route /api/ingest lit la clé dans l'en-tête X-Api-Key et nulle part ailleurs ; un jeton bearer n'y est pas accepté. Une clé manquante répond 401 api_key_missing, une clé inconnue ou révoquée 401 api_key_invalid.
Vérifier la clé
Terminalcurl http://localhost:8000/api/ingest/whoami -H "X-Api-Key: kin_…"Résultat attendu: Il répond avec l'identifiant du compte et le nom de la clé.
Envoyer les chiffres d'une journée
POST /api/ingest/daily-metricsavec une liste de jours. Seuldateest obligatoire ; un chiffre que vous omettez garde sa valeur : une ceinture cardio et un podomètre peuvent donc rapporter la même journée sans s'effacer l'un l'autre. Renvoyer une date corrige cette journée.Corps{ "days": [ { "date": "2026-08-23", "steps": 15342, "distanceKm": 11.4, "activeKcal": 941, "totalKcal": 2680, "floorsClimbed": 14, "exerciseMinutes": 78, "activeMinutes": 96, "standHours": 11, "restingHr": 58, "avgHr": 74 } ] }Résultat attendu:
{ "written": 1 }. Une valeur hors limites (un chiffre négatif,standHoursau-delà de 24, une fréquence cardiaque hors de 20 à 250) répond400.Envoyer des séances d'entraînement
POST /api/ingest/sessionsavec une liste de séances.workoutSlugdoit désigner une séance d'entraînement du catalogue (sinon404 workout_not_found). Une séance est identifiée par son compte, sa séance d'entraînement et son début : la renvoyer ne la compte donc pas deux fois. Chaque séance envoyée est marquée comme faite.Corps{ "sessions": [ { "workoutSlug": "conditioning", "startedAt": "2026-08-23T07:12:00.000Z", "finishedAt": "2026-08-23T07:49:00.000Z", "minutes": 37, "kcal": 412 } ] }
Chaque journée écrite enregistre le nom de la clé comme source, ce qui distingue une journée synchronisée d'une journée saisie à la main. Chaque requête acceptée met à jour la dernière utilisation de la clé.