Changelog

Follow up on the latest improvements and updates.

RSS

Wearable devices generate a huge amount of health data — the information is there, but turning it into something meaningful is a challenge.
Companies building health experiences run into the same problem: collecting data is just the beginning. The real work starts when you need to normalize information across devices, combine different metrics, calculate trends, and generate insights users can actually understand and act on.
That's why ROOK built the
User Health Profile
.
One profile, built from hundreds of health signals
The User Health Profile is a new ROOK feature that transforms wearable data into a structured health profile.
Instead of working with dozens of disconnected metrics, developers get a single profile organized into five key areas:
  • Activity
  • Sleep
  • Cardiovascular exercise
  • Recovery
  • Body care
Each profile includes normalized metrics, health scores, historical trends, and personalized insights generated from the user's recent wearable data. The system analyzes the last seven days of health information before generating the profile, giving applications a broader view than individual daily measurements can offer.
Beyond raw data
Collecting health data is relatively straightforward — creating meaningful context is much harder.
The User Health Profile combines multiple processing stages to turn raw wearable data into information applications can use right away:
  • Aggregates health data from multiple sources
  • Calculates standardized scores for each health domain
  • Detects improvements and declines over time
  • Generates personalized insights
  • Delivers the complete profile through a webhook
This lets teams focus on building user experiences instead of designing scoring models, trend calculations, and health interpretation engines from scratch.
Integrate it fast
The User Health Profile integrates directly into your existing ROOK integration.
Customers request a profile through the API, and ROOK handles everything internally — from data validation and aggregation to scoring, storage, and webhook delivery — improving efficiency and response times.
How to integrate User Health Profile
The integration works in two steps:
  1. Your application requests the profile through the API.
  2. ROOK processes the information and sends the result to your webhook.
API request
The
user_profile
endpoint:
POST /api/v2/user_profile
Send only the user identifier:
{
"user_id": ""
}
Example:
curl --request POST \
--url "https://api.tryrook.io/api/v2/user_profile" \
--header "Authorization: Basic <base64(client_uuid:password)>" \
--header "Content-Type: application/json" \
--data '{
"user_id": "user-12345"
}'
ROOK gets the
client_uuid
from authentication and internally generates a
request_id
and the request date. The API responds with
202 Accepted
and returns the request identifier:
{
"message": "User profile request queued",
"request_id": "<uuid>"
}
How it works
ROOK analyzes the user's available data, primarily from the last seven days, and builds five sub-profiles:
  • Activity
  • Sleep
  • Cardio
  • Recovery
  • Body
Each sub-profile can include:
  • Aggregated metrics
  • A score from zero to 100
  • A health level
  • A trend
  • Information about data coverage
The result also includes an overall user score.
What happens if a data point is missing
A missing metric is not interpreted as a bad result.
For example:
  • Having a low step count can produce a low score.
  • Having no step data at all means the value is unknown.
When a metric is missing, ROOK uses the other available metrics. The lack of information is reflected in the profile's confidence or coverage.
When there isn't enough data to calculate a sub-profile, its values may come back as null:
{
"score_int": null,
"level_string": null,
"trend_string": null
}
If there isn't enough information to generate any sub-profile, ROOK doesn't generate or send the profile.
Webhook response
When the profile is ready, ROOK sends it to the configured webhook:
{
"version": 1,
"document_version": <int>,
"data_structure": "user_profile",
"user_id": "<external_id_without_suffix>",
"client_uuid": "<client_uuid>",
"user_profile_data": {
"metadata": {
"datetime_string": "<YYYY-MM-DDTHH:MM:SS.ffffff±HH:MM>",
"user_id_string": "<external_id_without_suffix>",
"request_id_string": "<request_id>"
},
"demographics": { ... },
"profiles": { ... },
"overall": { ... },
"insights": [ ... ]
}
}
Your application must respond to the webhook with
200
,
201
, or
202
. If delivery fails, ROOK schedules retries.
Usage limits
The API allows:
  • Three requests per hour
  • 30 requests within a 24-hour window from the first request
Limits apply per user and per client.
User Health Profile FAQ
What is User Health Profile?
User Health Profile is a ROOK feature that transforms wearable data into a structured health profile.
The profile organizes information into five areas:
  • Activity
  • Sleep
  • Cardio
  • Recovery
  • Body
It also includes scores, trends, and personalized insights.
What problem does it solve?
It lets companies use processed health information without having to build their own aggregation, scoring, trend, and insight systems.
ROOK takes care of converting data from different sources into a consistent, integration-ready structure.
How is a profile requested?
ROOK gets the
client_uuid
from authentication and internally generates a
request_id
and the request date. The API responds with
202 Accepted
and returns the request identifier:
{
"message": "User profile request queued",
"request_id": "<uuid>"
}
Does the API return the profile immediately?
No. The flow is asynchronous.
The API receives the request, and ROOK processes the profile in the background. When the result is ready, we send it to the webhook configured by the client.
What information does ROOK use?
ROOK looks at the user's previously synced data, including:
  • Daily activity
  • Workouts
  • Sleep
  • Heart rate
  • HRV
  • Weight and other body metrics
  • Available demographic information
The main analysis window covers the last seven days. For some recovery calculations, ROOK may look at up to 14 days of sleep data.
Does User Health Profile connect directly to the wearable?
No. The profile is built from data that has already been synced and stored in ROOK. The user must first connect a supported data source and allow their data to sync.
What does each sub-profile include?
Each sub-profile includes:
  • Aggregated metrics
  • A score from zero to 100
  • A level
  • A trend
  • Information about data coverage
The exact information depends on the metrics available for each user.
How are levels interpreted?
Scores are classified as follows:
  • 80–100
    : Optimal
  • 65–79
    : Good
  • 50–64
    : Moderate
  • 30–49
    : Poor
  • Below 30
    : Critical
