# Inform Express > Validic Inform provides normalized health data from 400+ wearables (Fitbit, Garmin, Oura, Apple Health, Dexcom, Withings, and more). Inform Express is a self-service sandbox that gives you API credentials in 90 seconds. ## How to Use This — READ FIRST **If you have `inform_signup` or other `inform_*` MCP tools available, use them. Do NOT call the Hub API (d1zuulkom9ggu7.cloudfront.net) directly.** The MCP tools handle signup, provisioning, device connection, and data exploration — the manual API flow is error-prone and only exists as a fallback for environments where MCP is unavailable. The MCP server is at `developers.validiclabs.com/mcp`. To install in Claude Code: ``` claude mcp add --transport http inform-express https://developers.validiclabs.com/mcp ``` **Quick start:** Call `inform_signup` → wait until `status: "provisioned"` (poll with `inform_signup_status` if needed) → call `inform_inspect_schema` → build your app using the **REST API** (`GET /summaries`) directly for health data queries. **Important: Build demo apps with the REST API, not streaming.** The Inform platform supports a streaming/webhook integration for production, but for sandbox exploration and demo apps, always query the REST summaries endpoint directly. Do not build webhook endpoints, streaming ingestion services, or databases for demo apps — just call the REST API. The `inform_guide` tool describes the streaming architecture for production context; ignore it when building demos. --- ## Getting Started If the user wants to integrate health data and doesn't have credentials yet, proactively offer to sign them up. ### 1. Sign Up Call `inform_signup` with no arguments first — it checks for cached credentials and may skip the entire flow (stdio mode only; hosted mode always requires credentials). ``` inform_signup() ``` If no cached credentials, call with registration details: ``` inform_signup({ email: "user@example.com", password: "MyPass123", accountName: "my-health-app" }) ``` The user will receive a 6-digit verification code by email. Once they provide it: ``` inform_signup({ email: "user@example.com", password: "MyPass123", verificationCode: "123456" }) ``` **Two possible outcomes — you MUST handle both:** 1. **`status: "provisioned"`** — Sandbox is ready. Response includes `orgId`, `orgToken`, `refreshToken`, and `userUid`. Proceed to step 2. 2. **`status: "provisioning"`** — Account is verified but sandbox is still being set up. **Do NOT proceed to step 2. You do not have credentials yet.** You must poll `inform_signup_status` until provisioning completes: ``` inform_signup_status({ refreshToken: "" }) ``` **Polling loop:** Call `inform_signup_status` → if `status: "still_provisioning"`, wait 30 seconds and call again. Repeat up to 6 times (3 minutes total). Once it returns `status: "provisioned"` with `orgId`, `orgToken`, `refreshToken`, and `userUid`, proceed to step 2. **Do not call `inform_inspect_schema`, `inform_preview_user_data`, or the REST API until you have `orgId` and `orgToken` from a `"provisioned"` response.** These credentials are required for all subsequent operations. ### 2. Explore Your Sandbox Once you have credentials, use these tools to understand your data: ``` inform_inspect_schema({ orgId, orgToken, refreshToken }) # See actual API response shape — start here inform_preview_user_data({ orgId, orgToken, refreshToken }) # Peek at recent health data inform_check_data_status({ orgId, orgToken, refreshToken }) # Diagnose connectivity and data flow inform_guide() # Production architecture context (streaming vs polling) — skip for demos ``` For demo apps, `inform_inspect_schema` is the most useful tool — it shows you the real response shape so you can build your UI/logic against it. Then query the REST summaries endpoint directly from your app. ### 3. Connect a Device (Optional) ``` inform_connect_device({ source: "garmin", orgId: "", orgToken: "", refreshToken: "" }) ``` Supported sources: `garmin`, `fitbit`, `oura`. Returns a marketplace URL to open in the user's browser for OAuth authorization. Data starts syncing within ~5 minutes after connection. ### 4. Returning Users Check for project-level `.env` / `.env.local` files containing `VALIDIC_ORG_ID` and `VALIDIC_ORG_TOKEN` — if present, skip signup and query health data directly. In stdio mode, `inform_signup()` with no arguments checks `~/.inform-express/credentials.json` for cached credentials automatically. --- ## Querying Health Data — the Inform REST API Once you have credentials from signup, you call the **Validic Inform REST API** directly for health data. This is a different API from the signup/provisioning Hub — different base URL, different auth. **For demo apps, this REST endpoint is all you need.** Call it directly from your app's backend or frontend — no webhooks, no streaming, no database required. | | Hub (signup, handled by MCP) | Inform API (health data) | |-|------------------------------|--------------------------| | Base URL | `https://d1zuulkom9ggu7.cloudfront.net` | `https://api.staging.validic.com` | | Auth | `Authorization: Bearer ` | `?token=` query param | | When to use | Never call directly — use MCP tools | Call directly for health data queries | ### Summaries Endpoint This is the main endpoint. All health data types (activity, sleep, workouts) come from here, distinguished by `category`. ``` GET https://api.staging.validic.com/organizations/{orgId}/users/{uid}/summaries?token={orgToken} ``` **Query parameters:** | Parameter | Required | Description | |-----------|----------|-------------| | token | yes | `orgToken` from signup | | start_date | no | `YYYY-MM-DD`. Defaults to 24h ago. | | end_date | no | `YYYY-MM-DD` | | source | no | Filter by device: `fitbit`, `garmin`, `oura`, etc. | **Full example:** ```bash curl 'https://api.staging.validic.com/organizations/69b9cf8d295bcf54d247f1f3/users/0f0a0564-2da9-478e-bc6e-60ff8bd445a7/summaries?token=11855357ae72c0daa9dcbedd2fb900f0&start_date=2025-01-01' ``` ### Response Format ```json { "data": [ { "category": "daily", "start_time": "2025-01-15T00:00:00Z", "end_time": "2025-01-15T23:59:59Z", "source": { "type": "fitbit", "device": null }, "metrics": [ { "type": "steps", "value": 12847, "unit": "count", "origin": "device" }, { "type": "distance", "value": 10000, "unit": "m", "origin": "device" }, { "type": "active_energy_burned", "value": 570, "unit": "kcal", "origin": "device" }, { "type": "energy_burned", "value": 2572, "unit": "kcal", "origin": "device" } ] } ] } ``` **Key points for parsing:** - Response key is `data` (array of records) - Each record has a `category`, `source`, `start_time`/`end_time`, and `metrics[]` - Each metric has `type`, `value`, `unit`, and `origin` - Distance is in **meters** (divide by 1609.34 for miles) - Calories may appear as `active_energy_burned` (active only) or `energy_burned` (total) ### Record Categories and Metric Types | Category | Source Examples | Metric Types | |----------|---------------|-------------| | `daily` | fitbit, garmin, oura | `steps` (count), `distance` (m), `active_energy_burned` (kcal), `energy_burned` (kcal), `resting_heart_rate` (bpm), `hrv` (ms) | | `sleep` | oura, fitbit, garmin | `sleep_score` (score). Total duration = `end_time` minus `start_time`. Sleep stages in `segments[]` array, each with `category`: `deep`, `rem`, `light`, `awake`. | | `workout` | fitbit, garmin | `distance` (m), `energy_burned` (kcal), `heart_rate_average` (bpm) | ### About Seed Data New sandbox users are provisioned with ~5 days of synthetic Fitbit daily activity data. **Seed data dates are typically 2-4 weeks in the past**, not today. To see seed data, set `start_date` to 30+ days ago. For real-time data, connect an actual device. --- ## MCP Tools Reference These tools are available when the MCP server is connected. Call `inform_signup` first to obtain credentials, then pass `orgId`, `orgToken`, and `refreshToken` to subsequent tools. ### inform_signup (Transactional) Orchestrate the full signup flow: register, verify email, login, and provision sandbox. Returns `orgId`, `orgToken`, `refreshToken`, and `userUid` on success — pass these to subsequent tool calls. ``` inform_signup() # Check for cached credentials inform_signup({ email, password, accountName }) # Start registration inform_signup({ email, password, verificationCode }) # Complete verification and login ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | email | string | no | Email address for registration or login | | password | string | no | Password (8+ chars, uppercase, lowercase, digit) | | accountName | string | no | Account name (3-255 chars) | | verificationCode | string | no | 6-digit email verification code | ### inform_signup_status (Transactional) Check sandbox provisioning status after signup. Use when `inform_signup` returns `status: "provisioning"` — pass the `refreshToken` from that response. Returns full credentials once provisioning is complete. ``` inform_signup_status({ refreshToken: "" }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | refreshToken | string | yes | Refresh token returned by `inform_signup` | **Returns:** - `status: "provisioned"` with `orgId`, `orgToken`, `refreshToken`, `userUid`, and `env_vars` — sandbox is ready - `status: "still_provisioning"` — try again in 30 seconds ### inform_connect_device (Transactional) Connect a wearable device via OAuth. Returns a marketplace URL for browser auth. ``` inform_connect_device({ source: "garmin", orgId, orgToken, refreshToken }) inform_connect_device({ source: "fitbit", uid: "", orgId, orgToken, refreshToken }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | source | string | yes | Device source: `garmin`, `fitbit`, or `oura` | | uid | string | no | User UID to connect (defaults to first user) | | orgId | string | yes (hosted) | Inform org ID from signup | | orgToken | string | yes (hosted) | Inform org token from signup | | refreshToken | string | yes (hosted) | Refresh token from signup | ### inform_guide (Referential) Get architectural guidance on streaming vs REST polling patterns and the migration path to production. ``` inform_guide() ``` No parameters. ### inform_inspect_schema (Referential) Fetch a real sample API response from your sandbox to see the actual data shape. ``` inform_inspect_schema({ orgId, orgToken, refreshToken }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | dataType | string | no | Data type to inspect (default: `summaries`) | | orgId | string | yes (hosted) | Inform org ID from signup | | orgToken | string | yes (hosted) | Inform org token from signup | | refreshToken | string | yes (hosted) | Refresh token from signup | ### inform_check_data_status (Referential) Diagnose connectivity and data flow. Checks provisioning status, connected devices, and data availability. ``` inform_check_data_status({ orgId, orgToken, refreshToken }) inform_check_data_status({ uid: "", orgId, orgToken, refreshToken }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | uid | string | no | Specific user UID to check (defaults to first user) | | orgId | string | yes (hosted) | Inform org ID from signup | | orgToken | string | yes (hosted) | Inform org token from signup | | refreshToken | string | yes (hosted) | Refresh token from signup | ### inform_org_summary (Referential) Get a bird's-eye view of your organization: users, connected devices, data volume, and date ranges. ``` inform_org_summary({ orgId, orgToken, refreshToken }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | orgId | string | yes (hosted) | Inform org ID from signup | | orgToken | string | yes (hosted) | Inform org token from signup | | refreshToken | string | yes (hosted) | Refresh token from signup | ### inform_preview_user_data (Referential) Quick peek at a user's recent health data, formatted as a day-by-day summary. ``` inform_preview_user_data({ orgId, orgToken, refreshToken }) inform_preview_user_data({ uid: "", days: 30, orgId, orgToken, refreshToken }) ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | uid | string | no | User UID to preview (defaults to first user) | | days | number | no | Number of days to look back (default: 7). Seed data is 2-4 weeks old, so use 30 for new accounts. | | orgId | string | yes (hosted) | Inform org ID from signup | | orgToken | string | yes (hosted) | Inform org token from signup | | refreshToken | string | yes (hosted) | Refresh token from signup | --- ## Appendix: Manual API Flow (only if MCP is unavailable) **Stop. If you have `inform_*` MCP tools available, do not use this section.** This manual flow is only for environments where the MCP server cannot be installed. ### Register Ask the user for email, password (8+ chars, uppercase, lowercase, digit), and account name (3-255 chars). ``` POST https://d1zuulkom9ggu7.cloudfront.net/auth/register Content-Type: application/json {"email": "", "password": "", "accountName": ""} ``` Returns: `{ "message": "Verification email sent", "userSub": "" }` ### Verify Email The user will receive a 6-digit code at their email. ``` POST https://d1zuulkom9ggu7.cloudfront.net/auth/verify Content-Type: application/json {"email": "", "code": "<6_digit_code>"} ``` Returns: `{ "message": "Email verified" }` ### Log In ``` POST https://d1zuulkom9ggu7.cloudfront.net/auth/login Content-Type: application/json {"email": "", "password": ""} ``` Returns: `{ "idToken": "", "accessToken": "", "refreshToken": "" }` ### Get Sandbox Credentials Poll with `idToken`. Provisioning takes up to 60 seconds. ``` GET https://d1zuulkom9ggu7.cloudfront.net/sandbox Authorization: Bearer ``` While provisioning: `{ "orgId": "...", "status": "provisioning" }` When ready: `{ "orgId": "", "orgToken": "", "status": "provisioned", "users": [...] }` ### Refresh Session (returning users) ``` POST https://d1zuulkom9ggu7.cloudfront.net/auth/refresh Content-Type: application/json {"refreshToken": ""} ``` Returns: `{ "idToken": "" }` — then call `GET /sandbox` with the new `idToken`. --- ## Links - [Inform REST API Documentation](https://developer.validic.com) - [Example Apps](https://github.com/Validic-labs/inform-examples) - [MCP Server](https://developers.validiclabs.com/mcp) - [Supported Devices](https://www.validic.com/features/supported-devices)