Dispositivos y claves de ingesta
Cómo el reloj, el teléfono o un agregador de dispositivos de un miembro escribe pasos, frecuencia cardíaca y entrenamientos en Kinora con una clave personal.
Para el paquete Full Stack
Cómo entran los datos
Kinora no extrae datos de Garmin, Fitbit, Apple Health ni de ningún otro servicio. Los datos llegan porque algo los envía: la clave propia de un miembro permite que un dispositivo, una aplicación o un agregador de dispositivos escriba las cifras de movimiento y los entrenamientos de ese miembro por una sola puerta, /api/ingest.
- Los agregadores como Terra, Rook y Spike vinculan una vez la cuenta del reloj de un miembro y luego envían sus datos a una dirección que tú les das. Un pequeño adaptador propio convierte sus datos a la forma de abajo y los reenvía con la clave de ese miembro.
- El adaptador no está en la plantilla: es la única parte que depende del proveedor que elijas.
En el panel
- En Settings, la tarjeta Connected Devices muestra el catálogo de dispositivos, cada uno conectado o no, con su última sincronización y su batería. La carga de datos incluye un reloj deportivo con GPS, la Kinora Band Pro y una báscula inteligente.
- Connect a data source crea una clave: el miembro le pone nombre, y la clave completa se muestra una sola vez, para copiarla. Después solo se muestran sus 12 primeros caracteres.
- Una clave se puede revocar en cualquier momento, y deja de funcionar al instante.
Las claves
- Una clave corresponde exactamente a una cuenta. Escribe las cifras de movimiento y las sesiones de esa cuenta y nada más.
- Crear una necesita
fitness.edit, que solo tiene el rol Member: un token del personal responde403. - Una clave es
kin_seguido de 64 caracteres hexadecimales. El servidor solo guarda su hash SHA-256 y sus 12 primeros caracteres, así que una base de datos filtrada no le da a nadie una clave que funcione.
| Método | Ruta | Permiso | Qué hace |
|---|---|---|---|
GET | /api/fitness/devices/keys | fitness.view | Las claves de la cuenta que no están revocadas, de la más reciente a la más antigua |
POST | /api/fitness/devices/keys | fitness.edit | Crea una ({ name }, de 1 a 80 caracteres) y responde con la clave completa, legible solo esta vez |
DELETE | /api/fitness/devices/keys/:id | fitness.edit | Revoca una; 404 api_key_not_found para una clave que no es de la cuenta |
GET | /api/fitness/devices | fitness.view | El catálogo de dispositivos con la conexión de la cuenta a cada uno |
POST | /api/fitness/devices/:key/toggle | fitness.edit | Conecta o desconecta un dispositivo |
POST | /api/fitness/devices/:key/sync | fitness.edit | Siempre 400 device_sync_unavailable: el servidor no extrae nada |
Enviar datos
Todas las rutas /api/ingest leen la clave de la cabecera X-Api-Key y de ningún otro sitio; ahí no se acepta un token bearer. Una clave que falta responde 401 api_key_missing, y una desconocida o revocada 401 api_key_invalid.
Comprueba la clave
Terminalcurl http://localhost:8000/api/ingest/whoami -H "X-Api-Key: kin_…"Resultado esperado: Responde con el id de la cuenta y el nombre de la clave.
Envía las cifras de un día
POST /api/ingest/daily-metricscon una lista de días. Solodatees obligatorio; una cifra que omites mantiene su valor, así que una banda de frecuencia cardíaca y un podómetro pueden informar del mismo día sin borrarse entre sí. Enviar de nuevo una fecha corrige ese día.Cuerpo{ "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 } ] }Resultado esperado:
{ "written": 1 }. Un valor fuera de rango (una cifra negativa,standHourspor encima de 24, una frecuencia cardíaca fuera de 20 a 250) responde400.Envía entrenamientos
POST /api/ingest/sessionscon una lista de sesiones.workoutSlugdebe indicar un entrenamiento del catálogo (si no,404 workout_not_found). Una sesión se identifica por su cuenta, su entrenamiento y su inicio, así que enviarla de nuevo no la cuenta dos veces. Cada sesión enviada se marca como hecha.Cuerpo{ "sessions": [ { "workoutSlug": "conditioning", "startedAt": "2026-08-23T07:12:00.000Z", "finishedAt": "2026-08-23T07:49:00.000Z", "minutes": 37, "kcal": 412 } ] }
Cada día escrito registra el nombre de la clave como su origen, lo que distingue un día sincronizado de uno introducido a mano. Cada petición aceptada registra el último uso de la clave.