These values help summarize the available information, but they don't represent a medical diagnosis.
What happens if a metric is missing?
ROOK doesn't interpret missing data as a negative result. For example, having no step data isn't the same as having a low step count. When a metric isn't available, the system uses the other valid metrics and reflects the missing information in the result's coverage or confidence.
How does HRV availability affect the Cardio and Recovery profiles?
HRV is a particularly important metric for the Cardio and Recovery profiles. It accounts for 30% of the Cardio calculation, and in Recovery, HRV together with its variation from baseline accounts for 60% of the score.
If a user's data source doesn't provide HRV, ROOK doesn't interpret the absence as a negative value or assign a score of zero. Instead, it calculates the sub-profile using the available metrics and adjusts the weighting between them. This reduced data availability is reflected in the result's coverage or confidence.
As a result, without HRV, Cardio can be calculated using roughly 70% of the originally weighted metrics, and Recovery around 40%. If other required metrics are also missing, the sub-profile's score, level, or trend may come back as null.
For this reason, Cardio and Recovery offer more complete coverage mainly for users with sources that report HRV, such as Oura, Whoop, Garmin, and Polar. For sources that don't provide HRV, such as Fitbit under current coverage, these sub-profiles may show lower confidence or may not have enough data to be calculated.
What happens if there's no information for a sub-profile?
When there aren't enough metrics to calculate a sub-profile, its fields may come back as null:
{
"score_int": null,
"level_string": null,
"trend_string": null
}
That sub-profile should not be interpreted as a score of zero.
What happens if there isn't enough data to generate any profile?
ROOK doesn't generate or send an empty profile. In that case, processing ends with an internal insufficient-data result, and no webhook is sent.
How is the overall score calculated?
The overall score combines the five sub-profiles with the following weights:
  • Activity: 20%
  • Sleep: 25%
  • Cardio: 25%
  • Recovery: 20%
  • Body: 10%
Sub-profiles without usable data should not be treated as negative values.
How do trends work?
ROOK compares the current score with the last available previous profile for the same user. The trend can be:
  • improving
  • declining
  • stable
  • null
We use a stability band of approximately ±5%. The trend will be null when there's no previous profile or when one of the required scores isn't available.
What are insights?
Insights are observations generated from predefined rules. They can point to:
  • Risks
  • Trends
  • Positive patterns
  • Relationships between different areas of the profile
Each insight includes a confidence value tied to the coverage of the data used to generate it. It does not represent diagnostic certainty.
How many insights can a user receive?
There's no defined maximum limit.
ROOK delivers the insights that meet the rules after removing duplicates and resolving conflicting messages.
How is the profile delivered?
ROOK sends the profile via a POST request to the webhook configured by the client.
Simplified example:
{
"version": 1,
"document_version": <int>,
"data_structure": "user_profile",
"user_id": "<external_id_without_suffix>",
"client_uuid": "<client_uuid>",
"user_profile_data": {
"metadata": {
"datetime_string": "<YYYY-MM-DDTHH:MM:SS.ffffff±HH:MM>",
"user_id_string": "<external_id_without_suffix>",
"request_id_string": "<request_id>"
},
"demographics": { ... },
"profiles": { ... },
"overall": { ... },
"insights": [ ... ]
}
}
What should the webhook respond with?
The client's endpoint must respond with one of these codes:
  • 200 OK
  • 201 Created
  • 202 Accepted
Any other response code — including other 2xx codes such as 204 — or a timeout is treated as a failed delivery. After a successful delivery, ROOK marks the profile as synced.
What happens if the webhook fails?
ROOK keeps the profile pending and attempts to deliver it again, up to 3 additional attempts after the initial failure, following this sequence:
  • First retry: ~2 hours after the initial failure
  • Second retry: ~24 hours after the first retry
  • Third retry: ~24 hours after the second retry
If all four delivery attempts fail (the initial one plus the three retries), ROOK flags the document for deletion after 10 days. The total window is approximately 50 hours.
How can webhook authenticity be verified?
In webhooks compatible with version two, ROOK includes the header:
X-ROOK-HASH
The client must validate this signature before processing the content.
What is document_version?
document_version
identifies the profile's version. The first generation uses version one. When ROOK recalculates the profile, it increments this value. Clients can use it to avoid duplicates or ignore older versions.
Does ROOK recalculate the profile on every request?
Not necessarily. ROOK uses two filters to detect whether the data or metrics changed. When there are no changes, it can reuse the existing profile and resend it to the webhook without running the full processing pipeline.
Does the profile update automatically when new data arrives?
No. The profile is generated on demand. If new data arrives after the calculation, the client must request a new generation.
Are there usage limits?
Yes. Limits apply per client and per user:
  • Three requests per hour
  • 30 requests within a 24-hour window from the first request
When the limit is exceeded, the API responds with
429 Too Many Requests
and includes the following headers so the client can retry correctly:
  • X-RateLimit-Limit-Hour
    : request limit per hour
  • X-RateLimit-Remaining-Hour
    : requests remaining in the current hour
  • X-RateLimit-Limit-Day
    : request limit per day
  • X-RateLimit-Remaining-Day
    : requests remaining in the current day
  • Retry-After
    : seconds to wait before retrying
What happens if the client doesn't have access to the feature?
The API responds with:
{
"error": "Forbidden",
"exception": "feature_not_included",
"path": "/api/v2/user_profile",
"method": "POST"
}
This means the User Health Profile entitlement isn't enabled for the client.
Does User Health Profile provide medical diagnoses?
No. User Health Profile organizes, summarizes, and interprets available data using rules and scoring models. Results should be used as contextual information, not as a medical diagnosis, treatment, or recommendation.
Key Selector is ROOK’s new feature that allows clients to customize the JSON structures they receive. This customization tool solves the challenge of processing unnecessary data volumes by enabling each client to define exactly which variables are relevant to their business model.
Data Structure Configurate 1
Data Overload
ROOK clients previously received complete data structures that included variables not used in their workflows. This resulted in inefficient data processing, higher storage demands, and increased difficulty in filtering critical information within events and summaries across the three health pillars: Body, Physical, and Sleep.
Centralized and Manageable Customization
Key Selector introduces a configuration interface within the ROOK Portal, giving clients full control over their data structure.
  • Pillar management:
    Enables or disables entire health pillars (Body, Physical, Sleep) with a single click.
  • Variable control:
    Users can select or exclude specific key groups within each event or summary.
  • Smart event suppression:
    The system automatically evaluates whether an event should stop being sent if all its keys have been deselected, optimizing webhook traffic.
  • Pre-validation:
    Includes a JSON preview feature so developers can validate the structure before applying changes in production.
