Automatizaciones: tus datos, enviados con una programación
Marrow puede hacer POST de un archivo con tus datos de salud a cualquier URL que elijas, con la frecuencia que elijas, directamente desde el teléfono. Esta página es la referencia: cómo configurar una, qué aspecto tiene cada payload y cómo escribir algo que lo reciba.
Las configuraciones listas para usar con n8n, Zapier, Make, Home Assistant, Google Sheets e InfluxDB están en conexiones.
Todas las guías de Marrow: MCP · Espejo autoalojado · Automatizaciones · Archivos · Soporte
Qué es una automatización
Un trabajo guardado en Exportar, Automatizado: un tipo de datos, un formato, un rango de fechas, una URL, una cadencia. Marrow genera el archivo a partir de su almacén verificado y hace POST a la URL con la app cerrada, después de cada confirmación de sincronización y en cada actualización en segundo plano, siempre que haya pasado la cadencia. Nada pasa por nosotros: el teléfono habla directamente con tu endpoint.
Configurar una
- Pestaña Exportar, Automatizado: actívalo y luego Nueva automatización. Si se crea desde la página de una herramienta (n8n, Zapier, Home Assistant y el resto en conexiones), la automatización lleva el nombre de esa herramienta e indica junto a cada campo lo que la herramienta quiere ahí.
- Dirección: la URL https a la que debe hacer POST. Encabezados: los que necesite tu receptor (un token bearer en
Authorization, unX-Gitlab-Token, lo que sea). Cuando la herramienta no necesita ninguno, Añadir encabezado está en Más opciones. - Datos: Métricas de salud, Entrenamientos, Registro de fuerza, Diario de nutrición, o Síntomas y estado de ánimo, como JSON o CSV. Una automatización lleva un solo tipo, así que crea una por cada tipo que quieras. Cada una que está activada cuenta como una conexión: el plan gratuito mantiene 1 conexión activa a la vez, Marrow Pro hasta 10, incluidas las IA y los servidores.
- Cadencia: cada tantos minutos, horas o días. El rango de fechas, la agregación y el tiempo de espera están en Más opciones.
- Ejecutar ahora envía un primer payload para que puedas comprobar el receptor antes de esperar a la programación.
Rangos de fechas
- Desde la última carrera (predeterminado): todo desde la última ejecución correcta, menos un solape de dos días. HealthKit sigue rellenando un día después de que termine, así que el solape reenvía los días completados hace poco. Conserva en tu lado el último valor por métrica y día y las repeticiones serán inofensivas. Un receptor que estuvo caído un tiempo recibe todos los días perdidos en la primera ejecución que funcione.
- Hoy, Últimos 7 / 30 / 90 días, Último año: ventanas móviles fijas, reenviadas completas en cada ejecución. Elígelas cuando prefieras una instantánea que se corrige sola a un delta.
Formatos del payload
Métricas de salud (totales diarios, JSON)
La misma estructura que las métricas de Health Auto Export (una lista metrics de name, units y data con qty), así que un receptor escrito para esa app solo necesita pequeños cambios: aquí las fechas son días simples, no marcas de tiempo, y los payloads de entrenamientos y fuerza de abajo son propios de Marrow. Los valores están en la unidad almacenada que indica units (kg, m, mL, degC, kcal, count). La frecuencia cardiaca llega como el Avg, Min y Max de cada día en bpm, y el sueño como cada noche con sus fases en horas. Convierte en tu lado si quieres unidades imperiales.
{"data": {"metrics": [
{"name": "body_mass", "units": "kg",
"data": [{"date": "2026-09-11", "qty": 81.3}]},
{"name": "step_count", "units": "count",
"data": [{"date": "2026-09-11", "qty": 8746}]},
{"name": "heart_rate", "units": "bpm",
"data": [{"date": "2026-09-11", "Avg": 71, "Min": 52, "Max": 148}]},
{"name": "sleep_analysis", "units": "h",
"data": [{"date": "2026-09-11", "totalSleep": 7.2, "asleep": 7.2, "deep": 1.1, "rem": 1.6, "core": 4.3, "awake": 0.2,
"sleepStart": "2026-09-10 23:36:00 -0400", "sleepEnd": "2026-09-11 07:02:00 -0400"}]}
]}}
Las muestras sin procesar (la agrupación Muestras sin procesar) envían cada muestra con su hora de inicio y de fin en lugar de un total diario. Las métricas en CSV llegan como la tabla ancha descrita en la página de archivos.
Entrenamientos
{"data": {"workouts": [
{"activity": "Running", "start": "2026-09-11T18:43:41Z", "end": "2026-09-11T19:13:53Z",
"duration_min": 30.2, "kcal": 512, "distance_mi": 3.06, "avg_hr": 174, "source": "Apple Watch"}
]}}
Registro de fuerza
Cada serie de trabajo (los calentamientos se dejan fuera), más el progreso por ejercicio y el volumen por grupo muscular. Los pesos están en la unidad que elegiste en Ajustes, Unidades. El campo unit indica cuál. El set_type de cada serie es work, failure o drop, y una serie también lleva rir cuando registraste repeticiones en reserva. set_credits cuenta las series acreditadas a un grupo muscular, en fracciones cuando un ejercicio trabaja varios grupos.
{"data": {"unit": "lb",
"sets": [{"time": "2026-09-11T17:02:00Z", "session": "Push day", "exercise": "Bench Press",
"set": 1, "weight": 185, "reps": 8, "est_1rm": 229.6, "set_type": "work"}],
"exercises": [{"exercise": "Bench Press", "best_est_1rm": 229.6,
"sessions": [{"date": "2026-09-11T17:02:00Z", "sets": 3, "top_weight": 185, "top_reps": 8, "est_1rm": 229.6, "volume": 3885}]}],
"muscle_groups": [{"group": "Chest", "volume": 3108.0, "set_credits": 2.4}]
}}
Diario de nutrición
{"data": {"days": [
{"day": "2026-09-11", "entries": [
{"meal": "breakfast", "name": "Oatmeal", "grams": 250, "kcal": 300,
"protein_g": 10, "carbs_g": 54, "fat_g": 5, "logged_at": "2026-09-11T12:10:00Z",
"nutrients": {"dietary_fiber": 8.0, "dietary_sugar": 1.2}}
]}
]}}
Escribir un receptor
Vale cualquier cosa que acepte un POST HTTPS y responda 2xx: un servicio de webhooks, una función sin servidor, un script en un servidor casero. Tres reglas lo mantienen robusto:
- Gana el último. Guarda los valores con la clave (métrica, día) o la identidad propia de la entrada y sobrescribe cuando se repitan. Las ventanas se solapan a propósito.
- Archiva primero el cuerpo sin procesar. Luego analízalo. Un error del analizador nunca debería costarte los datos.
- Responde rápido. Marrow espera hasta el tiempo límite que establezcas (60 s por defecto) y si no marca la ejecución como fallida. Las ejecuciones fallidas se reintentan en el siguiente ciclo de la cadencia desde la última ventana correcta.
Un receptor en Python de doce líneas que archiva cada envío:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
class H(BaseHTTPRequestHandler):
def do_POST(self):
body = self.rfile.read(int(self.headers.get("Content-Length", 0)))
with open(f"marrow-{int(time.time())}.json", "wb") as f:
f.write(body)
self.send_response(200)
self.end_headers()
HTTPServer(("0.0.0.0", 8798), H).serve_forever()
Ponlo detrás de HTTPS (un Cloudflare Tunnel, Tailscale Funnel o cualquier proxy inverso) y apunta la automatización hacia él. Si lo que quieres es una copia consultable en lugar de una carpeta de archivos, el espejo autoalojado es ese receptor ya escrito.
Conviene saber
- Las automatizaciones solo se ejecutan cuando iOS deja que la app se ejecute: tras una confirmación de sincronización, al actualizar en primer plano y durante la actualización en segundo plano. Un teléfono que pasa todo el día bloqueado envía cuando se desbloquea de nuevo. La ventana de «Desde la última carrera» cubre el hueco.
- Cada ejecución queda anotada en el Registro de actividad de la automatización (Más opciones) con su resultado, así que una URL mal configurada se ve en la app, no solo en tu servidor.
- Duplica una automatización para reutilizar sus encabezados con otro tipo de datos.
Solución de problemas
Prueba con Ejecutar ahora. La línea de debajo dice qué pasó, y Más opciones, Registro de actividad guarda las últimas 30 ejecuciones con la misma línea. Activa Notificar al ejecutarse (Más opciones) para recibir una notificación en cada ejecución mientras compruebas.
| Lo que muestra Marrow | Qué hacer |
|---|---|
Un resumen de lo que se envió, como 12 diary entries | Entregado: el receptor respondió 2xx. Si no aparece nada en su lado, mira las últimas filas de abajo. |
Server answered 401 o 403 | El receptor quiere un encabezado, o el que añadiste es incorrecto. Comprueba su nombre y valor, incluido Bearer y el espacio que va después. |
Server answered 404 | Dirección incorrecta, o el receptor no está escuchando. En n8n, usa la Production URL y activa el flujo de trabajo. Comprueba que no falte una ruta al final. |
Server answered 405 | La dirección no admite un POST. Apunta al endpoint pensado para recibir datos. |
Server answered 413 | El payload es demasiado grande para el receptor. Elige un rango de fechas más corto, menos métricas, o Totales diarios en lugar de Muestras sin procesar. |
Server answered 500 u otro 5xx | El receptor falló al procesarlo. Mira su propio registro. Archiva primero el cuerpo sin procesar y luego analízalo. |
| Se ha agotado el tiempo de espera de la solicitud | El receptor tardó más que el tiempo de espera. Responde primero y trabaja después, o sube el Tiempo de espera en Más opciones (hasta 300 s). |
| La política de seguridad de transporte de la app requiere el uso de una conexión segura | La dirección es http sin cifrar en internet. Usa https. iOS deja que Marrow use http sin cifrar solo en tu propia red. |
| No se pudo encontrar un servidor con el nombre de host especificado | Una errata en la dirección, o un nombre que solo conoce tu red doméstica. Compruébalo en Safari en el teléfono. |
No valid URL - set an https endpoint first | La dirección está vacía o no empieza por https:// (o http:// en tu propia red). |
Nothing to export in this range | No hay datos de ese tipo en el rango de fechas. Elige un rango más largo en Más opciones, o registra algo primero. |
- Entregado, pero no llega nada. Algunos receptores responden 200 incluso cuando descartan los datos. Home Assistant lo hace con un ID de webhook incorrecto, y la receta de Apps Script con un
?key=incorrecto. Zapier y Make no muestran nada hasta que cargas una muestra en su editor. Mira el historial o el registro del propio receptor. - Las ejecuciones llegan tarde o no llegan. iOS elige el momento de las ejecuciones en segundo plano: después de una sincronización, cuando abres Marrow y durante la actualización en segundo plano. Mantén activada la actualización en segundo plano para Marrow (Ajustes, General, Actualización en segundo plano). El modo de bajo consumo frena las ejecuciones en segundo plano, y un teléfono que pasa todo el día bloqueado envía cuando se desbloquea de nuevo. Desde la última carrera se pone al día en la siguiente ejecución que funcione.
- Un receptor en tu red doméstica. Marrow necesita acceso a la red local para llegar a él: Ajustes, Privacidad y seguridad, Red local. Toca Ejecutar ahora una vez con Marrow abierta para que iOS pueda preguntar. En segundo plano, iOS lo rechaza sin preguntar hasta que hayas respondido.
- Cerrada a la fuerza. Después de deslizar Marrow para cerrarla en el selector de apps, puede que iOS no la despierte en segundo plano hasta que la abras de nuevo.
- Los mismos días llegan dos veces. A propósito: Desde la última carrera reenvía los dos últimos días, porque Apple Health sigue rellenándolos. Conserva el último valor por métrica y día.
- No se activa. Cada automatización activada cuenta como una conexión. El plan gratuito mantiene 1 conexión activa a la vez, Marrow Pro hasta 10: IA, servidores y automatizaciones juntos. Desactiva otra primero.
- Las unidades parecen mal. Las métricas llegan en las unidades almacenadas que indica
units(kg, m, mL, degC, kcal). Las series de fuerza siguen Ajustes, Unidades, y el campounitindica cuál.
Las soluciones para cada herramienta están en su página: n8n, Zapier, Make, Home Assistant, Google Sheets, InfluxDB, cualquier URL.