Availability and Rollout
The feature is immediately available as a customization tool within the ROOK Portal. By default, all clients will continue receiving the full data structure to ensure compatibility with existing integrations, with the option to enable customization based on their technical needs.
FAQ
What is Key Selector?
It is a customization tool that allows users to tailor the JSON data structures received through ROOKConnect by enabling or disabling specific variables across each health pillar and data structures such as events and summaries.
What problems does this feature solve?
It eliminates unnecessary processing of irrelevant data and improves efficiency when handling large volumes of downstream information.
Does it have any additional cost?
The feature is available as a customization tool within the ROOK Portal at no additional cost.
How does it affect my existing webhooks?
If all keys within an event are deselected, ROOK will stop sending that event entirely. This change will be reflected in your webhook configuration to avoid unnecessary traffic.
Can I revert changes if I disable a variable by mistake?
Yes. Previously disabled variables can be re-enabled without any issues.
Additionally, the ROOK Portal includes a “Reset” button in each section to restore the default configuration, which includes all keys and data groups.
What happens if ROOK adds new metrics or keys in the future?
To prevent data loss, any new key added to the platform will be enabled by default in your data structure.
Is there a risk of breaking my current integration when enabling Key Selector?
No. The system is fully compatible with existing clients, and by default, complete data is delivered until the user decides to manually exclude elements.
How can I ensure the new JSON will work in my system?
Before saving any changes, the portal provides a preview of the configured JSON and allows it to be downloaded for compatibility testing in your development environment. Changes will also be reflected in the JSON Simulator tool.
New Long Term Support (LTS) version of ROOK SDKs,version 4.0.0. This version is designed to maximize the reliability, scalability, and maturity of Health Kit integrations such as Apple Health, Health Connect, and Samsung Health. This update transforms the SDK integration with your app, offering a more stable and predictable environment for developers and customers.
The version 4.0.0 It ensures that every integration with health data sources , more robust, and more predictable for all supported ecosystems:
  • Frameworks móviles: React Native, Flutter y Capacitor.
  • Nativo: iOS y Android (Health Connect y Samsung Health).
Security Update
This release outlines our strategic migration regarding the authentication schema between our backend services and SDKs. We are evolving our current model toward a stateless security architecture, specifically designed to enhance operational efficiency and streamline secret rotation.
Under this new framework, security and verification will be bolstered through mandatory signing of requests. Development teams will now be required to provide their Bundle ID/Package Name along with a secret word. These credentials must be configured directly within the ROOK Portal to ensure seamless and secure communication between services.
This transition represents a significant step forward in our commitment to providing a robust, scalable, and highly secure environment for our global partners.
Important:
Configure your secret word, meaning that this word will sign the requests between ROOK and SDK , you will need the Bundle ID (iOS) and Package Name (Android). If you don't have one of these, you will need to provide your internet domain.
Learn more about how to get this in this article
SDKs focused on stability and control
The update addresses the need to improve the synchronization and data retrieval experience of Apple Health Health Connect, and Samsung Health.
Improved visibility through Notification Webhooks
To transform the operation of the SDKs into a transparent flow, we have integrated Notification Webhook. This will allow us to notify clients of the following events:
  • User created: Notification after successful registration of a new user through the SDK.
{
"client_uuid":"YOUR-CLIENT-UUUID",
"user_id":"EXAMPLE-USER",
"action":"user_created",
"level":"info",
"data_source":"apple" | "healthConnect" | "samsung",
"message":"A new user has been successfully created",
"action_datetime":"2025-07-02T19:23:14.393487",
"environment":"sandbox"
}
  • Permission request: Alert when the SDK launches the permission request pop-up to the user.
{
"client_uuid":"YOUR-CLIENT-UUID",
"user_id":"EXAMPLE-USER",
"action":"permission_request_launched",
"level":"info",
"data_source":"apple" | "healthConnect" | "samsung",
"message":"SDK launched permission request pop-up",
"action_datetime":"2025-07-02T19:23:14.393487",
"environment":"sandbox"
}
  • Background synchronization: Confirmation that the SDK has successfully started collecting data in the background.
{
"client_uuid":"YOUR-CLIENT-UUID",
"user_id":"EXAMPLE-USER",
"action":"background_sync_started",
"level":"info",
"data_source":"apple" | "healthConnect" | "samsung",
"message":"SDK successfully initiated background sync",
"action_datetime":"2025-07-02T19:23:14.393487",
"environment":"sandbox"
}
  • Deleted user: Alert when a user is deleted from the SDK.
{
"client_uuid":"YOUR-CLIENT-UUID",
"user_id":"EXAMPLE-USER",
"action":"user_deleted",
"level":"info",
"data_source":"apple" | "healthConnect" | "samsung",
"message":"User has been successfully deleted",
"action_datetime":"2025-07-02T19:23:14.393487",
"environment":"sandbox"
}
Identification of pre-existing data
From the version 4.0.0, Health records will include a flag to identify historical data.
  • Summaries and events prior to the SDK installation date will have the value true in the pre-existing data field.
  • This allows companies to clearly differentiate between historical information and new data generated after integration with their application.
Mandatory update and notice of important changes
This version introduces significant architectural improvements to the ROOK SDK. Please note that this is a mandatory update containing major changes that will require modifications to your current integration. The SDK version change must be made by September 30, 2026.
FAQ
What is version 4.0.0 LTS?
This is a Long Term Support (LTS) release designed to maximize the reliability, scalability, and maturity of integrations with Health Kits. This update provides a more stable and predictable environment for developers.
Which ecosystems and frameworks does this update support?
Version 4.0.0 is compatible with the following environments:
  • Frameworks móviles: React Native, Flutter y Capacitor.
  • Nativo: iOS, Android (Health Connect) y Samsung Health.
Why is this update mandatory?
This version introduces significant architectural improvements. As it is a mandatory update, it contains important changes that require modifications to each client's current integration. The SDK version change must be made by September 30, 2026.
What improvements does it include for health data management?
The update improves the Apple Health and Health Connect data synchronization and retrieval experience, as well as expanding direct compatibility with Samsung Health.
How can historical data be distinguished from new data?
Starting with this version, logs include a flag to identify pre-existing data. Summaries and events prior to the SDK installation date will have the value "true" in the pre-existing data field. This allows you to differentiate historical information from new data generated after integration.
What specific events trigger the Notification Webhook?
The system will report the following events:
  • User created: After successful registration of a new user through the SDK.
  • Permission request: When the SDK launches the permission request pop-up to the user.
  • Background synchronization: Confirmation that the SDK successfully started collecting data in the background.
  • Deleted user: When a user is removed from the SDK.

new

Integrations Web API

Nutrition Events

In response to the growing demand for nutrition data, we launched theNutrition EventsIn this way, the extraction, transformation, and delivery of nutritional events from multiple connected health data sources can be achieved.
This improvement allows us to process nutrition information from devices like Fitbit (API) and platforms like Apple Health, Health Connect, and Samsung Health (SDKs). Thanks to this advancement, our customers will be able to access standardized nutritional data, processed and delivered according to availability or time intervals, depending on the source.
A unified approach to diverse data
With
Nutrition Events
, the data structure is standardized through the new object
nutrition_event
which encapsulates key information such as:
  • Date and time of the event
  • Fuente del dato (ej. Fitbit, Apple Health, Health Connect o Samsung Health)
  • Nutritional indicators (calories, fats, proteins, carbohydrates, among others)
This standardization allows our partners to receive high-value information, ready for analysis or direct integration into their products.
Key features of Nutrition Events
  • Automated extraction via webhook (Fitbit, Android SDKs) or hourly polling (Apple Health).
  • Unified and validated JSON structure for all events.
  • Fault tolerance with automatic retries and centralized monitoring.
  • Compliance with security standards with internal JWT authentication.
  • Hourly data deliveries for aggregate sources such as Apple Health.
Driving smarter decisions
By offering precise, hourly, ready-to-use nutrition events, this launch significantly expands our customers' analytical capabilities.
Frequently Asked Questions (FAQ)
How does it work?
Nutrition Events operates in two modes:
  • Webhook (immediate):For Fitbit, Health Connect, and Samsung Health. Each notification generates a unique event.
  • Polling (per hour):for Apple Health. The accumulated total is transformed into hourly deltas for each event.
The data is structured in a JSON object of typenutrition_eventwhich includes indicators such as calories, protein, fat, carbohydrates and more, plus metadata such as source, timestamp and physical activity.
What data does a nutrition event include?
Each
nutrition_event
may include the following indicators:
data = {
"created_at": datetime,
"auto_detected": bool,
"client_uuid": str,
"user_id": str,
"datetime": str,
"sources_of_data": str,
"was_the_user_under_physical_activity": bool, # Default: False
"food_intake_number": float | None,
"calories_intake_number": float | None,
"protein_intake_g_number": float | None,
"sugar_intake_g_number": float | None,
"fat_intake_g_number": float | None,
"trans_fat_intake_g_number": float | None,
"carbohydrates_intake_g_number": float | None,
"fiber_intake_g_number": float | None,
"alcohol_intake_g_number": float | None,
"sodium_intake_mg_number": float | None,
"cholesterol_intake_mg_number": float | None,
"non_structured_data": list
}
How is the data delivered?
Events are delivered via webhook to client systems. In the case of Apple Health, events are grouped and delivered hourly with their corresponding deltas, preventing accumulation. Zero values ​​are explicitly included; no values ​​are stored.null.
Does this product replace something that already exists?
No. It's a new data structure. Nutrition Events expands the scope of our platform to include food intake data.
How do I access this feature?
Nutrition Events is available to all customers with active integrations with supported sources (Fitbit, Apple Health, Health Connect, Samsung Health). No additional integration is required, but webhook endpoint configuration is necessary.

new

Integrations Web API

Partial Summaries

This new functionality allows API-based customers to access regular updates of their users' body and physical summaries without waiting until the end of the day.
The end of waiting for daily progress
Previously, the processing of data for daily summaries relied on a final daily synchronization, resulting in periods without information during the day. This limitation prevented clients from providing immediate feedback or behavioral adjustments based on the user's current progress.
With Partial Summaries, this behavior is being addressed by delivering summary updates at four-hour intervals for the pillar of Physical. This solution ensures that information flows continuously through the APIs, automatically consolidating with the final summary, as has been the practice, at the end of the day.
Technical innovation and efficiency
The projectIt has been designed to streamline data visibility while minimizing the consumption of unnecessary resources:
  • Data query: The system performs automatic queries every four hours to refresh the data.
  • Optimization via Webhooks:If a webhook delivers information before the scheduled cycle, it will be delivering the data while avoiding polling, making it more efficient.
  • Detecting changes in Body Summary: Because metrics like height are mostly static, the system only processes updates when it detects manual changes or new, specific measurements.
  • Advanced state management: We have implemented specific logic for sources like Polar, correctly interpreting codes to ensure an uninterrupted flow of data.
Compatibility and Integrity
To facilitate a seamless implementation, partial summaries maintain full consistency with the ROOK structure. This ensures that teams can integrate this functionality into their existing pipelines without modifying their current analysis processes.
The availability of the information is still linked to how often the user syncs their wearable with the original source, but now the ROOK team ensures that, once synced, the data is continuously available.
Likewise, this feature is only available for summaries extracted via the ROOK API from Fitbit, Oura, Polar, Whoop, and Withings.
Frequently Asked Questions
What are Partial Summaries?
It is a ROOK feature that allows customers to access updates to the pillar of Physical in four-hour intervals. Instead of waiting for a single summary at the end of the day, we deliver data periodically to improve visibility of user progress.
What problem does this feature solve?
Previously, there were periods of information "blindness" because the system relied on end-of-day synchronization. This latency prevented applications from providing immediate feedback or behavioral adjustments based on recent user activity.
Do partial summaries replace the final daily summary?
No. These summaries are consolidated and synchronized with the Summary final at the end of the day. The goal is to provide ongoing understanding without losing the integrity of the final consolidated data.
How often is the data updated?
We perform automated polling of source endpoints every four hours. However, if a webhook delivers information before this period, the system logs the data and skips the redundant poll to optimize traffic.
How does this affect API and resource consumption?
The system prioritizes querying dynamic metrics such as steps, activity, and nutrition.
Should I change my current integration structure?
It is not necessary. Partial summaries are consistent with the structure of the ROOK Version 2. This ensures that our customers' existing integration pipelines are compatible without requiring modifications.
Is the data available if the user does not sync their device?
The availability of this information depends on how frequently the user syncs their wearable with its original app (Fitbit, Oura, Polar, Whoop, and Withings). If there is no syncing at the source, we will not receive updated data to process.
How does ROOKScore interact with this partial summary update?
Since ROOKScore is linked to summary generation, a partial ROOKScore will also be generated whenever a partial summary is generated. Therefore, the health score of partially linked users can also be monitored throughout the day.
What is the best way to implement partial summaries?
To implement partial summaries, no additional integration changes are required. If daily summary reception is already integrated, partial summaries will be received through the same channel. Additionally, two variables must be considered to ensure the summaries and partial exams are handled in an organized manner:
  • "document_version": Partial summaries will be delivered with a document version number that allows for accurate tracking of the daily update number. The closing summary for the day will be the final version received.
  • “datetime”: This variable will help us track which day this partial or full summary corresponds to.
For more information on how to use “document_version” and “datetime”, read this article.

new

SDK´s

Integrations Web API

Nutrition Events

In response to the growing demand for nutrition data, we launched theNutrition EventsIn this way, the extraction, transformation, and delivery of nutritional events from multiple connected health data sources can be achieved.
This improvement allows us to process nutrition information from devices like Fitbit (API) and platforms like Apple Health, Health Connect, and Samsung Health (SDKs). Thanks to this advancement, our customers will be able to access standardized nutritional data, processed and delivered according to availability or time intervals, depending on the source.
A unified approach to diverse data
With Nutrition EventsThe data structure is standardized through the new object
nutrition_event
which encapsulates key information such as:
  • Date and time of the event
  • Fuente del dato (ej. Fitbit, Apple Health, Health Connect o Samsung Health)
  • Nutritional indicators (calories, fats, proteins, carbohydrates, among others)
This standardization allows our partners to receive high-value information, ready for analysis or direct integration into their products.
Key features of Nutrition Events
  • Automated extraction via webhook (Fitbit, Android SDKs) or hourly polling (Apple Health).
  • Unified and validated JSON structure for all events.
  • Fault tolerance with automatic retries and centralized monitoring.
  • Compliance with security standards with internal JWT authentication.
  • Hourly data deliveries for aggregate sources such as Apple Health.
Driving smarter decisions
By offering precise, hourly, ready-to-use nutrition events, this launch significantly expands our customers' analytical capabilities.
Frequently Asked Questions
How does it work?
Nutrition Events operates in two modes:
  • Webhook (immediate):For Fitbit, Health Connect, and Samsung Health. Each notification generates a unique event.
  • Polling (per hour):for Apple Health. The accumulated total is transformed into hourly deltas for each event.
The data is structured in a JSON object of typenutrition_eventwhich includes indicators such as calories, protein, fat, carbohydrates and more, plus metadata such as source, timestamp and physical activity.
What data does a nutrition event include?
Each
nutrition_event
It may include the following indicators:
data = {
"created_at": datetime,
"auto_detected": bool,
"client_uuid": str,
"user_id": str,
"datetime": str,
"sources_of_data": str,
"was_the_user_under_physical_activity": bool, # Default: False
"food_intake_number": float | None,
"calories_intake_number": float | None,
"protein_intake_g_number": float | None,
"sugar_intake_g_number": float | None,
"fat_intake_g_number": float | None,
"trans_fat_intake_g_number": float | None,
"carbohydrates_intake_g_number": float | None,
"fiber_intake_g_number": float | None,
"alcohol_intake_g_number": float | None,
"sodium_intake_mg_number": float | None,
"cholesterol_intake_mg_number": float | None,
"non_structured_data": list
}
How is the data delivered?
Events are delivered via webhook to client systems. In the case of Apple Health, events are grouped and delivered hourly with their corresponding deltas, preventing accumulation. Zero values are explicitly included; no values are stored
null
.
Does this product replace something that already exists?
No. It's a new data structure. Nutrition Events expands the scope of our platform to include food intake data.
How do I access this feature?
Nutrition Events is available to all customers with active integrations with supported sources (Fitbit, Apple Health, Health Connect, Samsung Health). No additional integration is required, but webhook endpoint configuration is necessary.
Our ROOKScore is a health score based on 3 pillars of health: Physical Health, Sleep Health and Body Health is fed by several sub-pillars. However, these metrics were previously limited to the total result obtained at the end of the day through the pillar summaries. Therefore, with this improvement, it will be possible to receive the original data from the data sources that make up the ROOKScore throughout the day.
This functionality is designed to offer customers and users greater flexibility in managing biometric data. The new field
non_structured_data_array
allows customers to access metrics from manufacturers such as Oura, Garmin, Polar, Whoop, and Withings directly within ROOKScore's JSON.
Technical value
Previously, customers had to choose between using ROOK's standardized scores or performing additional queries to retrieve the original data from the data source. This update resolves data fragmentation by consolidating both streams into a single data structure.
  • Direct access: Provides the original scores (such as Garmin's Body Battery or Whoop's Strain) unprocessed.
  • Seamless integration: Unstructured data does not affect ROOKScore's internal calculations, guaranteeing the integrity of our predictive models.
  • Real-time update: The system replaces the most recent values ​​within the array to keep the information up to date, avoiding the accumulation of unnecessary historical data.
Implementation
The field
non_structured_data_array
is integrated as an array of objects within the ROOK Score JSON. Each object includes the tag
source_of_data_string
to identify the source of the information.
  • Standardization of labels: In specific cases, we rename certain fields to avoid conflicts. For example, the Oura "
    score
    " value is mapped as
    sleep_score
    or
    activity_score
    depending on the context.
  • Granular data management: For devices like Garmin, where a single Body Battery score is not provided, the array captures granular data showing the evolution of the value throughout the day.
  • Scalability: The structure allows each device to maintain its original format, facilitating the incorporation of future new data sources.
Validation and Activation Guide
To ensure a successful transition to production, our team recommends following this verification workflow:
  • Portal settings: It is imperative to verify that the settings in the ROOKScore portal are enabled to allow data transmission. Likewise, to receive unstructured data, the option to receive unstructured data must be activated in the portal.
  • Version validation: Developers must confirm receipt of the field by reviewing
    document_version
    and the
    datetime_string
    to ensure data synchronization.
  • Scale management: It should be noted that each manufacturer uses different scales. For example, Polar uses a range of one to six for recovery status, while Whoop uses a range of 0 to 21 for strain.
Example of JSON with ROOKScore - Non-Structured Data
{
"data_structure": "health_score",
"version": 2,
"document_version": 1,
"user_id": "testUser",
"client_uuid": "019240e3-64ff-7195-a487-c4728502b190",
"health_score_data": {
"metadata": {
"datetime_string": "2023-12-28T00:00:00.000000Z",
"sources_of_data_array": [
"Oura",
"Polar"
],
"user_id_string": "testUser"
},
"overall_scores": {...},
"physical_health_score": {...},
"sleep_health_score": {...},
"body_health_score": {...},
"non_structured_data_array": [
{
"sleep_score": 80,
"source_of_data_string": "Oura"
},
{
"readiness": {
"score": 26
},
"source_of_data_string": "Oura"
},
{
"daily_activity": 70,
"source_of_data_string": "Polar"
}
]
}
}
FAQ
What is the non_structured_data_array field?
It's a new component within the ROOK Score JSON that allows you to integrate ROOKScore scores and native metrics from various data sources. This field gives our customers the flexibility to access original data without it interfering with ROOK's standardized calculations.
What manufacturer metrics can be accessed through this feature?
Currently, we allow access to data from sources such as Oura, Garmin, Polar, Whoop, and Withings. This includes specific metrics such as Oura's Readiness Score, Garmin's Body Battery, and Whoop's Strain.
How does this new data affect the calculation of my ROOK Score?
It has no effect whatsoever. The ROOKScore scoring model is maintained independently within its own system.
Why do some field names differ from the original names in the data source?
We standardize labels in specific cases to avoid naming conflicts. For example, in the case of Oura, the generic value "
score
" is mapped as
sleep_score
or
activity_score
depending on the context of the data.
How does ROOK handle data from devices that do not provide a unique score?
For data sources that provide granular metrics rather than a single value, such as Garmin's Body Battery, the array captures the evolution of the data throughout the day. This allows the customer to receive the detailed information as delivered by the original provider.
Does this field keep a record of scores for the day?
No, this process does not accumulate historical records within the JSON. The system replaces previous values ​​with the most recent ones to ensure that the information provided is always up-to-date and to avoid processing unnecessary data.
How can I start receiving unstructured data in my API calls?
To enable this feature, the client must verify and activate the corresponding option within the ROOK configuration portal. Once enabled, the field will automatically appear in the ROOK Score JSON object.
What should I consider when interpreting scales from different manufacturers?
It is crucial to consider that each data source uses different measurement criteria. For example, while Whoop uses a scale of 0 to 21 for strain, Polar uses a range of one to six for recovery status.
How can we ensure that unstructured data is synchronized?
We recommend that developers always validate the synchronization of information by reviewing the field
datetime_string
and the version of the document (
document_version
) included in the JSON.
We are pleased to announce the implementation of a new data processing protocol designed to identify, classify, and exclude naps within sleep summaries (sleep_summary). This update ensures that key metrics, such as total sleep duration and sleep efficiency, exclusively reflect the user's primary rest period.
The challenge of sleep data
In the ecosystem of wearables and portable devices, naps often skew health metrics by overlapping with nighttime sleep. To address this, we've developed a four-stage system that standardizes data from multiple sources.
Definition of siesta for ROOK
To properly manage naps, we first need to define what a nap is. We will base this on how Oura classifies naps and primary sleep:
  • Main sleep: This is the longest and most continuous block of sleep that occurs mainly during the night.
  • Nap: Any block of sleep other than main sleep, occurring outside of regular nighttime sleep hours, have a maximum duration of 3 hours.
Identification and exclusion of naps
We use two processes to identify a nap, the first is by label and the second by definition.
  • By tag: First, it detects if the data source provides specific nap parameters, such as Fitbit (isMainSleep), Garmin (naps), Oura (type: late_nap) and Whoop (nap: true).
  • Logically: If the sleep event is less than three hours, it will be discarded as a nap.
  • Filtering based on long sessions: The system discards naps only when a main sleep session is already recorded.
Once sleep sessions are identified as "Siesta", they are discarded to ensure accuracy in the data analysis.
Benefits for the technical ecosystem
This improvement allows access to cleaner, more processed data, eliminating data noise caused by short sleep periods. By centralizing this logic in our data pipeline, we reduce the analytical workload for our clients, allowing them to focus on generating valuable insights for their end users.
Availability and validation
This functionality is directly integrated into the data delivery flow via SDK and API. Technical teams are advised to validate the information using the sleep_start_datetime_string and sleep_duration_seconds_int fields to confirm the correct classification of events.
FAQ
How do we define a nap at ROOK?
A nap is defined as any block of sleep other than the main period of rest. To be classified as such, the session must occur outside the user's usual nighttime sleep schedule and have a minimum duration maximum of 3 hours.
What is the "main dream" under this new protocol?
Main sleep is considered to be the longest and most continuous block of sleep that usually occurs during the night.
Why is it necessary to exclude naps from sleep summaries?
Naps often mix their metrics with those of nighttime sleep, skewing critical data such as total sleep duration and efficiency. The goal of this process is to refine the analysis so that the metrics exclusively reflect the user's primary rest.
How do we identify which sleep sessions are naps?
Our team uses two identification methods:
  • By tag: First, it detects if the data source provides specific nap parameters, such as Fitbit (isMainSleep), Garmin (naps), Oura (type: late_nap) and Whoop (nap: true).
  • Logically: If the sleep event is less than three hours, it will be discarded as a nap.
  • Filtering based on long sessions: The system discards naps only when a main sleep session is already recorded.
What happens if a user only sleeps two hours a day?
Following the filtering logic, if there is no previous main sleep session, the system does not discard that short block, thus avoiding misinterpretations or loss of essential sleep data.
Where is this new functionality integrated?
This update is available directly in the data pipeline and is delivered through our SDKs and APIs.
Through the
Good Implementation Practice
s for
document_version
guide , the aim is to standardize how technical teams manage document versions within integrations with the ROOK SDK and APIs.
This guide helps ensure reliable communication between client systems and ROOK integration, reducing synchronization errors, incompatibilities, and the use of outdated data during integration processes.
Standardization
The initiative aims to prevent common errors stemming from improper version control, such as synchronization failures, incompatibilities between environments, and the transmission of outdated data. With proper implementation of
document_version
, developers can maintain more stable integrations, reduce production issues, and optimize the traceability of collected data.
Technical context
The
document_version
acts as a key identifier within ROOK's data structures. Each submitted data structure includes this version, which allows for validation of the delivered JSON version by referencing an update to a previously extracted and delivered data structure.
{
"client_uuid" : "demoClientUUID" ,
"user_id" : "demoUserId" ,
"version" : 2 ,
"document_version" : 1 ,
"data_structure" : "physical_summary" ,
"physical_health" : {
"summary" : {}
}
}
To avoid these scenarios, ROOK recommends that teams proactively validate and update health data with each new delivery of data structures according to their version.
Principles of good practice
The following recommendations should be followed when integrating ROOK and using datasets:
  • Keep the
    document_version
    updated and synchronized.
  • Record and track changes to the data before and after each dataset delivery.
  • Avoid using outdated versions.
These recommendations aim to strengthen the reliability of the integration ecosystem and significantly reduce the risk of operational errors.
General guidelines
  • document_version
    identifies the most recent state of a user's synchronized data.
  • Whenever the user's data changes (for example, new measurements or updates from the source), the version also changes.
  • ROOK uses this value to determine what information has already been delivered and what still needs to be synchronized.
  • Customers must correctly store, update, and forward the latest
    document_version
    received in each communication.
Synchronization and storage
  • Always save the latest synchronized
    document_version
    .
  • Never manually generate this value; versions are managed exclusively by ROOK.
  • Avoid deleting or resetting previously stored versions.
  • Maintain sequential synchronization to ensure data consistency.
Logs and traceability
It is recommended to record the following in the internal logs:
  • The previous and new value of
    document_version
    in each synchronization.
  • Compatibility or misalignment errors detected.
This facilitates monitoring, debugging, and historical control of changes between versions, allowing for a faster response to incidents or inconsistencies.
Recommended implementation flows
  1. First time you receive a dataset
  • It will arrive with
    document_version: 1
    .
  • Validate the day or time window of the dataset using the
    datetime
    field .
  • Save the entire dataset.
  • Use that version as your initial reference for synchronization and display.
  1. An updated dataset arrives
  • ROOK will send a
    document_version
    greater (for example, 2).
  • Validate the datetime of the dataset, as updates from previous days may arrive.
  • If the dataset corresponds to the same time window, it completely replaces the previous dataset.
  • Save the new
    document_version
    like the current version.
  • From that moment on, all interaction must be synchronized using that version.
  1. If you receive a minor version
  • Example: You have version 2 and you receive version 1.
  • Validates the
    datetime
    of the dataset.
  • Sometimes updates from previous days arrive, but the correct match should always be based on the combination:
    document_version
    +
    datetime
    .
  • If the
    document_version
    is lower, ignore the dataset.
  • Log the event as misalignment.
  1. Using datetime
  • It is not enough to use only
    document_version
    , you must also consider the datetime of the dataset.
  • This is key because ROOK can send updates from previous days, and if only the version is compared, errors such as the following can occur:
  • Example 1: Current day: 20/11/2025, you receive
    document_version = 5
    .
- Then comes a `document_version = 6 `, but from 11/18/2025.
- `datetime` is not validated: You could incorrectly replace the data from the 20th with old data from the 18th.
  • Example 2: You have
    document_version = 5
    from 11/20/2025.
- Then comes `document_version = 3` from 11/19/2025`.
- With the correct logic: That dataset should be ignored, as its version is smaller and corresponds to a previous day.
Document-version flow
Validations and testing
To ensure a stable and consistent
document_version
implementation, it's necessary to validate the integration's behavior under various scenarios. These tests help detect misalignments, update errors, and synchronization issues before going into production.
  • Validate receipt of the first dataset or initial version: confirm that the user correctly receives the initial version.
  • Validate update with new version: ensure that data is replaced correctly when a major version is released.
  • Validate misalignment (minor version): prevent old data from overwriting current information.
  • Validate loss of synchronization: verify that the client can recover the correct state if they lose the saved version.
  • Validate logging: ensure useful traceability for support and debugging.
Implementation Checklist
Correct use of document_version:
  • The client always stores the latest
    document_version
    received. Validate that each received dataset includes
    document_version
    .
1. major version → replace entire dataset
2. minor version → ignore and log in
  • Do not manually edit the
    document_version
    value.
  • It does not mix datasets with different versions.
  • Ensure that the updated dataset replaces the previous one
Technical FAQ
What happens if I don't update the document_version?
If you don't update it, your integration may display outdated or inconsistent data. This often leads to logic errors and problems with the end-user experience.
What do I do if I receive a dataset with a lower document_version?
Ignore it completely. That indicates a misalignment or a resending of old data. The correct thing to do is:
  • Do not replace the current dataset.
  • Record the event in logs.
How do I know if I should replace the dataset?
Very simple:
  • Major version: replaces the entire previous dataset.
  • Same version: You shouldn't receive it, but if it happens, ignore it.
  • Minor version: ignore it and log in as misalignment.
Can I generate the document_version myself?
No. The version is generated solely by ROOK to ensure consistency and traceability. Your integration should only receive, store, and forward it.
What happens if I mix datasets from different versions?
You will generate corrupt or inconsistent data for the end user.
Each dataset represents a complete snapshot of the user's state: they are not mixed, they are replaced.
How do I prove that my implementation is correct?
You must validate:
  • First dataset → version 1 received and stored.
  • Update → major version replaces all data.
  • Misalignment → minor version is ignored.
  • Logging → before/after each version.
  • Recovery → validate behavior if your client “loses” the version.
Why does ROOK use document_version?
For:
  • Ensure that the client always displays the user's latest correct photo.
  • Avoid inconsistencies if old data is resubmitted.
  • Ensure stable synchronization in integrations with many users and sources.
We are announcing the launch of the JSON Simulator, a new tool in the ROOK portal designed to simplify and accelerate the validation of integrations with our API and SDK ecosystem.
The JSON Simulator allows teams to simulate, preview, and send real JSON payloads to their configured webhook, without the need for a physical wearable or data generated by end users. The tool integrates directly with the existing configuration of the ROOK portal.
JSON simulator
Previously, customers needed an active wearable and had to wait for data generation to validate their webhook. With the JSON Simulator, that bottleneck disappears.
The tool allows you to:
  • Send complete and consistent JSON payloads to the customer’s Data Webhook.
  • Preview data by health pillar, structure, and data source.
  • Test pipelines without relying on null values.
  • Generate a generic user_id that does not affect real data.
Key capabilities
  1. Automatic webhook verification: Before generating or sending data, the simulator checks whether the webhook is active to avoid errors or incomplete tests.
  2. Detailed data-source selection: Customers can choose the specific data source, health pillar, and data structure. Only compatible combinations are shown.
  3. Realistic and complete JSON generation: Generated JSON strictly follows ROOK’s Version 2 data structure and reflects the customer’s portal configuration.
  4. Direct webhook delivery: Allows end-to-end integration testing and provides immediate feedback.
  5. Simple flow, guaranteed speed: Generation and delivery take no more than 3 seconds per request.
Impact for customers
The JSON Simulator reduces integration times, removes dependency on wearables for testing, and improves understanding of how data varies across brands and structures. This enables teams to:
  • Train their product without physical devices.
  • Safely validate JSON and dashboards.
  • Ensure their webhooks work correctly before going live.
Availability
The JSON Simulator is available in the ROOK portal under the Tools module. Customers must have a configured webhook to use it; otherwise, they will be redirected to the configuration area.
FAQ
What is the JSON Simulator?
It is a tool in the ROOK portal that allows you to generate, preview, and send real JSON payloads to the customer’s Data Webhook, without physical wearables or real user data.
What is it for?
It speeds up and simplifies integration validation with ROOK’s APIs and SDKs. It enables full-flow testing without waiting for real data or relying on devices.
What problem does it solve?
Previously, customers needed an active wearable to validate webhook reception, which caused delays.
With the JSON Simulator, tests are immediate and fully controlled.
What type of data can I simulate?
You can simulate any JSON available in ROOK’s Version 2 data structure by selecting:
  • Compatible data source/brand
  • Health pillar
  • Structure (Summary, Activity, Heart Rate, etc.)
Are the JSON payloads real or test data?
They are real JSONs based on ROOK’s official structure, but they contain a generic user_id that does not affect your KPIs or real data.
Can I send the JSON directly to my webhook?
Yes. The tool allows you to:
  • Preview the JSON
  • Copy or download it
  • Send it directly to your configured webhook. You’ll always get immediate feedback indicating success or failure.
What happens if my webhook is not active?
The simulator automatically checks its status.
If it’s inactive, you won’t be able to generate or send JSON. The portal will guide you to activate it.
Which portal configurations affect the JSON?
The simulator respects your active settings, such as granularity and other applicable parameters.
Do the JSONs include null values?
You can generate fully populated JSON payloads without nulls—ideal for testing pipelines, dashboards, or transformations.
How long does it take?
Generation and delivery take less than 3 seconds per request.
What concrete benefits does my team get?
  • Faster validations
  • Less dependency on wearables
  • More reliable integrations
  • Better internal technical training
  • End-to-end tests in minutes
Where can I find the JSON Simulator?
In the ROOK portal under Tools → JSON Simulator.
Who can use it?
Any customer with a Webhook already configured in the portal.
If you don’t have one, the system will automatically redirect you to configure it.
Load More