# Junction API Source: https://docs.junction.com/api-details/junction-api Overview of the Junction API including production and sandbox environments, regional endpoints, authentication methods, and core API capabilities. You use Junction API to: * manage users and demographic information in your Team with the [Core API](/api-reference/user/create-user); * manage user connections, pull ingested device data, and inspect connection backfill statuses through the [Devices API](/wearables/connecting-providers/introduction); * order lab tests, manage appointments and pull the results through the [Lab Testing API](/lab/overview/introduction); and * aggregate ingested device data with the [Junction Sense API](/sense/overview). For managing Team configuration and Org resources programmatically, see [Junction Management API](/api-details/junction-management-api). ## Environments Junction provides two Sandbox environments and two Production environments today: | Environment | Base URL | Team API Key Prefix | | ------------------ | -------------------------------------- | ------------------- | | πŸ‡ΊπŸ‡Έ Production US | `https://api.us.junction.com/` | `pk_us_*` | | πŸ‡ͺπŸ‡Ί Production EU | `https://api.eu.junction.com/` | `pk_eu_*` | | πŸ‡ΊπŸ‡Έ Sandbox US | `https://api.sandbox.us.junction.com/` | `sk_us_*` | | πŸ‡ͺπŸ‡Ί Sandbox EU | `https://api.sandbox.eu.junction.com/` | `sk_eu_*` | If you are using a `*.tryvital.io` Base URL, they are still supported alongside `*.junction.com`. Sandbox environments are functionally identical to Production environments, except that: 1. Each Team can have only up to 50 Users in Sandbox; 2. You can create [Synthetic Device connections](/wearables/providers/test_data); and 3. You can [simulate and transition an order through its lifecycle](/lab/overview/sandbox). ## Authentication Junction API accepts two team-scoped credential types β€” pick one per request. | Credential | Lifetime | Header | Provisioned via | | --------------------------------------------------------------------------------------------------------- | ------------------------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Team API Key](/api-reference/org-management/team-api-keys/create-team-api-key) | Long-lived until revoked | `X-Vital-API-Key: ` | Team Config page in the [Junction Dashboard](https://app.junction.com) or [Create Team API Key](/api-reference/org-management/team-api-keys/create-team-api-key) | | [Team API Access Token](/api-reference/org-management/team-api-access-token/create-team-api-access-token) | Several minutes | `Authorization: Bearer ` | Created programmatically via [Create Team API Access Token](/api-reference/org-management/team-api-access-token/create-team-api-access-token) | ### When to use a Team API Key Choose a Team API Key when your system can safely store a pre-shared secret and you intend to issue separate team-scoped keys to your own divisions or environments. Keys are listed and rotated from the Team Config page in the [Junction Dashboard](https://app.junction.com), or programmatically through the Management API via [Create Team API Key](/api-reference/org-management/team-api-keys/create-team-api-key). ```bash cURL theme={null} curl --request GET \ --url 'https://api.us.junction.com/v2/providers' \ --header 'X-Vital-API-Key: ' ``` ### When to use a Team API Access Token Choose a Team API Access Token when you are integrating Junction into a multi-tenant EMR or similar platform and need to act on behalf of many customer teams without provisioning and storing a Team API Key for each one. Mint a token on demand from your backend by calling the Management API endpoint [Create Team API Access Token](/api-reference/org-management/team-api-access-token/create-team-api-access-token) with your Management Key, then call Junction API with the returned token. ```bash cURL theme={null} curl --request GET \ --url 'https://api.us.junction.com/v2/providers' \ --header 'Authorization: Bearer ' ``` Tokens are short-lived (several minutes) and the Create Team API Access Token endpoint is rate limited. Cache and reuse each token until it expires rather than minting per request. When a Junction API call returns `401 Unauthorized`, mint a fresh token by calling the endpoint again, then retry the request. A [Management Key](/api-details/junction-management-api) used by Junction Management API does not function as a Team API Key. However, you can provision Team API Keys and mint Team API Access Tokens through a Management Key. ## Junction Mobile SDKs [Junction Mobile SDKs](/wearables/sdks/) support two authentication methods: | Scheme | Authorization | Recommended use case | | ---------------------------------------------------------------------- | --------------------- | ---------------------- | | [Sign-In Token](/wearables/sdks/authentication#junction-sign-in-token) | User-scoped access | Production mobile apps | | [Team API Keys](/wearables/sdks/authentication#junction-team-api-keys) | Full Team data access | Proof-of-concept | Refer to the [Mobile SDK Authentication](/wearables/sdks/authentication) documentation for more information. # Junction Management API Source: https://docs.junction.com/api-details/junction-management-api Use the Junction Management API to programmatically manage organization resources like teams, members, API keys, and ETL pipelines. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. You use Junction Management API to: * manage Junction Org resources, such as [Teams](/api-reference/org-management/team/create-team) and [Members](/api-reference/org-management/member/list-members); * manage Team configurations across both Sandbox and Production environments, such as: * [Team features and brand information](/api-reference/org-management/team/update-team); * [Team ETL Pipelines](/api-reference/org-management/team-etl-pipeline/upsert-team-etl-pipelines); * [Team Custom Credentials](/api-reference/org-management/team-custom-credentials/upsert-team-custom-credentials); and * [Team Continuous Query](/api-reference/sense/continuous-query/create); * integrate Junction Dashboard experiences into your web application with [Junction Connect](/connect/overview) β€” see [Junction Connect in the Management API Reference](/api-reference/org-management/connect/junction-connect) for the endpoints involved. Note that you can access a lot of Junction Management API functionalities through the [Junction Dashboard](https://app.junction.com/) as well. For device and lab testing access, see [Junction API](/api-details/junction-api). ## Environments There is one production environment for Junction Management API: | Environment | Base URL | Management Key Prefix | | ------------- | -------------------------------------- | --------------------- | | πŸ€– Production | `https://api.management.junction.com/` | `mg_*` | ## Authentication Junction Management API accepts a **Management Key**. Enterprise customers can request a Management Key through your Junction Customer Success Manager. Your API requests should present the Management Key under the `X-Management-Key` header. For example: ```bash cURL theme={null} curl --request GET \ --url "https://api.management.junction.com/v1/org/${ORG_ID}" \ --header 'X-Management-Key: ${YOUR_MANAGEMENT_KEY}' ``` A [Team API Key](/api-details/junction-api#authentication) does not work with Junction Management API. Junction enforces the use of separate API credentials based on the principle of least privilege, especially considering the administrative power of Junction Management API. # Rate Limiting Source: https://docs.junction.com/api-details/rate_limiting Learn about Junction API rate limiting behavior, HTTP 429 and 503 responses under server load, and targeted limits on specific endpoints. Junction does not impose a per-customer rate limit on server-to-server API calls at this time. We adjust the elastic capacity and overprovisioning rate of our API servers regularly, in response to your usage pattern changes and product launch plans. However, when Junction API servers are under stress, there is a possibility that our infrastructure may abort a number of your API requests with a **429 Too Many Requests** or **503 Service Unavailable** response. For idempotent API requests, consider retrying the API request at least once, upon receiving a 429 or 503 response. Optionally, if you are making the API request in an asynchronous job context, consider having more retry attempts with an exponential backoff strategy. ## Targeted rate limits You may encounter **429 Too Many Requests** in these specific scenarios: | Endpoint | Authentication Scheme | Rate Limit | | ------------------------------ | --------------------- | ------------------- | | `POST /user/refresh/{user_id}` | Junction API Key | 8 per hour per user | Junction may adjust rate limiting based on real-world usage patterns. We will give you sufficient notice if a new enforcement would impact your existing usage patterns. # Regions Source: https://docs.junction.com/api-details/regions Understand how Junction stores data regionally in either the US (HIPAA compliant) or EU (GDPR compliant), and how organizations span multiple regions. Junction Team is a **regional** resource. All data of the Team is stored in the region you selected. This cannot be changed afterwards. Make sure you choose a region that is suitable for your data residency requirements. | Regions | Data Residency | | ------- | ----------------------------------------------- | | πŸ‡ΊπŸ‡Έ US | Data stored in United States (Subject to HIPAA) | | πŸ‡ͺπŸ‡Ί EU | Data stored in Belgium (Subject to GDPR) | Your Junction Org is a **global** resource β€” you can start with a Team in one region and create more in a different region as you expand. # Raw Source: https://docs.junction.com/api-reference/data/activity/get-raw GET /v2/summary/activity/{user_id}/raw Retrieve raw activity data for a specific user as received from their connected wearable provider. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/activity/{user_id}/raw \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.activity.get_raw( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.activity.getRaw({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.activity.requests.GetRawActivityRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.activity().getRaw( "", GetRawActivityRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Activity.GetRaw(context.TODO(), &junction.GetRawActivityRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/activity/get-summary GET /v2/summary/activity/{user_id} Retrieve processed activity summary data for a specific user, including steps, calories, and distance metrics. ```bash Shell theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/activity/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.activity.get( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.activity.get({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.activity.requests.GetActivityRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.activity().get( "", GetActivityRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Activity.Get(context.TODO(), &junction.GetActivityRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Raw Source: https://docs.junction.com/api-reference/data/body/get-raw GET /v2/summary/body/{user_id}/raw Retrieve raw body composition data for a specific user as received from their connected wearable provider. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/body/{user_id}/raw \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.body.get_raw( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.body.getRaw({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.body.requests.GetRawBodyRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.body().getRaw( "", GetRawBodyRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Body.GetRaw(context.TODO(), &junction.GetRawBodyRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/body/get-summary GET /v2/summary/body/{user_id} Retrieve processed body summary data for a specific user, including weight, body fat, and BMI measurements. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/body/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.body.get( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.body.get({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.body.requests.GetBodyRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.body().get( "", GetBodyRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Body.Get(context.TODO(), &junction.GetBodyRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get User Device Source: https://docs.junction.com/api-reference/data/device/get-device GET /v2/user/{user_id}/device/{device_id} Retrieve user device via the Junction API. Requires authentication with your team API key. ```bash Shell theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/{user_id}/device/{device_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_device("", "") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getDevice({ userId: "", deviceId: "", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getDevice("", ""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetDevice(context.TODO(), &junction.GetDeviceUserRequest{ UserId: "", DeviceId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get User Devices Source: https://docs.junction.com/api-reference/data/device/get-devices GET /v2/user/{user_id}/device Retrieve user devices via the Junction API. Requires authentication with your team API key. ```bash Shell theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/{user_id}/device \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_devices("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getDevices({ userId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getDevices(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetDevices(context.TODO(), &junction.GetDevicesUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/electrocardiogram/get-summary GET /v2/summary/electrocardiogram/{user_id} Retrieve electrocardiogram summary data for a specific user from their connected wearable provider. The Electrocardiogram summary type does not embed the voltage measurements. Use the [Get Electrocardiogram Voltage](/api-reference/data/timeseries/electrocardiogram-voltage) endpoint with the `session_start` and `session_end` timestamps to query the voltage measurements. ```bash Shell theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/electrocardiogram/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.electrocardiogram.get( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.electrocardiogram.get({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.electrocardiogram.requests.GetElectrocardiogramRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.electrocardiogram().get( "", GetElectrocardiogramRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Electrocardiogram.Get(context.TODO(), &junction.GetElectrocardiogramRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get historical pulls Source: https://docs.junction.com/api-reference/data/introspection/historical-pulls GET /v2/introspect/historical_pull List historical data pull records to track the progress and status of initial data backfills for connected providers. ## Overview Diagnose user historical data unavailability through the User Resources Introspection API. This API offers detailed insights into all provider connections and collected historical resources of all users in your team, empowering you to perform an initial diagnosis of any user connection issue with ease. Please note that `user_limit` is an upper bound and the endpoint can return data for fewer users. This would be the case if any of the top selected users had no available resource information. # Get user resources Source: https://docs.junction.com/api-reference/data/introspection/user-resources GET /v2/introspect/resources List available data resources for the authenticated user, showing which providers and data types are accessible. ## Overview Diagnose user data unavailability through the User Resources Introspection API. This API offers detailed insights into all provider connections and collected resources of all users in your team, empowering you to perform an initial diagnosis of any user connection issue with ease. Please note that `user_limit` is an upper bound and the endpoint can return data for fewer users. This would be the case if any of the top selected users had no available resource information. # Summary Source: https://docs.junction.com/api-reference/data/meal/get-summary GET /v2/summary/meal/{user_id} Retrieve meal and nutrition summary data for a specific user from their connected tracking provider. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/meal/{user_id}?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.meal.get( "", start_date="2021-01-01", end_date="2021-01-02", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.meal.get({ userId: "", startDate: "2021-01-01", endDate: "2021-01-02", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.meal.requests.GetMealRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.meal().get( "", GetMealRequest.builder() .startDate("2021-01-01") .endDate("2021-01-02") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2021-01-02" response, err := c.Meal.Get(context.TODO(), &junction.GetMealRequest{ UserId: "", StartDate: "2021-01-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/menstrual-cycle/get-summary GET /v2/summary/menstrual_cycle/{user_id} Retrieve menstrual cycle tracking summary data for a specific user from their connected wearable provider. ```bash Shell theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/menstrual_cycle/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.menstrual_cycle.get( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.menstrualCycle.get({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.menstrualcycle.requests.GetMenstrualCycleRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.menstrualCycle().get( "", GetMenstrualCycleRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.MenstrualCycle.Get(context.TODO(), &junction.GetMenstrualCycleRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Raw Source: https://docs.junction.com/api-reference/data/profile/get-raw GET /v2/summary/profile/{user_id}/raw Retrieve raw user profile data as received from their connected wearable provider without processing. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/profile/{user_id}/raw \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.profile.get_raw("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.profile.getRaw({ userId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.profile().getRaw(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Profile.GetRaw(context.TODO(), &junction.GetRawProfileRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/profile/get-summary GET /v2/summary/profile/{user_id} Retrieve the processed user profile data from their connected wearable provider, including demographics and preferences. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/profile/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.profile.get("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.profile.get({ userId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.profile().get(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Profile.Get(context.TODO(), &junction.GetProfileRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/sleep-cycle/get-summary GET /v2/summary/sleep_cycle/{user_id} Retrieve sleep cycle analysis data for a specific user, including sleep stage breakdowns and cycle metrics. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/sleep_cycle/{user_id}?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.sleep_cycle.get( "", start_date="2021-01-01", end_date="2021-01-02", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.sleepCycle.get({ userId: "", startDate: "2021-01-01", endDate: "2021-01-02", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.sleepcycle.requests.GetSleepCycleRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.sleepCycle().get( "", GetSleepCycleRequest.builder() .startDate("2021-01-01") .endDate("2021-01-02") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2021-01-02" response, err := c.SleepCycle.Get(context.TODO(), &junction.GetSleepCycleRequest{ UserId: "", StartDate: "2021-01-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Raw Source: https://docs.junction.com/api-reference/data/sleep/get-raw GET /v2/summary/sleep/{user_id}/raw Retrieve raw sleep data for a specific user as received from their connected wearable provider. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/sleep/{user_id}/raw \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.sleep.get_raw( "", start_date="2021-01-01", end_date="2021-01-02", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.sleep.getRaw({ userId: "", startDate: "2021-01-01", endDate: "2021-01-02", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.sleep.requests.GetRawSleepRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.sleep().getRaw( "", GetRawSleepRequest.builder() .startDate("2021-01-01") .endDate("2021-01-02") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2021-01-02" response, err := c.Sleep.GetRaw(context.TODO(), &junction.GetRawSleepRequest{ UserId: "", StartDate: "2021-01-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/sleep/get-summary GET /v2/summary/sleep/{user_id} Retrieve processed sleep summary data for a specific user, including duration, efficiency, and quality scores. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/sleep/{user_id}?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.sleep.get( "", start_date="2021-01-01", end_date="2021-01-02", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.sleep.get({ userId: "", startDate: "2021-01-01", endDate: "2021-01-02", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.sleep.requests.GetSleepRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.sleep().get( "", GetSleepRequest.builder() .startDate("2021-01-01") .endDate("2021-01-02") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2021-01-02" response, err := c.Sleep.Get(context.TODO(), &junction.GetSleepRequest{ UserId: "", StartDate: "2021-01-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Afib Burden Source: https://docs.junction.com/api-reference/data/timeseries/afib-burden GET /v2/timeseries/{user_id}/afib_burden/grouped Retrieve atrial fibrillation (AFib) burden time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/afib_burden/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.afib_burden_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsAfibBurdenGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsAfibBurdenGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.afibBurdenGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsAfibBurdenGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsAfibBurdenGroupedRequest request = VitalsAfibBurdenGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().afibBurdenGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsAfibBurdenGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.AfibBurdenGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "%", "value": 3 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Basal Body Temperature Source: https://docs.junction.com/api-reference/data/timeseries/basal-body-temperature GET /v2/timeseries/{user_id}/basal_body_temperature/grouped Retrieve basal body temperature time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/basal_body_temperature/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.basal_body_temperature_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBasalBodyTemperatureGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBasalBodyTemperatureGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.basalBodyTemperatureGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBasalBodyTemperatureGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBasalBodyTemperatureGroupedRequest request = VitalsBasalBodyTemperatureGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().basalBodyTemperatureGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBasalBodyTemperatureGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BasalBodyTemperatureGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "\u00b0C", "value": 36.7 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Blood Oxygen Source: https://docs.junction.com/api-reference/data/timeseries/blood-oxygen GET /v2/timeseries/{user_id}/blood_oxygen/grouped Retrieve blood oxygen saturation (SpO2) time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/blood_oxygen/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.blood_oxygen_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBloodOxygenGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBloodOxygenGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bloodOxygenGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBloodOxygenGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBloodOxygenGroupedRequest request = VitalsBloodOxygenGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bloodOxygenGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBloodOxygenGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BloodOxygenGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "%", "value": 98 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Blood Pressure Source: https://docs.junction.com/api-reference/data/timeseries/blood-pressure GET /v2/timeseries/{user_id}/blood_pressure/grouped Retrieve blood pressure time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/blood_pressure/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.blood_pressure_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBloodPressureGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBloodPressureGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bloodPressureGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBloodPressureGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBloodPressureGroupedRequest request = VitalsBloodPressureGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bloodPressureGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBloodPressureGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BloodPressureGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "diastolic": 75, "systolic": 125, "timestamp": "2026-08-07T08:36:23+00:00", "unit": "mmHg" } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Body Fat Source: https://docs.junction.com/api-reference/data/timeseries/body-fat GET /v2/timeseries/{user_id}/body_fat/grouped Retrieve body fat percentage time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/body_fat/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.body_fat_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBodyFatGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBodyFatGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bodyFatGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBodyFatGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBodyFatGroupedRequest request = VitalsBodyFatGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bodyFatGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBodyFatGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BodyFatGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "%", "value": 50 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Body Mass Index Source: https://docs.junction.com/api-reference/data/timeseries/body-mass-index GET /v2/timeseries/{user_id}/body_mass_index/grouped Retrieve body mass index (BMI) time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/body_mass_index/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.body_mass_index_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBodyMassIndexGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBodyMassIndexGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bodyMassIndexGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBodyMassIndexGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBodyMassIndexGroupedRequest request = VitalsBodyMassIndexGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bodyMassIndexGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBodyMassIndexGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BodyMassIndexGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "index", "value": 21 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Body Temperature Source: https://docs.junction.com/api-reference/data/timeseries/body-temperature GET /v2/timeseries/{user_id}/body_temperature/grouped Retrieve body temperature time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/body_temperature/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.body_temperature_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBodyTemperatureGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBodyTemperatureGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bodyTemperatureGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBodyTemperatureGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBodyTemperatureGroupedRequest request = VitalsBodyTemperatureGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bodyTemperatureGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBodyTemperatureGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BodyTemperatureGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "sensor_location": "eardrum", "start": "2023-02-13T14:30:52+00:00", "unit": "\u00b0C", "value": 65 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Body Temperature Delta Source: https://docs.junction.com/api-reference/data/timeseries/body-temperature-delta GET /v2/timeseries/{user_id}/body_temperature_delta/grouped Retrieve body temperature delta time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/body_temperature_delta/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.body_temperature_delta_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBodyTemperatureDeltaGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBodyTemperatureDeltaGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bodyTemperatureDeltaGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBodyTemperatureDeltaGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBodyTemperatureDeltaGroupedRequest request = VitalsBodyTemperatureDeltaGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bodyTemperatureDeltaGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBodyTemperatureDeltaGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BodyTemperatureDeltaGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "sensor_location": "wrist", "start": "2023-02-13T14:30:52+00:00", "unit": "\u00b0C", "value": -1.0 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Body Weight Source: https://docs.junction.com/api-reference/data/timeseries/body-weight GET /v2/timeseries/{user_id}/body_weight/grouped Retrieve body weight time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/body_weight/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.body_weight_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsBodyWeightGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsBodyWeightGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.bodyWeightGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsBodyWeightGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsBodyWeightGroupedRequest request = VitalsBodyWeightGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().bodyWeightGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsBodyWeightGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.BodyWeightGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "kg", "value": 65 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Caffeine Source: https://docs.junction.com/api-reference/data/timeseries/caffeine GET /v2/timeseries/{user_id}/caffeine/grouped Retrieve caffeine intake time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/caffeine/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.caffeine_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsCaffeineGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsCaffeineGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.caffeineGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsCaffeineGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsCaffeineGroupedRequest request = VitalsCaffeineGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().caffeineGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsCaffeineGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.CaffeineGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "g", "value": 42 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Calories Active Source: https://docs.junction.com/api-reference/data/timeseries/calories-active GET /v2/timeseries/{user_id}/calories_active/grouped Retrieve active calories burned time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/calories_active/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.calories_active_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsCaloriesActiveGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsCaloriesActiveGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.caloriesActiveGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsCaloriesActiveGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsCaloriesActiveGroupedRequest request = VitalsCaloriesActiveGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().caloriesActiveGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsCaloriesActiveGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.CaloriesActiveGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "kcal", "value": 184 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Calories Basal Source: https://docs.junction.com/api-reference/data/timeseries/calories-basal GET /v2/timeseries/{user_id}/calories_basal/grouped Retrieve basal calories burned time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/calories_basal/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.calories_basal_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsCaloriesBasalGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsCaloriesBasalGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.caloriesBasalGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsCaloriesBasalGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsCaloriesBasalGroupedRequest request = VitalsCaloriesBasalGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().caloriesBasalGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsCaloriesBasalGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.CaloriesBasalGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "kcal", "value": 22.8 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Carbohydrates Source: https://docs.junction.com/api-reference/data/timeseries/carbohydrates GET /v2/timeseries/{user_id}/carbohydrates/grouped Retrieve carbohydrate intake time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/carbohydrates/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.carbohydrates_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsCarbohydratesGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsCarbohydratesGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.carbohydratesGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsCarbohydratesGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsCarbohydratesGroupedRequest request = VitalsCarbohydratesGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().carbohydratesGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsCarbohydratesGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.CarbohydratesGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "g", "value": 30 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Daylight Exposure Source: https://docs.junction.com/api-reference/data/timeseries/daylight-exposure GET /v2/timeseries/{user_id}/daylight_exposure/grouped Retrieve daylight exposure time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/daylight_exposure/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.daylight_exposure_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsDaylightExposureGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsDaylightExposureGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.daylightExposureGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsDaylightExposureGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsDaylightExposureGroupedRequest request = VitalsDaylightExposureGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().daylightExposureGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsDaylightExposureGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.DaylightExposureGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "min", "value": 45 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Distance Source: https://docs.junction.com/api-reference/data/timeseries/distance GET /v2/timeseries/{user_id}/distance/grouped Retrieve distance traveled time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/distance/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.distance_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsDistanceGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsDistanceGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.distanceGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsDistanceGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsDistanceGroupedRequest request = VitalsDistanceGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().distanceGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsDistanceGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.DistanceGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "m", "value": 5.6 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Electrocardiogram Voltage Source: https://docs.junction.com/api-reference/data/timeseries/electrocardiogram-voltage GET /v2/timeseries/{user_id}/electrocardiogram_voltage/grouped Retrieve electrocardiogram (ECG) voltage time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/electrocardiogram_voltage/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.electrocardiogram_voltage_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsElectrocardiogramVoltageGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsElectrocardiogramVoltageGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.electrocardiogramVoltageGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsElectrocardiogramVoltageGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsElectrocardiogramVoltageGroupedRequest request = VitalsElectrocardiogramVoltageGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().electrocardiogramVoltageGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsElectrocardiogramVoltageGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.ElectrocardiogramVoltageGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "type": "lead_1", "unit": "mV", "value": -373 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Fall Source: https://docs.junction.com/api-reference/data/timeseries/fall GET /v2/timeseries/{user_id}/fall/grouped Retrieve fall detection events time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/fall/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.fall_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsFallGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsFallGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.fallGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsFallGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsFallGroupedRequest request = VitalsFallGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().fallGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsFallGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.FallGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 3 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Floors Climbed Source: https://docs.junction.com/api-reference/data/timeseries/floors-climbed GET /v2/timeseries/{user_id}/floors_climbed/grouped Retrieve floors climbed time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/floors_climbed/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.floors_climbed_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsFloorsClimbedGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsFloorsClimbedGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.floorsClimbedGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsFloorsClimbedGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsFloorsClimbedGroupedRequest request = VitalsFloorsClimbedGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().floorsClimbedGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsFloorsClimbedGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.FloorsClimbedGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 2 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Forced Expiratory Volume 1 Source: https://docs.junction.com/api-reference/data/timeseries/forced-expiratory-volume-1 GET /v2/timeseries/{user_id}/forced_expiratory_volume_1/grouped Retrieve forced expiratory volume in one second (FEV1) time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/forced_expiratory_volume_1/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.forced_expiratory_volume_1_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsForcedExpiratoryVolume1GroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsForcedExpiratoryVolume1GroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.forcedExpiratoryVolume1Grouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsForcedExpiratoryVolume1GroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsForcedExpiratoryVolume1GroupedRequest request = VitalsForcedExpiratoryVolume1GroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().forcedExpiratoryVolume1Grouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsForcedExpiratoryVolume1GroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.ForcedExpiratoryVolume1Grouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "L", "value": 3.5 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Forced Vital Capacity Source: https://docs.junction.com/api-reference/data/timeseries/forced-vital-capacity GET /v2/timeseries/{user_id}/forced_vital_capacity/grouped Retrieve forced vital capacity (FVC) time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/forced_vital_capacity/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.forced_vital_capacity_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsForcedVitalCapacityGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsForcedVitalCapacityGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.forcedVitalCapacityGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsForcedVitalCapacityGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsForcedVitalCapacityGroupedRequest request = VitalsForcedVitalCapacityGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().forcedVitalCapacityGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsForcedVitalCapacityGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.ForcedVitalCapacityGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "L", "value": 4.2 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Glucose Source: https://docs.junction.com/api-reference/data/timeseries/glucose GET /v2/timeseries/{user_id}/glucose/grouped Retrieve blood glucose time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/glucose/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.glucose_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsGlucoseGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsGlucoseGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.glucoseGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsGlucoseGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsGlucoseGroupedRequest request = VitalsGlucoseGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().glucoseGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsGlucoseGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.GlucoseGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "type": "automatic | manual_scan", "unit": "mmol/L", "value": 0.5 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Handwashing Source: https://docs.junction.com/api-reference/data/timeseries/handwashing GET /v2/timeseries/{user_id}/handwashing/grouped Retrieve handwashing events time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/handwashing/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.handwashing_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsHandwashingGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsHandwashingGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.handwashingGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsHandwashingGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsHandwashingGroupedRequest request = VitalsHandwashingGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().handwashingGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsHandwashingGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.HandwashingGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 1 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Heart Rate Alert Source: https://docs.junction.com/api-reference/data/timeseries/heart-rate-alert GET /v2/timeseries/{user_id}/heart_rate_alert/grouped Retrieve heart rate alerts time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/heart_rate_alert/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.heart_rate_alert_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsHeartRateAlertGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsHeartRateAlertGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.heartRateAlertGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsHeartRateAlertGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsHeartRateAlertGroupedRequest request = VitalsHeartRateAlertGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().heartRateAlertGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsHeartRateAlertGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.HeartRateAlertGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "start": "2023-02-13T14:30:52+00:00", "type": "irregular_rhythm", "unit": "count", "value": 1 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Heart Rate Recovery One Minute Source: https://docs.junction.com/api-reference/data/timeseries/heart-rate-recovery-one-minute GET /v2/timeseries/{user_id}/heart_rate_recovery_one_minute/grouped Retrieve one-minute heart rate recovery time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/heart_rate_recovery_one_minute/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.heart_rate_recovery_one_minute_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsHeartRateRecoveryOneMinuteGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsHeartRateRecoveryOneMinuteGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.heartRateRecoveryOneMinuteGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsHeartRateRecoveryOneMinuteGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsHeartRateRecoveryOneMinuteGroupedRequest request = VitalsHeartRateRecoveryOneMinuteGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().heartRateRecoveryOneMinuteGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsHeartRateRecoveryOneMinuteGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.HeartRateRecoveryOneMinuteGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 37 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Heart Rate Source: https://docs.junction.com/api-reference/data/timeseries/heartrate GET /v2/timeseries/{user_id}/heartrate/grouped Retrieve heart rate time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/heartrate/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.heartrate_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsHeartrateGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsHeartrateGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.heartrateGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsHeartrateGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsHeartrateGroupedRequest request = VitalsHeartrateGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().heartrateGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsHeartrateGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.HeartrateGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "bpm", "value": 70 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Heart Rate Variability Source: https://docs.junction.com/api-reference/data/timeseries/hrv GET /v2/timeseries/{user_id}/hrv/grouped Retrieve heart rate variability (HRV) time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/hrv/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.hrv_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsHrvGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsHrvGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.hrvGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsHrvGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsHrvGroupedRequest request = VitalsHrvGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().hrvGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsHrvGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.HrvGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "rmssd", "value": 48 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Inhaler Usage Source: https://docs.junction.com/api-reference/data/timeseries/inhaler-usage GET /v2/timeseries/{user_id}/inhaler_usage/grouped Retrieve inhaler usage time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/inhaler_usage/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.inhaler_usage_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsInhalerUsageGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsInhalerUsageGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.inhalerUsageGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsInhalerUsageGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsInhalerUsageGroupedRequest request = VitalsInhalerUsageGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().inhalerUsageGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsInhalerUsageGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.InhalerUsageGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 2 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Insulin Injection Source: https://docs.junction.com/api-reference/data/timeseries/insulin-injection GET /v2/timeseries/{user_id}/insulin_injection/grouped Retrieve insulin injections time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/insulin_injection/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.insulin_injection_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsInsulinInjectionGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsInsulinInjectionGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.insulinInjectionGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsInsulinInjectionGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsInsulinInjectionGroupedRequest request = VitalsInsulinInjectionGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().insulinInjectionGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsInsulinInjectionGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.InsulinInjectionGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "bolus_purpose": "correction", "delivery_form": "extended", "delivery_mode": "bolus", "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "type": "rapid_acting", "unit": "unit", "value": 2.5 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Lean Body Mass Source: https://docs.junction.com/api-reference/data/timeseries/lean-body-mass GET /v2/timeseries/{user_id}/lean_body_mass/grouped Retrieve lean body mass time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/lean_body_mass/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.lean_body_mass_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsLeanBodyMassGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsLeanBodyMassGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.leanBodyMassGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsLeanBodyMassGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsLeanBodyMassGroupedRequest request = VitalsLeanBodyMassGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().leanBodyMassGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsLeanBodyMassGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.LeanBodyMassGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "kg", "value": 50 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Mindfulness Minutes Source: https://docs.junction.com/api-reference/data/timeseries/mindfulness-minutes GET /v2/timeseries/{user_id}/mindfulness_minutes/grouped Retrieve mindfulness minutes time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/mindfulness_minutes/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.mindfulness_minutes_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsMindfulnessMinutesGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsMindfulnessMinutesGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.mindfulnessMinutesGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsMindfulnessMinutesGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsMindfulnessMinutesGroupedRequest request = VitalsMindfulnessMinutesGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().mindfulnessMinutesGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsMindfulnessMinutesGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.MindfulnessMinutesGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2026-08-07T08:41:22.492526+00:00", "start": "2023-02-13T14:57:24+00:00", "unit": "min", "value": 42 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Note Source: https://docs.junction.com/api-reference/data/timeseries/note GET /v2/timeseries/{user_id}/note/grouped Retrieve user notes time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/note/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.note_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsNoteGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsNoteGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.noteGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsNoteGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsNoteGroupedRequest request = VitalsNoteGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().noteGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsNoteGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.NoteGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "start": "2023-02-13T14:30:52+00:00", "tags": [ "food", "exercise" ], "unit": "text", "value": "Lorem ipsum dolor sit amet" } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Peak Expiratory Flow Rate Source: https://docs.junction.com/api-reference/data/timeseries/peak-expiratory-flow-rate GET /v2/timeseries/{user_id}/peak_expiratory_flow_rate/grouped Retrieve peak expiratory flow rate time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/peak_expiratory_flow_rate/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.peak_expiratory_flow_rate_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsPeakExpiratoryFlowRateGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsPeakExpiratoryFlowRateGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.peakExpiratoryFlowRateGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsPeakExpiratoryFlowRateGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsPeakExpiratoryFlowRateGroupedRequest request = VitalsPeakExpiratoryFlowRateGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().peakExpiratoryFlowRateGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsPeakExpiratoryFlowRateGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.PeakExpiratoryFlowRateGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "L/min", "value": 450 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Respiratory Rate Source: https://docs.junction.com/api-reference/data/timeseries/respiratory-rate GET /v2/timeseries/{user_id}/respiratory_rate/grouped Retrieve respiratory rate time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/respiratory_rate/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.respiratory_rate_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsRespiratoryRateGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsRespiratoryRateGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.respiratoryRateGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsRespiratoryRateGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsRespiratoryRateGroupedRequest request = VitalsRespiratoryRateGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().respiratoryRateGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsRespiratoryRateGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.RespiratoryRateGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "bpm", "value": 15.5 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Sleep Apnea Alert Source: https://docs.junction.com/api-reference/data/timeseries/sleep-apnea-alert GET /v2/timeseries/{user_id}/sleep_apnea_alert/grouped Retrieve sleep apnea alerts time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/sleep_apnea_alert/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.sleep_apnea_alert_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsSleepApneaAlertGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsSleepApneaAlertGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.sleepApneaAlertGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsSleepApneaAlertGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsSleepApneaAlertGroupedRequest request = VitalsSleepApneaAlertGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().sleepApneaAlertGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsSleepApneaAlertGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.SleepApneaAlertGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 1 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Sleep Breathing Disturbance Source: https://docs.junction.com/api-reference/data/timeseries/sleep-breathing-disturbance GET /v2/timeseries/{user_id}/sleep_breathing_disturbance/grouped Retrieve sleep breathing disturbances time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/sleep_breathing_disturbance/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.sleep_breathing_disturbance_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsSleepBreathingDisturbanceGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsSleepBreathingDisturbanceGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.sleepBreathingDisturbanceGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsSleepBreathingDisturbanceGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsSleepBreathingDisturbanceGroupedRequest request = VitalsSleepBreathingDisturbanceGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().sleepBreathingDisturbanceGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsSleepBreathingDisturbanceGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.SleepBreathingDisturbanceGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "type": "elevated", "unit": "count", "value": 12 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Stand Duration Source: https://docs.junction.com/api-reference/data/timeseries/stand-duration GET /v2/timeseries/{user_id}/stand_duration/grouped Retrieve stand duration time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/stand_duration/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.stand_duration_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsStandDurationGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsStandDurationGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.standDurationGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsStandDurationGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsStandDurationGroupedRequest request = VitalsStandDurationGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().standDurationGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsStandDurationGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.StandDurationGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "min", "value": 15 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Stand Hour Source: https://docs.junction.com/api-reference/data/timeseries/stand-hour GET /v2/timeseries/{user_id}/stand_hour/grouped Retrieve stand hours time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/stand_hour/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.stand_hour_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsStandHourGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsStandHourGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.standHourGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsStandHourGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsStandHourGroupedRequest request = VitalsStandHourGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().standHourGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsStandHourGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.StandHourGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 1 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Steps Source: https://docs.junction.com/api-reference/data/timeseries/steps GET /v2/timeseries/{user_id}/steps/grouped Retrieve steps time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/steps/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.steps_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsStepsGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsStepsGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.stepsGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsStepsGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsStepsGroupedRequest request = VitalsStepsGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().stepsGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsStepsGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.StepsGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 123 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Stress Level Source: https://docs.junction.com/api-reference/data/timeseries/stress-level GET /v2/timeseries/{user_id}/stress_level/grouped Retrieve stress level time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/stress_level/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.stress_level_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsStressLevelGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsStressLevelGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.stressLevelGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsStressLevelGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsStressLevelGroupedRequest request = VitalsStressLevelGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().stressLevelGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsStressLevelGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.StressLevelGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "timestamp": "2023-02-13T14:30:52+00:00", "unit": "%", "value": 35 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Uv Exposure Source: https://docs.junction.com/api-reference/data/timeseries/uv-exposure GET /v2/timeseries/{user_id}/uv_exposure/grouped Retrieve UV exposure time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/uv_exposure/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.uv_exposure_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsUvExposureGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsUvExposureGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.uvExposureGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsUvExposureGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsUvExposureGroupedRequest request = VitalsUvExposureGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().uvExposureGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsUvExposureGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.UvExposureGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "index", "value": 5 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Vo2 Max Source: https://docs.junction.com/api-reference/data/timeseries/vo2-max GET /v2/timeseries/{user_id}/vo2_max/grouped Retrieve VO2 max time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/vo2_max/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.vo2_max_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsVo2MaxGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsVo2MaxGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.vo2MaxGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsVo2MaxGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsVo2MaxGroupedRequest request = VitalsVo2MaxGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().vo2MaxGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsVo2MaxGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.Vo2MaxGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "mL/kg/min", "value": 48 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Waist Circumference Source: https://docs.junction.com/api-reference/data/timeseries/waist-circumference GET /v2/timeseries/{user_id}/waist_circumference/grouped Retrieve waist circumference time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/waist_circumference/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.waist_circumference_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWaistCircumferenceGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWaistCircumferenceGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.waistCircumferenceGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWaistCircumferenceGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWaistCircumferenceGroupedRequest request = VitalsWaistCircumferenceGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().waistCircumferenceGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWaistCircumferenceGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WaistCircumferenceGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "cm", "value": 90 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Water Source: https://docs.junction.com/api-reference/data/timeseries/water GET /v2/timeseries/{user_id}/water/grouped Retrieve water intake time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/water/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.water_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWaterGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWaterGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.waterGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWaterGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWaterGroupedRequest request = VitalsWaterGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().waterGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWaterGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WaterGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "unit": "ml", "value": 400 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Wheelchair Push Source: https://docs.junction.com/api-reference/data/timeseries/wheelchair-push GET /v2/timeseries/{user_id}/wheelchair_push/grouped Retrieve wheelchair pushes time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/wheelchair_push/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.wheelchair_push_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWheelchairPushGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWheelchairPushGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.wheelchairPushGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWheelchairPushGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWheelchairPushGroupedRequest request = VitalsWheelchairPushGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().wheelchairPushGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWheelchairPushGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WheelchairPushGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 52 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Workout Distance Source: https://docs.junction.com/api-reference/data/timeseries/workout-distance GET /v2/timeseries/{user_id}/workout_distance/grouped Retrieve workout distance time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/workout_distance/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.workout_distance_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWorkoutDistanceGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWorkoutDistanceGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.workoutDistanceGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWorkoutDistanceGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWorkoutDistanceGroupedRequest request = VitalsWorkoutDistanceGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().workoutDistanceGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWorkoutDistanceGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WorkoutDistanceGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "m", "value": 37 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Workout Duration Source: https://docs.junction.com/api-reference/data/timeseries/workout-duration GET /v2/timeseries/{user_id}/workout_duration/grouped Retrieve workout duration time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/workout_duration/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.workout_duration_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWorkoutDurationGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWorkoutDurationGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.workoutDurationGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWorkoutDurationGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWorkoutDurationGroupedRequest request = VitalsWorkoutDurationGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().workoutDurationGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWorkoutDurationGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WorkoutDurationGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:30:52+00:00", "intensity": "medium", "start": "2023-02-13T14:30:52+00:00", "unit": "min", "value": 48 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Workout Swimming Stroke Source: https://docs.junction.com/api-reference/data/timeseries/workout-swimming-stroke GET /v2/timeseries/{user_id}/workout_swimming_stroke/grouped Retrieve workout swimming strokes time-series data for a user over a date range, grouped by source, from Vital's Data API. The Response section on the page still needs work. Click here to check out the complete schema. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/timeseries/{user_id}/workout_swimming_stroke/grouped?start_date={{START_DATE}}&end_date={{END_DATE}} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from vital.client import Vital from vital.environment import VitalEnvironment client = Vital( api_key="YOUR_API_KEY", environment=VitalEnvironment.SANDBOX ) data = client.vitals.workout_swimming_stroke_grouped( user_id="", start_date="2021-10-01", end_date="2021-10-02" ) ``` ```javascript Node theme={null} import { VitalClient, VitalEnvironment } from '@tryvital/vital-node'; import { VitalsWorkoutSwimmingStrokeGroupedRequest } from '@tryvital/vital-node/api/resources/vitals'; const client = new VitalClient({ apiKey: '', environment: VitalEnvironment.Sandbox, }); const request: VitalsWorkoutSwimmingStrokeGroupedRequest = { startDate: "2022-05-01", endDate: "2022-06-01" } const data = await client.vitals.workoutSwimmingStrokeGrouped( '', request ); ``` ```java Java theme={null} import com.vital.api.Vital; import com.vital.api.core.Environment; import com.vital.api.resources.vitals.requests.VitalsWorkoutSwimmingStrokeGroupedRequest; Vital vital = Vital.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); VitalsWorkoutSwimmingStrokeGroupedRequest request = VitalsWorkoutSwimmingStrokeGroupedRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build(); var data = vital.vitals().workoutSwimmingStrokeGrouped("", request); ``` ```go Go theme={null} import ( "context" vital "github.com/tryVital/vital-go" vitalclient "github.com/tryVital/vital-go/client" ) client := vitalclient.NewClient( vitalclient.WithApiKey(""), vitalclient.WithBaseURL(vital.Environments.Sandbox), ) EndDate := "2022-06-01" request := &vital.VitalsWorkoutSwimmingStrokeGroupedRequest{ StartDate: "2022-05-01", EndDate: &EndDate, } response, err := client.Vitals.WorkoutSwimmingStrokeGrouped(context.TODO(), "*", request) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Example theme={null} { "groups": { "oura": [ { "data": [ { "end": "2023-02-13T14:57:24+00:00", "start": "2023-02-13T14:30:52+00:00", "timestamp": "2023-02-13T14:30:52+00:00", "unit": "count", "value": 37 } ], "source": { "provider": "oura", "type": "ring" } } ] } } ``` # Raw Source: https://docs.junction.com/api-reference/data/workouts/get-raw GET /v2/summary/workouts/{user_id}/raw Retrieve raw workout data for a specific user as received from their connected wearable provider. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/workouts/{user_id}/raw \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.workouts.get_raw( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.workouts.getRaw({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.workouts.requests.GetRawWorkoutsRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.workouts().getRaw( "", GetRawWorkoutsRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Workouts.GetRaw(context.TODO(), &junction.GetRawWorkoutsRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Stream Source: https://docs.junction.com/api-reference/data/workouts/get-stream GET /v2/timeseries/workouts/{workout_id}/stream Retrieve timeseries workouts stream via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/workouts/{workout_id}/stream \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.workouts.get_by_workout_id("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.workouts.getByWorkoutId({ workoutId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.workouts().getByWorkoutId(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Workouts.GetByWorkoutId(context.TODO(), &junction.GetByWorkoutIdWorkoutsRequest{ WorkoutId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Summary Source: https://docs.junction.com/api-reference/data/workouts/get-summary GET /v2/summary/workouts/{user_id} Retrieve processed workout summary data for a specific user, including type, duration, and calorie metrics. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/summary/workouts/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.workouts.get( "", start_date="2022-05-01", end_date="2022-06-01", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.workouts.get({ userId: "", startDate: "2022-05-01", endDate: "2022-06-01", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.workouts.requests.GetWorkoutsRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.workouts().get( "", GetWorkoutsRequest.builder() .startDate("2022-05-01") .endDate("2022-06-01") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2022-06-01" response, err := c.Workouts.Get(context.TODO(), &junction.GetWorkoutsRequest{ UserId: "", StartDate: "2022-05-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get ABN Form PDF Source: https://docs.junction.com/api-reference/lab-testing/abn-pdf GET /v3/order/{order_id}/abn_pdf Retrieve order abn pdf via the Junction API. Requires authentication with your team API key. Retrieving ABNs is currently in closed beta. When [getting an order](/api-reference/lab-testing/get-order#response-has-abn), you can view the `has_abn` field to determine if an ABN form is available for this order. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//abn_pdf' \ --header 'accept: application/pdf' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --output file.pdf ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_order_abn_pdf("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getOrderAbnPdf({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getOrderAbnPdf(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetOrderAbnPdf(context.TODO(), &junction.GetOrderAbnPdfLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get area info Source: https://docs.junction.com/api-reference/lab-testing/area-info GET /v3/order/area/info Retrieve order area info via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/area/info?zip_code=85004' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_area_info(zip_code="85004") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getAreaInfo({ zipCode: "85004" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.GetAreaInfoLabTestsRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getAreaInfo( GetAreaInfoLabTestsRequest.builder() .zipCode("85004") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetAreaInfo(context.TODO(), &junction.GetAreaInfoLabTestsRequest{ ZipCode: "85004", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "zip_code": "85004", "phlebotomy": { "is_served": true, "providers": [ { "name": "getlabs", "tier": ["appointment-ready"] }, { "name": "phlebfinders", "tier": ["appointment-request"] } ] }, "central_labs": { "labcorp": { "patient_service_centers": { "within_radius": 5, "radius": "25", "capabilities": ["stat"] } } } } ``` # Create appointment availability Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-availability POST /v3/order/phlebotomy/appointment/availability Create or submit order phlebotomy appointment availability via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/phlebotomy/appointment/availability' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "first_line": "256 West Lincoln Street", "second_line": "14", "city": "Phoenix", "state": "AZ", "zip_code": "85004" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_phlebotomy_appointment_availability( first_line="123 Main St", city="San Francisco", state="CA", zip_code="94105", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPhlebotomyAppointmentAvailability({ body: { firstLine: "123 Main St", city: "San Francisco", state: "CA", zipCode: "94105", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.types.UsAddress; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPhlebotomyAppointmentAvailability( UsAddress.builder() .firstLine("123 Main St") .city("San Francisco") .state("CA") .zipCode("94105") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPhlebotomyAppointmentAvailability(context.TODO(), &junction.GetPhlebotomyAppointmentAvailabilityLabTestsRequest{ Body: &junction.UsAddress{ FirstLine: "123 Main St", City: "San Francisco", State: "CA", ZipCode: "94105", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "timezone":"America/Phoenix", "slots": [ { "date":"2023-05-09", "slots": [ { "booking_key": "foo123", "start": "2023-05-09T17:00:00+00:00", "end": "2023-05-09T19:00:00+00:00", "expires_at": "2023-05-09T12:39:57.827000+00:00", "price": 3500, "is_priority": true, "num_appointments_available": 5 }, ... ], }, { "date":"2023-05-10", "slots": [ { "booking_key": "bar456", "start": "2023-05-10T12:00:00+00:00", "end": "2023-05-10T14:00:00+00:00", "expires_at": "2023-05-09T12:39:57.852000+00:00", "price": 7900, "is_priority": true, "num_appointments_available": 5 }, ... ], }, ] } ``` # Create appointment book Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-booking POST /v3/order/{order_id}/phlebotomy/appointment/book Create or submit order phlebotomy appointment book via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/phlebotomy/appointment/book' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "booking_key": "foo123", "appointment_notes": "Please bring photo ID" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.book_phlebotomy_appointment( "", booking_key="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.bookPhlebotomyAppointment({ orderId: "", body: { bookingKey: "", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.BookPhlebotomyAppointmentLabTestsRequest; import com.junction.api.types.AppointmentBookingRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().bookPhlebotomyAppointment( "", BookPhlebotomyAppointmentLabTestsRequest.builder() .body( AppointmentBookingRequest.builder() .bookingKey("") .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.BookPhlebotomyAppointment(context.TODO(), &junction.BookPhlebotomyAppointmentLabTestsRequest{ OrderId: "", Body: &junction.AppointmentBookingRequest{ BookingKey: "", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14", "access_notes": "Gate code #1234, use side entrance" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-15T16:00:00+00:00", "end_at": "2023-05-15T18:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "phlebotomy", "provider": "getlabs", "status": "pending", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule":true, "appointment_notes": "Please bring photo ID" } ``` # Get appointment cancellation reasons Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-cancellation-reasons GET /v3/order/phlebotomy/appointment/cancellation-reasons Retrieve order phlebotomy appointment cancellation reasons via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/phlebotomy/appointment/cancellation-reasons' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_phlebotomy_appointment_cancellation_reason() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPhlebotomyAppointmentCancellationReason(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPhlebotomyAppointmentCancellationReason(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPhlebotomyAppointmentCancellationReason(context.TODO()) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json theme={null} [ { "id": "5c0257ef-6fea-4a22-b20a-3ddab573d5c9", "name": "Did not fast for appointment", "is_refundable": true }, { "id": "448c519c-64b4-4497-ae73-622fa93371b3", "name": "Do not trust company", "is_refundable": true }, { "id": "d378e152-12d1-433e-9dd1-e0410f9331dc", "name": "Getlabs cannot deliver to my preferred lab", "is_refundable": true }, { "id": "5330c863-ac80-4316-901b-d305d0df74d5", "name": "No longer interested", "is_refundable": true }, { "id": "2b9f23fd-163e-4483-bb10-90c74a67e0dc", "name": "Other", "is_refundable": true }, { "id": "98f861dd-fe61-4817-a9d6-1b99b19cd0fb", "name": "Provider asked me to cancel", "is_refundable": true }, { "id": "7dfd7da5-ed6e-40bb-a7e4-c8003f0c10a9", "name": "Scheduled for wrong patient", "is_refundable": true }, { "id": "796da8c8-e654-4347-8ded-1026410c1976", "name": "Scheduled time no longer works", "is_refundable": true }, { "id": "ba02af35-a34f-4a7a-abe5-5f766e8f6cd1", "name": "Unable to get lab order from provider", "is_refundable": true }, { "id": "0c9425db-f11e-49c5-b976-3c0d1d4a4ea8", "name": "Wanted to book in-person appointment", "is_refundable": true }, { "id": "2599a0ea-0b4a-42fe-8df6-d8f7c68182e7", "name": "Went to lab for appointment", "is_refundable": true } ] ``` # Cancel appointment Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-cancelling PATCH /v3/order/{order_id}/phlebotomy/appointment/cancel Cancel an order phlebotomy appointment via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request PATCH \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/phlebotomy/appointment/cancel' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "cancellation_reason_id": "7dfd7da5-ed6e-40bb-a7e4-c8003f0c10a9" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.cancel_phlebotomy_appointment( "", cancellation_reason_id="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelPhlebotomyAppointment({ orderId: "", cancellationReasonId: "", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelPhlebotomyAppointment( "", ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest.builder() .cancellationReasonId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelPhlebotomyAppointment(context.TODO(), &junction.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest{ OrderId: "", CancellationReasonId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "phlebotomy", "provider": "getlabs", "status": "cancelled", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` # Create appointment request Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-request POST /v3/order/{order_id}/phlebotomy/appointment/request Create or submit order phlebotomy appointment request via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/phlebotomy/appointment/request' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "address": { "first_line": "256 West Lincoln Street", "second_line": "14", "city": "Phoenix", "state": "AZ", "zip_code": "85004" }, "provider": "phlebfinders", "appointment_notes": "Please bring photo ID" } ' ``` ```python Python theme={null} from junction import AppointmentProvider, Junction, UsAddress from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.request_phlebotomy_appointment( "", address=UsAddress( first_line="123 Main St", city="San Francisco", state="CA", zip_code="94105", ), provider=AppointmentProvider.PHLEBFINDERS, ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.requestPhlebotomyAppointment({ orderId: "", address: { firstLine: "123 Main St", city: "San Francisco", state: "CA", zipCode: "94105", }, provider: "phlebfinders", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.RequestAppointmentRequest; import com.junction.api.types.AppointmentProvider; import com.junction.api.types.UsAddress; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().requestPhlebotomyAppointment( "", RequestAppointmentRequest.builder() .address( UsAddress.builder() .firstLine("123 Main St") .city("San Francisco") .state("CA") .zipCode("94105") .build() ) .provider(AppointmentProvider.PHLEBFINDERS) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.RequestPhlebotomyAppointment(context.TODO(), &junction.RequestAppointmentRequest{ OrderId: "", Address: &junction.UsAddress{ FirstLine: "123 Main St", City: "San Francisco", State: "CA", ZipCode: "94105", }, Provider: junction.AppointmentProviderPhlebfinders, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14", "access_notes": "Gate code #1234, use side entrance" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "type": "phlebotomy", "provider": "phlebfinders", "status": "pending", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule":false, "appointment_notes": "Please bring photo ID" } ``` # Update appointment reschedule Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/appointment-rescheduling PATCH /v3/order/{order_id}/phlebotomy/appointment/reschedule Partially update order phlebotomy appointment reschedule via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request PATCH \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/phlebotomy/appointment/reschedule' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "booking_key": "bar456", "appointment_notes": "Updated: need morning appointment" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.reschedule_phlebotomy_appointment( "", booking_key="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.reschedulePhlebotomyAppointment({ orderId: "", body: { bookingKey: "", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ReschedulePhlebotomyAppointmentLabTestsRequest; import com.junction.api.types.AppointmentRescheduleRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().reschedulePhlebotomyAppointment( "", ReschedulePhlebotomyAppointmentLabTestsRequest.builder() .body( AppointmentRescheduleRequest.builder() .bookingKey("") .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.ReschedulePhlebotomyAppointment(context.TODO(), &junction.ReschedulePhlebotomyAppointmentLabTestsRequest{ OrderId: "", Body: &junction.AppointmentRescheduleRequest{ BookingKey: "", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14", "access_notes": "Gate code #1234, use side entrance" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "phlebotomy", "provider": "getlabs", "status": "pending", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true, "appointment_notes": "Updated: need morning appointment" } ``` # Get phlebotomy appointment Source: https://docs.junction.com/api-reference/lab-testing/at-home-phlebotomy/get-appointment GET /v3/order/{order_id}/phlebotomy/appointment Retrieve order phlebotomy appointment via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/phlebotomy/appointment' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_phlebotomy_appointment("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPhlebotomyAppointment({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPhlebotomyAppointment(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPhlebotomyAppointment(context.TODO(), &junction.GetPhlebotomyAppointmentLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "phlebotomy", "provider": "getlabs", "status": "pending", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` # Get Available Biomarkers Source: https://docs.junction.com/api-reference/lab-testing/biomarkers GET /v3/lab_tests/markers Retrieve lab tests markers via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/lab_tests/markers' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_markers() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getMarkers(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getMarkers(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetMarkers(context.TODO(), &junction.GetMarkersLabTestsRequest{}) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "markers": [ { "id": 202, "name": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "slug": "acetylcholine-receptor-achr-antibodies-complete-profile-with-reflex-to-musk-antibodies", "description": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "lab_id": 6, "provider_id": "165605", "type": "biomarker", "unit": null, "price": "N/A", "expected_results": [ { "id": 2938, "name": "AChR Blocking Abs, Serum", "slug": "achr-blocking-abs-serum", "lab_id": 6, "provider_id": "085927", "loinc": { "id": 3514, "name": "Acetylcholine receptor blocking Ab Qn (S)", "slug": "acetylcholine-receptor-blocking-ab-qn-s", "code": "11561-8", "unit": "%{inhibition}" } }, { "id": 2939, "name": "AChR Binding Abs, Serum", "slug": "achr-binding-abs-serum", "lab_id": 6, "provider_id": "085904", "loinc": { "id": 3174, "name": "Acetylcholine receptor binding Ab (S) [Moles/Vol]", "slug": "acetylcholine-receptor-binding-ab-s-moles-vol", "code": "11034-6", "unit": "nmol/L" } }, { "id": 2940, "name": "AChR-modulating Ab", "slug": "achr-modulating-ab", "lab_id": 6, "provider_id": "505199", "loinc": { "id": 61121, "name": "Acetylcholine receptor modulation Ab FC Ql (S)", "slug": "acetylcholine-receptor-modulation-ab-fc-ql-s", "code": "99062-2", "unit": null } } ] } ], "total": 2, "page": 1, "size": 2 } ``` # Cancel order Source: https://docs.junction.com/api-reference/lab-testing/cancel-order POST /v3/order/{order_id}/cancel Cancel an order via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.cancel_order("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelOrder({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelOrder(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelOrder(context.TODO(), &junction.CancelOrderLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} [ { "order": { "title": "ClientFacingOrder", "required": [ "user_id", "id", "team_id", "patient_details", "patient_address", "lab_test", "details", "created_at", "updated_at", "events" ], "type": "object", "properties": { "user_id": { "title": "User Id", "type": "string", "description": "User id returned by vital create user request. This id should be stored in your database against the user and used for all interactions with the vital api.", "format": "uuid" }, "user_key": { "title": "User Key", "type": "string", "description": "User key returned by vital create user key request. This key should be stored in your database against the user and used for all interactions with the vital api.", "format": "uuid", "deprecated": true }, "id": { "title": "Id", "type": "string", "description": "The Vital Order ID", "format": "uuid" }, "team_id": { "title": "Team Id", "type": "string", "description": "Your team id.", "format": "uuid" }, "patient_details": { "title": "Patient Details", "allOf": [ { "title": "PatientDetails", "required": ["dob", "gender"], "type": "object", "properties": { "dob": { "title": "Dob", "type": "string", "format": "date-time" }, "gender": { "title": "Gender", "type": "string" }, "email": { "title": "Email", "type": "string" } } } ], "description": "Patient Details" }, "patient_address": { "title": "Patient Address", "allOf": [ { "title": "PatientAddress", "required": [ "receiver_name", "street", "city", "state", "zip", "country", "phone_number" ], "type": "object", "properties": { "receiver_name": { "title": "Receiver Name", "type": "string" }, "street": { "title": "Street", "type": "string" }, "street_number": { "title": "Street Number", "type": "string" }, "city": { "title": "City", "type": "string" }, "state": { "title": "State", "type": "string" }, "zip": { "title": "Zip", "type": "string" }, "country": { "title": "Country", "type": "string" }, "phone_number": { "title": "Phone Number", "type": "string" } } } ], "description": "Patient Address" }, "lab_test": { "title": "Lab Test", "allOf": [ { "title": "LabTestInDB", "required": [ "slug", "name", "sample_type", "method", "lab_id", "price", "is_active", "created_at", "updated_at", "id" ], "type": "object", "properties": { "slug": { "title": "Slug", "type": "string" }, "name": { "title": "Name", "type": "string" }, "description": { "title": "Description", "type": "string" }, "sample_type": { "title": "LabTestSampleType", "enum": ["dried_blood_spot"], "type": "string", "description": "The type of sample used to perform a lab test." }, "method": { "title": "LabTestMethod", "enum": ["testkit", "walk_in_test"], "type": "string", "description": "The method used to perform a lab test." }, "lab_id": { "title": "Lab Id", "type": "integer" }, "skus": { "title": "Skus", "type": "array", "items": { "type": "object" } }, "price": { "title": "Price", "type": "number" }, "is_active": { "title": "Is Active", "type": "boolean" }, "turnaround_time_lower": { "title": "Turnaround Time Lower", "type": "integer" }, "turnaround_time_upper": { "title": "Turnaround Time Upper", "type": "integer" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "format": "date-time" }, "id": { "title": "Id", "type": "string", "format": "uuid" }, "lab": { "title": "LabInDB", "required": [ "slug", "name", "first_line_address", "city", "zipcode", "id" ], "type": "object", "properties": { "slug": { "title": "Slug", "type": "string" }, "name": { "title": "Name", "type": "string" }, "first_line_address": { "title": "First Line Address", "type": "string" }, "city": { "title": "City", "type": "string" }, "zipcode": { "title": "Zipcode", "type": "string" }, "clia": { "title": "Clia", "type": "string" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "format": "date-time" }, "id": { "title": "Id", "type": "integer" } } }, "markers": { "title": "Markers", "type": "array", "items": { "title": "MarkerInDB", "required": ["name", "slug", "description", "id"], "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "slug": { "title": "Slug", "type": "string" }, "description": { "title": "Description", "type": "string" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "format": "date-time" }, "id": { "title": "Id", "type": "integer" } } } } }, "description": "Schema for a LabTest in the database." } ], "description": "The Vital Test associated with the order" }, "details": { "title": "Details", "anyOf": [ { "title": "ClientFacingWalkInOrderDetails", "required": ["type"], "type": "object", "properties": { "type": { "title": "Type", "enum": ["walk_in_test"], "type": "string" }, "data": { "title": "ClientFacingWalkInTestOrder", "required": ["id", "created_at", "updated_at"], "type": "object", "properties": { "id": { "title": "Id", "type": "string", "description": "The Vital walk-in test Order ID", "format": "uuid" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "format": "date-time" } }, "description": "Schema for a walk-in test order in the client facing API.\n\nTo be used as part of a ClientFacingOrder.", "example": { "id": "0651ee15-31a1-461b-9c10-86aa960da6c9", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } } } }, { "title": "ClientFacingTestKitOrderDetails", "required": ["type"], "type": "object", "properties": { "type": { "title": "Type", "enum": ["testkit"], "type": "string" }, "data": { "title": "ClientFacingTestkitOrder", "required": ["id", "created_at", "updated_at"], "type": "object", "properties": { "id": { "title": "Id", "type": "string", "description": "The Vital TestKit Order ID", "format": "uuid" }, "shipment": { "title": "Shipment", "allOf": [ { "title": "ClientFacingShipment", "required": [ "id", "outbound_tracking_number", "outbound_tracking_url", "inbound_tracking_number", "inbound_tracking_url", "outbound_courier", "inbound_courier", "notes" ], "type": "object", "properties": { "id": { "title": "Id", "type": "string", "description": "The Vital Shipment ID", "format": "uuid" }, "outbound_tracking_number": { "title": "Outbound Tracking Number", "type": "string", "description": "Tracking number for delivery to customer" }, "outbound_tracking_url": { "title": "Outbound Tracking Url", "type": "string", "description": "Tracking url for delivery to customer" }, "inbound_tracking_number": { "title": "Inbound Tracking Number", "type": "string", "description": "Tracking number for delivery to lab" }, "inbound_tracking_url": { "title": "Inbound Tracking Url", "type": "string", "description": "Tracking url for delivery to lab" }, "outbound_courier": { "title": "Outbound Courier", "type": "string", "description": "Courier used for delivery to customer" }, "inbound_courier": { "title": "Inbound Courier", "type": "string", "description": "Courier used for delivery to lab" }, "notes": { "title": "Notes", "type": "string", "description": "Notes associated to the Vital shipment" } }, "description": "Schema for a Shipment in the client facing API.\n\nTo be used as part of a ClientFacingTestkitOrder.", "example": { "id": "dcab86c6-a315-493d-97aa-2fd0fa649130", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "" } } ], "description": "Shipment object" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "format": "date-time" } }, "description": "Schema for a testkit order in the client facing API.\n\nTo be used as part of a ClientFacingOrder.", "example": { "id": "43697a79-298f-43db-9703-e4cf16006c66", "shipment": { "id": "51caeb91-cc5c-4f82-a4c2-6f23b68e54c5", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } } } } ] }, "sample_id": { "title": "Sample Id", "type": "string", "description": "Sample ID" }, "notes": { "title": "Notes", "type": "string", "description": "Notes associated with the order" }, "created_at": { "title": "Created At", "type": "string", "description": "When your order was created", "format": "date-time" }, "updated_at": { "title": "Updated At", "type": "string", "description": "When your order was last updated", "format": "date-time" }, "events": { "title": "Events", "type": "array", "items": { "title": "ClientFacingOrderEvent", "required": ["id", "created_at", "status"], "type": "object", "properties": { "id": { "title": "Id", "type": "integer" }, "created_at": { "title": "Created At", "type": "string", "format": "date-time" }, "status": { "title": "OrderV2Status", "enum": [ "received.walk_in_test.requisition_created", "completed.walk_in_test.order_completed", "failed.walk_in_test.sample_error", "received.testkit.ordered", "received.testkit.requisition_created", "collecting_sample.testkit.transit_customer", "collecting_sample.testkit.out_for_delivery", "collecting_sample.testkit.with_customer", "collecting_sample.testkit.transit_lab", "collecting_sample.testkit.problem_in_transit_customer", "collecting_sample.testkit.problem_in_transit_lab", "sample_with_lab.testkit.delivered_to_lab", "sample_with_lab.testkit.lab_processing_blocked", "completed.testkit.completed", "failed.testkit.failure_to_deliver_to_customer", "failed.testkit.failure_to_deliver_to_lab", "failed.testkit.sample_error", "failed.testkit.lost", "cancelled.testkit.cancelled", "cancelled.testkit.do_not_process" ], "type": "string", "description": "An enumeration." } } } }, "status": { "title": "OrderV2TopLevelStatus", "enum": [ "received", "collecting_sample", "sample_with_lab", "completed", "cancelled", "failed" ], "type": "string", "description": "An enumeration." } }, "example": { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "team_id": "cbb64555-af07-46c1-be09-ef89308e9b60", "user_id": "94e2d9f2-d600-4a23-9f08-536df378e2c7", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.testkit.transit_customer" } ] } }, "status": { "title": "Status", "type": "string" }, "message": { "title": "Message", "type": "string" } } ] ``` # Compendium Convert Source: https://docs.junction.com/api-reference/lab-testing/compendium/convert POST /v3/compendium/convert Create or submit compendium convert via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Compendium Search Source: https://docs.junction.com/api-reference/lab-testing/compendium/search POST /v3/compendium/search Create or submit compendium search via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Create order Source: https://docs.junction.com/api-reference/lab-testing/create-order POST /v3/order Create or submit order via the Junction API. Requires authentication with your team API key. Patient name fields (`first_name`, `last_name`) must follow specific validation rules due to lab restrictions. See [Patient Name Validation](/lab/workflow/order-requirements#patient-name-validation) for complete details. ```python Python theme={null} from junction import Gender, Junction, PatientAddressWithValidation, PatientDetailsWithValidation from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.create_order( user_id="63661a2b-2bb3-4125-bb1a-b590f64f057f", lab_test_id="5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="2020-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddressWithValidation( receiver_name="John Doe", first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", phone_number="+1123456789", access_notes="Gate code #1234, use side entrance", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.createOrder({ userId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", labTestId: "5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", patientDetails: { firstName: "John", lastName: "Doe", dob: "2020-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { receiverName: "John Doe", firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", phoneNumber: "+1123456789", accessNotes: "Gate code #1234, use side entrance", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.CreateOrderRequestCompatible; import com.junction.api.types.Gender; import com.junction.api.types.PatientAddressWithValidation; import com.junction.api.types.PatientDetailsWithValidation; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().createOrder( CreateOrderRequestCompatible.builder() .userId("63661a2b-2bb3-4125-bb1a-b590f64f057f") .patientDetails( PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("2020-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build() ) .patientAddress( PatientAddressWithValidation.builder() .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .build() ) .labTestId("5b41f610-ebc5-4803-8f0c-a61c3bdc7faf") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CreateOrder(context.TODO(), &junction.CreateOrderRequestCompatible{ UserId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", LabTestId: junction.String("5b41f610-ebc5-4803-8f0c-a61c3bdc7faf"), PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "2020-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddressWithValidation{ ReceiverName: junction.String("John Doe"), FirstLine: "123 Main St.", SecondLine: junction.String("Apt. 208"), City: "San Francisco", State: "CA", Zip: "91189", Country: "US", PhoneNumber: junction.String("+1123456789"), AccessNotes: junction.String("Gate code #1234, use side entrance"), }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "order": { "id": "ea7eae96-2c25-404f-b043-bfc08584610d", "team_id": "c26a9cc7-cdff-4f23-a5f6-74d40088c16a", "user_id": "63661a2b-2bb3-4125-bb1a-b590f64f057f", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789", "access_notes": "Gate code #1234, use side entrance" }, "priority": false, "health_insurance_id": "33ec11aa-d8bf-4f46-950d-c9171be3c22f", "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.testkit.transit_customer" } ] }, "status": "string", "message": "string" } ``` # Create Unregistered Testkit Order Source: https://docs.junction.com/api-reference/lab-testing/create-unregistered-order POST /v3/order/testkit Create or submit order testkit via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction, ShippingAddressWithValidation from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.testkit.create_order( user_id="63661a2b-2bb3-4125-bb1a-b590f64f057f", lab_test_id="5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", shipping_details=ShippingAddressWithValidation( receiver_name="John Doe", first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", phone_number="+11234567890", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.testkit.createOrder({ userId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", labTestId: "5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", shippingDetails: { receiverName: "John Doe", firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", phoneNumber: "+11234567890", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.testkit.requests.CreateRegistrableTestkitOrderRequest; import com.junction.api.types.ShippingAddressWithValidation; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.testkit().createOrder( CreateRegistrableTestkitOrderRequest.builder() .userId("63661a2b-2bb3-4125-bb1a-b590f64f057f") .labTestId("5b41f610-ebc5-4803-8f0c-a61c3bdc7faf") .shippingDetails( ShippingAddressWithValidation.builder() .receiverName("John Doe") .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .phoneNumber("+11234567890") .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Testkit.CreateOrder(context.TODO(), &junction.CreateRegistrableTestkitOrderRequest{ UserId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", LabTestId: "5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", ShippingDetails: &junction.ShippingAddressWithValidation{ ReceiverName: "John Doe", FirstLine: "123 Main St.", SecondLine: junction.String("Apt. 208"), City: "San Francisco", State: "CA", Zip: "91189", Country: "US", PhoneNumber: "+11234567890", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/testkit' \ --header 'Accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "user_id": "63661a2b-2bb3-4125-bb1a-b590f64f057f", "lab_test_id": "5b41f610-ebc5-4803-8f0c-a61c3bdc7faf", "shipping_details": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "US", "phone_number": "+1123456789" } } ' ``` ```json Response theme={null} { "order": { "id": "96edc6ef-3b2c-412b-b9e5-96f361f93aec", "team_id": "b080b20c-e162-4cf1-9c7d-8faee72ee08e", "user_id": "9f1e094e-1641-466b-b668-d4d3300e569f", "shipping_details": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+11234567890" }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "health_insurance_id": "7695cc28-f9e5-400d-95d2-ec7d9ec580df", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "received", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.awaiting_registration" } ] }, "status": "string", "message": "string" } ``` # Get Lab Test Source: https://docs.junction.com/api-reference/lab-testing/get-lab-test GET /v3/lab_tests/{lab_test_id} Retrieve lab tests via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_by_id("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getById({ labTestId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getById(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetById(context.TODO(), &junction.GetByIdLabTestsRequest{ LabTestId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "5af405fc-fafb-49e8-b0bf-fe9d91df6a7d", "slug": "a94e3005-new-test", "name": "New test", "sample_type": "serum", "method": "at_home_phlebotomy", "price": 0.0, "is_active": true, "status": "active", "fasting": false, "lab": { "id": 26, "slug": "quest", "name": "Quest", "first_line_address": "100 Tri State International #100", "city": "Lincolnshire", "zipcode": "60069", "collection_methods": ["at_home_phlebotomy", "walk_in_test"], "sample_types": ["serum", "saliva", "urine"] }, "markers": [ { "id": 6859, "name": "17-Hydroxyprogesterone", "slug": "17-hydroxyprogesterone", "description": "17-Hydroxyprogesterone", "lab_id": 26, "provider_id": "17180", "type": "biomarker", "unit": null, "price": "N/A", "aoe": null, "a_la_carte_enabled": true }, { "id": 8213, "name": "17-Hydroxypregnenolone", "slug": "17-hydroxypregnenolone", "description": "17-Hydroxypregnenolone", "lab_id": 26, "provider_id": "8352", "type": "biomarker", "unit": null, "price": "N/A", "aoe": null, "a_la_carte_enabled": true } ], "is_delegated": false, "auto_generated": false } ``` # Get order Source: https://docs.junction.com/api-reference/lab-testing/get-order GET /v3/order/{order_id} Retrieve order via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_order("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getOrder({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getOrder(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetOrder(context.TODO(), &junction.GetOrderLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "team_id": "cbb64555-af07-46c1-be09-ef89308e9b60", "user_id": "94e2d9f2-d600-4a23-9f08-536df378e2c7", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "priority": false, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.testkit.transit_customer" } ], "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "active", "orders": [ { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "low_level_status": "transit_customer", "low_level_status_created_at": "2022-01-03T00:00:00Z", "origin": "initial" } ] } } ``` # Get orders Source: https://docs.junction.com/api-reference/lab-testing/get-orders GET /v3/orders Retrieve orders via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/orders' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_orders() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getOrders(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getOrders(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetOrders(context.TODO(), &junction.GetOrdersLabTestsRequest{}) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "orders": [ { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "team_id": "cbb64555-af07-46c1-be09-ef89308e9b60", "user_id": "94e2d9f2-d600-4a23-9f08-536df378e2c7", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "priority": false, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.testkit.transit_customer" } ], "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "active", "orders": [ { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "low_level_status": "transit_customer", "low_level_status_created_at": "2022-01-03T00:00:00Z", "origin": "initial" } ] } } ], "total": 1, "page": 1, "size": 50 } ``` # Get Team Physicians Source: https://docs.junction.com/api-reference/lab-testing/get-team-physicians GET /v2/team/{team_id}/physicians Retrieve the list of physicians associated with a team. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url https://api.tryvital.io/v2/team/{team_id}/physicians \ --header 'x-vital-api-key: ' ``` ```json Response theme={null} [ { "first_name": "Jane", "last_name": "Smith", "npi": "1234567890" } ] ``` # Import Order Source: https://docs.junction.com/api-reference/lab-testing/import-order POST /v3/order/import Create or submit order import via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. Patient name fields (`first_name`, `last_name`) must follow specific validation rules due to lab restrictions. See [Patient Name Validation](/lab/workflow/order-requirements#patient-name-validation) for complete details. ```python Python theme={null} from junction import Billing, Gender, Junction, LabTestCollectionMethod, OrderSetRequest, PatientAddress, PatientDetailsWithValidation, PhysicianCreateRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.import_order( user_id="63661a2b-2bb3-4125-bb1a-b590f64f057f", billing_type=Billing.CLIENT_BILL, order_set=OrderSetRequest(lab_test_ids=[]), collection_method=LabTestCollectionMethod.WALK_IN_TEST, physician=PhysicianCreateRequest(first_name="Jane", last_name="Doe", npi=""), patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="2020-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddress( receiver_name="John Doe", first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", ), sample_id="1234567890", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.importOrder({ userId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", billingType: "client_bill", orderSet: { labTestIds: [], }, collectionMethod: "walk_in_test", physician: { firstName: "Jane", lastName: "Doe", npi: "", }, patientDetails: { firstName: "John", lastName: "Doe", dob: "2020-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { receiverName: "John Doe", firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", }, sampleId: "1234567890", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ImportOrderBody; import com.junction.api.types.Billing; import com.junction.api.types.Gender; import com.junction.api.types.LabTestCollectionMethod; import com.junction.api.types.OrderSetRequest; import com.junction.api.types.PatientAddress; import com.junction.api.types.PatientDetailsWithValidation; import com.junction.api.types.PhysicianCreateRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().importOrder( ImportOrderBody.builder() .userId("63661a2b-2bb3-4125-bb1a-b590f64f057f") .billingType(Billing.CLIENT_BILL) .orderSet(OrderSetRequest.builder().build()) .collectionMethod(LabTestCollectionMethod.WALK_IN_TEST) .patientDetails( PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("2020-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build() ) .patientAddress( PatientAddress.builder() .receiverName("John Doe") .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .build() ) .sampleId("1234567890") .physician( PhysicianCreateRequest.builder() .firstName("Jane") .lastName("Doe") .npi("") .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.ImportOrder(context.TODO(), &junction.ImportOrderBody{ UserId: "63661a2b-2bb3-4125-bb1a-b590f64f057f", BillingType: junction.BillingClientBill, OrderSet: &junction.OrderSetRequest{}, CollectionMethod: junction.LabTestCollectionMethodWalkInTest, Physician: &junction.PhysicianCreateRequest{ FirstName: junction.String("Jane"), LastName: junction.String("Doe"), Npi: "", }, PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "2020-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddress{ ReceiverName: "John Doe", FirstLine: "123 Main St.", SecondLine: junction.String("Apt. 208"), City: "San Francisco", State: "CA", Zip: "91189", Country: "US", }, SampleId: "1234567890", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "order": { "user_id": "7ea94b27-a536-461f-ac4b-1c26c854d180", "id": "d3ec7ac7-2584-4254-9709-fc61d80635c4", "team_id": "59d4dfa1-e7c8-4d96-af15-74ca5ac5d189", "patient_details": { "first_name": "John", "last_name": "Doe", "dob": "1990-01-01T00:00:00+00:00", "gender": "male", "phone_number": "+11231234123", "email": "john@example.com" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main Street", "second_line": null, "city": "New York", "state": "NY", "zip": "12345", "country": "US", "phone_number": "+11231234123" }, "lab_test": { "id": "d0b479ec-afcc-4763-985c-4e23f17149f5", "slug": "59d4dfa1-testosterone", "name": "Testosterone", "sample_type": "serum", "method": "at_home_phlebotomy", "price": 0.0, "is_active": true, "status": "active", "fasting": false, "lab": null, "markers": null, "is_delegated": false, "auto_generated": false }, "details": { "type": "at_home_phlebotomy", "data": { "id": "21cb5e3f-25e3-443d-9fee-272de1393310", "appointment_id": null, "created_at": "2025-03-20T13:07:32+00:00", "updated_at": "2025-03-20T13:07:32+00:00" } }, "sample_id": "1234567890", "notes": null, "created_at": "2025-03-20T13:07:32+00:00", "updated_at": "2025-03-20T13:07:32+00:00", "events": [ { "id": 74769, "created_at": "2025-03-20T13:07:32+00:00", "status": "received.at_home_phlebotomy.ordered" }, { "id": 74770, "created_at": "2025-03-20T13:07:32+00:00", "status": "received.at_home_phlebotomy.requisition_bypassed" } ], "status": "received", "physician": { "first_name": "Jane", "last_name": "Doe", "npi": "123" }, "health_insurance_id": null, "requisition_form_url": null, "priority": false, "shipping_details": null, "activate_by": null, "passthrough": null, "billing_type": "client_bill", "icd_codes": null }, "status": "success", "message": "Order created successfully" } ``` # Create Payor Source: https://docs.junction.com/api-reference/lab-testing/insurance/create-payor POST /v3/payor Create or submit payor via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. Create a new payor. Allows the creation of new payors that don't already exist in Junction's system. Created payors are tied to the team that created them, so they will only be returned as search results when [searched](/api-reference/lab-testing/insurance/search-payor-get) by that same team. # Get search diagnosis Source: https://docs.junction.com/api-reference/lab-testing/insurance/search-diagnosis GET /v3/insurance/search/diagnosis Retrieve insurance search diagnosis via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/insurance/search/diagnosis?diagnosis_query=glucose' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.insurance.search_diagnosis(diagnosis_query="") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.insurance.searchDiagnosis({ diagnosisQuery: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.insurance.requests.SearchDiagnosisInsuranceRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.insurance().searchDiagnosis( SearchDiagnosisInsuranceRequest.builder() .diagnosisQuery("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Insurance.SearchDiagnosis(context.TODO(), &junction.SearchDiagnosisInsuranceRequest{ DiagnosisQuery: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} [ { "diagnosis_code": "D55.0", "description": "ANEMIA DUE TO G6PD DEFICIENCY" }, { "diagnosis_code": "D75.A", "description": "GLUC-6-PHOS DHYDRGNS DEF W/O ANEMIA" }, { "diagnosis_code": "E74.810", "description": "GLUC TRANSPORT PROTEIN TYPE 1 DEFIC" }, { "diagnosis_code": "E74.818", "description": "OTHER DISORDERS GLUCOSE TRANSPORT" } ] ``` # Get search payor Source: https://docs.junction.com/api-reference/lab-testing/insurance/search-payor-get GET /v3/insurance/search/payor Retrieve insurance search payor via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/insurance/search/payor?insurance_name=AETNA' \ --header 'accept: application/json' \ --header 'x-vital-api-key: {YOUR_KEY}' ``` ```json Response theme={null} [ { "code": "AARPA", "name": "AARP", "aliases": [ "AARP", "AARP" ], "org_address": { "first_line": "PO BOX 740819", "second_line": null, "country": "US", "zip": "30374", "city": "ATLANTA", "state": "GA" } } ] ``` # Get Lab Report Parser Job Source: https://docs.junction.com/api-reference/lab-testing/lab-report-parsing/get-lab-report-parser-job GET /lab_report/v1/parser/job/{job_id} Retrieve lab report parser job via the Junction API. Requires authentication with your team API key. Retrieve the status and results of a lab report parsing job. When the job status is `completed`, the `data` field will contain the extracted lab results with LOINC matches. **Job Status Values:** * `upload_pending` - Job created, waiting for file upload * `started` - File uploaded, parsing in progress * `completed` - Parsing complete, results available in `data` * `failed` - Parsing failed ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/lab_report/v1/parser/job/' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_report.parser_get_job("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labReport.parserGetJob({ jobId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labReport().parserGetJob(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabReport.ParserGetJob(context.TODO(), &junction.ParserGetJobLabReportRequest{ JobId: "", }) if err != nil { return err } fmt.Printf("Status: %s\n", response.Status) ``` ```json Response theme={null} { "job_id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "data": { "metadata": { "patient_first_name": "John", "patient_last_name": "Doe", "dob": "1990-05-15", "lab_name": "Quest Diagnostics", "date_reported": "2024-01-15", "date_collected": "2024-01-14", "specimen_number": "SP123456" }, "results": [ { "test_name": "Glucose", "value": "95", "type": "numeric", "units": "mg/dL", "min_reference_range": 70, "max_reference_range": 100, "interpretation": "normal", "is_above_max_range": false, "is_below_min_range": false, "loinc_matches": [ { "loinc_code": "2345-7", "loinc_name": "Glucose [Mass/volume] in Serum or Plasma", "display_name": "Glucose [Mass/volume] in Serum or Plasma", "aliases": ["Blood Sugar", "Fasting Glucose"], "confidence_score": 0.95 } ] }, { "test_name": "Hemoglobin A1c", "value": "5.4", "type": "numeric", "units": "%", "min_reference_range": 4.0, "max_reference_range": 5.6, "interpretation": "normal", "is_above_max_range": false, "is_below_min_range": false, "loinc_matches": [ { "loinc_code": "4548-4", "loinc_name": "Hemoglobin A1c/Hemoglobin.total in Blood", "display_name": "Hemoglobin A1c/Hemoglobin.total in Blood", "aliases": ["HbA1c", "Glycated Hemoglobin"], "confidence_score": 0.98 } ] } ] }, "needs_human_review": false, "is_reviewed": false } ``` # Create Lab Report Parser Job Source: https://docs.junction.com/api-reference/lab-testing/lab-report-parsing/post-lab-report-parser-job POST /lab_report/v1/parser/job Create or submit lab report parser job via the Junction API. Requires authentication with your team API key. Upload a lab report file (PDF, JPEG, or PNG) to create a parsing job. The job will extract lab results and match them to LOINC codes. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/lab_report/v1/parser/job' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --header 'Content-Type: multipart/form-data' \ --form 'file=@/path/to/lab_report.pdf' \ --form 'user_id=' \ --form 'needs_human_review=false' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) with open("lab_report.pdf", "rb") as f: data = client.lab_report.parser_create_job( file=[f], user_id="", needs_human_review=False, ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; import * as fs from "fs"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labReport.parserCreateJob({ file: [fs.createReadStream("lab_report.pdf")], userId: "", needsHumanReview: false, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labreport.requests.CreateLabReportParserJobBody; import java.io.File; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labReport().parserCreateJob( new File("lab_report.pdf"), CreateLabReportParserJobBody.builder() .userId("") .needsHumanReview(false) .build() ); ``` ```go Go theme={null} import ( "context" "os" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) file, _ := os.Open("lab_report.pdf") defer file.Close() response, err := c.LabReport.ParserCreateJob(context.TODO(), &junction.CreateLabReportParserJobBody{ File: []io.Reader{file}, UserId: "", NeedsHumanReview: junction.Bool(false), }) if err != nil { return err } fmt.Printf("Job ID: %s\n", response.JobId) ``` ```json Response theme={null} { "job_id": "550e8400-e29b-41d4-a716-446655440000", "status": "started", "data": null, "needs_human_review": false, "is_reviewed": false } ``` # Get Collection Instructions PDF for Lab Test Source: https://docs.junction.com/api-reference/lab-testing/lab-test-collection-instructions-pdf GET /v3/lab_test/{lab_test_id}/collection_instruction_pdf Retrieve lab test collection instructions PDF via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/lab_test//collection_instruction_pdf' \ --header 'accept: application/pdf' \ --header 'x-vital-api-key: {YOUR_KEY}' \ --output file.pdf ``` # Get Markers for Lab Test Source: https://docs.junction.com/api-reference/lab-testing/lab-test-markers GET /v3/lab_tests/{lab_test_id}/markers Retrieve lab tests markers via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/lab_tests/{lab_test_id}/markers' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_markers_for_lab_test("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getMarkersForLabTest({ labTestId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getMarkersForLabTest(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetMarkersForLabTest(context.TODO(), &junction.GetMarkersForLabTestLabTestsRequest{ LabTestId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "markers": [ { "id": 202, "name": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "slug": "acetylcholine-receptor-achr-antibodies-complete-profile-with-reflex-to-musk-antibodies", "description": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "lab_id": 6, "provider_id": "165605", "type": "biomarker", "unit": null, "price": "N/A", "expected_results": [ { "id": 2938, "name": "AChR Blocking Abs, Serum", "slug": "achr-blocking-abs-serum", "lab_id": 6, "provider_id": "085927", "loinc": { "id": 3514, "name": "Acetylcholine receptor blocking Ab Qn (S)", "slug": "acetylcholine-receptor-blocking-ab-qn-s", "code": "11561-8", "unit": "%{inhibition}" } }, { "id": 2939, "name": "AChR Binding Abs, Serum", "slug": "achr-binding-abs-serum", "lab_id": 6, "provider_id": "085904", "loinc": { "id": 3174, "name": "Acetylcholine receptor binding Ab (S) [Moles/Vol]", "slug": "acetylcholine-receptor-binding-ab-s-moles-vol", "code": "11034-6", "unit": "nmol/L" } }, { "id": 2940, "name": "AChR-modulating Ab", "slug": "achr-modulating-ab", "lab_id": 6, "provider_id": "505199", "loinc": { "id": 61121, "name": "Acetylcholine receptor modulation Ab FC Ql (S)", "slug": "acetylcholine-receptor-modulation-ab-fc-ql-s", "code": "99062-2", "unit": null } } ] } ], "total": 2, "page": 1, "size": 2 } ``` # Get Lab Accounts Source: https://docs.junction.com/api-reference/lab-testing/lab_accounts GET /v3/lab_test/lab_account Retrieve lab test lab account via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/lab_test/lab_account' \ --header 'x-vital-api-key: {YOUR_KEY}' ``` # Get Labels PDF Source: https://docs.junction.com/api-reference/lab-testing/labels-pdf GET /v3/order/{order_id}/labels/pdf Retrieve order labels pdf via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//labels/pdf' \ --header 'accept: application/pdf' \ --header 'x-vital-api-key: {YOUR_KEY}' \ --output file.pdf ``` # Get All Available Labs Source: https://docs.junction.com/api-reference/lab-testing/labs GET /v3/lab_tests/labs Retrieve lab tests labs via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/lab_tests/labs' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_labs() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getLabs(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getLabs(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetLabs(context.TODO()) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} [ { "id": 1, "slug": "labcorp", "name": "LabCorp", "first_line_address": "123 Main St", "city": "San Francisco", "zipcode": "91789", "collection_methods": ["at_home_phlebotomy", "walk_in_test"], "sample_types": ["saliva", "serum"] } ] ``` # Get Collection Instructions PDF for Order Source: https://docs.junction.com/api-reference/lab-testing/order-collection-instructions-pdf GET /v3/order/{order_id}/collection_instruction_pdf Retrieve order collection instructions PDF via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//collection_instruction_pdf' \ --header 'accept: application/pdf' \ --header 'x-vital-api-key: {YOUR_KEY}' \ --output file.pdf ``` # Get order PSC info Source: https://docs.junction.com/api-reference/lab-testing/order-psc-info GET /v3/order/{order_id}/psc/info Retrieve order PSC info via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//psc/info' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_order_psc_info("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getOrderPscInfo({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getOrderPscInfo(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetOrderPscInfo(context.TODO(), &junction.GetOrderPscInfoLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "lab_id": 27, "slug": "labcorp", "patient_service_centers": [ { "metadata": { "name": "LABCORP", "state": "AZ", "city": "Phoenix", "zip_code": "85006", "first_line": "1300 N 12th St", "second_line": "Ste 300", "phone_number": "480-878-3988", "fax_number": "844-346-5903", "hours": null }, "distance": "25", "capabilities": ["stat"] } ] } ``` # Get Markers for Order Set Source: https://docs.junction.com/api-reference/lab-testing/order-set-marker POST /v3/lab_tests/list_order_set_markers Create or submit lab tests list order set markers via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/lab_tests/list_order_set_markers' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ -d ' { "lab_test_ids": ["id"], "add_on": { "provider_ids": ["123"] } } ' ``` ```python Python theme={null} from junction import AddOnOrder, Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_markers_for_order_set( lab_test_ids=[""], add_on=AddOnOrder(provider_ids=["123"]), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getMarkersForOrderSet({ body: { labTestIds: [""], addOn: { providerIds: ["123"] }, }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.types.AddOnOrder; import com.junction.api.types.OrderSetRequest; import java.util.List; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getMarkersForOrderSet( OrderSetRequest.builder() .labTestIds(List.of("")) .addOn( AddOnOrder.builder() .providerIds(List.of("123")) .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetMarkersForOrderSet(context.TODO(), &junction.GetMarkersForOrderSetLabTestsRequest{ Body: &junction.OrderSetRequest{ LabTestIds: []string{""}, AddOn: &junction.AddOnOrder{ ProviderIds: []string{"123"}, }, }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "markers": [ { "id": 202, "name": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "slug": "acetylcholine-receptor-achr-antibodies-complete-profile-with-reflex-to-musk-antibodies", "description": "Acetylcholine Receptor (AChR) Antibodies, Complete Profile with Reflex to MuSK Antibodies", "lab_id": 6, "provider_id": "165605", "type": "biomarker", "unit": null, "price": "N/A", "expected_results": [ { "id": 2938, "name": "AChR Blocking Abs, Serum", "slug": "achr-blocking-abs-serum", "lab_id": 6, "provider_id": "085927", "loinc": { "id": 3514, "name": "Acetylcholine receptor blocking Ab Qn (S)", "slug": "acetylcholine-receptor-blocking-ab-qn-s", "code": "11561-8", "unit": "%{inhibition}" } }, { "id": 2939, "name": "AChR Binding Abs, Serum", "slug": "achr-binding-abs-serum", "lab_id": 6, "provider_id": "085904", "loinc": { "id": 3174, "name": "Acetylcholine receptor binding Ab (S) [Moles/Vol]", "slug": "acetylcholine-receptor-binding-ab-s-moles-vol", "code": "11034-6", "unit": "nmol/L" } }, { "id": 2940, "name": "AChR-modulating Ab", "slug": "achr-modulating-ab", "lab_id": 6, "provider_id": "505199", "loinc": { "id": 61121, "name": "Acetylcholine receptor modulation Ab FC Ql (S)", "slug": "acetylcholine-receptor-modulation-ab-fc-ql-s", "code": "99062-2", "unit": null } } ] } ], "total": 2, "page": 1, "size": 2 } ``` # Get order transaction Source: https://docs.junction.com/api-reference/lab-testing/order-transactions/get-order-transaction GET /v3/order_transaction/{transaction_id} Retrieve order transaction via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.order_transaction.get_transaction("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.orderTransaction.getTransaction({ transactionId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.orderTransaction().getTransaction(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.OrderTransaction.GetTransaction(context.TODO(), &junction.GetTransactionOrderTransactionRequest{ TransactionId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "team_id": "cbb64555-af07-46c1-be09-ef89308e9b60", "status": "active", "orders": [ { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "low_level_status": "transit_customer", "low_level_status_created_at": "2022-01-03T00:00:00Z", "origin": "initial" } ] } ``` # Update a Test Source: https://docs.junction.com/api-reference/lab-testing/patch-lab-test PATCH /v3/lab_tests/{lab_test_id} Partially update lab tests via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.update_lab_test( "", name="", active=True, ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.updateLabTest({ labTestId: "", name: "", active: true, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.UpdateLabTestRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().updateLabTest( "", UpdateLabTestRequest.builder() .name("") .active(true) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.UpdateLabTest(context.TODO(), &junction.UpdateLabTestRequest{ LabTestId: "", Name: junction.String(""), Active: junction.Bool(true), }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "5af405fc-fafb-49e8-b0bf-fe9d91df6a7d", "slug": "a94e3005-new-test", "name": "New test", "sample_type": "serum", "method": "at_home_phlebotomy", "price": 0.0, "is_active": true, "status": "active", "fasting": false, "lab": { "id": 26, "slug": "quest", "name": "Quest", "first_line_address": "100 Tri State International #100", "city": "Lincolnshire", "zipcode": "60069", "collection_methods": ["at_home_phlebotomy", "walk_in_test"], "sample_types": ["serum", "saliva", "urine"] }, "markers": [ { "id": 6859, "name": "17-Hydroxyprogesterone", "slug": "17-hydroxyprogesterone", "description": "17-Hydroxyprogesterone", "lab_id": 26, "provider_id": "17180", "type": "biomarker", "unit": null, "price": "N/A", "aoe": null, "a_la_carte_enabled": true }, { "id": 8213, "name": "17-Hydroxypregnenolone", "slug": "17-hydroxypregnenolone", "description": "17-Hydroxypregnenolone", "lab_id": 26, "provider_id": "8352", "type": "biomarker", "unit": null, "price": "N/A", "aoe": null, "a_la_carte_enabled": true } ], "is_delegated": false, "auto_generated": false } ``` # Update an order Source: https://docs.junction.com/api-reference/lab-testing/patch-order PATCH /v3/order/{order_id} Update an order via the Junction API. Requires authentication with your team API key. You can only update an order while its [low-level status](/lab/workflow/lab-test-lifecycle#statuses) is `ordered` or `awaiting_registration`. ```bash cURL theme={null} curl --request PATCH \ --url https://api.sandbox.junction.com/v3/order/ \ --header 'x-vital-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "activate_by": "2026-06-01" }' ``` ```json Response theme={null} { "order": { "id": "0ee312e2-6773-4a21-a6e1-506882cd98ed", "team_id": "cbb64555-af07-46c1-be09-ef89308e9b60", "user_id": "94e2d9f2-d600-4a23-9f08-536df378e2c7", "activate_by": "2026-06-01", "status": "received" }, "status": "success", "message": "order updated" } ``` # Create a Test Source: https://docs.junction.com/api-reference/lab-testing/post-test POST /v3/lab_tests Create or submit lab tests via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction, LabTestCollectionMethod from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.create( name="", method=LabTestCollectionMethod.TESTKIT, description="", provider_ids=["000110"], ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.create({ name: "", method: "testkit", description: "", providerIds: ["000110"], }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.CreateLabTestRequest; import com.junction.api.types.LabTestCollectionMethod; import java.util.List; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().create( CreateLabTestRequest.builder() .name("") .method(LabTestCollectionMethod.TESTKIT) .description("") .providerIds(List.of("000110")) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.Create(context.TODO(), &junction.CreateLabTestRequest{ Name: "", Method: junction.LabTestCollectionMethodTestkit, Description: "", ProviderIds: []string{"000110"}, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "2e82a1d4-e2e6-421c-9c54-2210d667ce48", "slug": "a94e3005-labcorp-panel", "name": "Labcorp panel", "sample_type": "serum", "method": "at_home_phlebotomy", "price": 0.0, "is_active": true, "status": "active", "fasting": false, "lab": { "id": 27, "slug": "labcorp", "name": "Labcorp", "first_line_address": "labcorp address", "city": "Lincolnshire", "zipcode": "60069", "collection_methods": ["at_home_phlebotomy", "walk_in_test"], "sample_types": ["serum", "saliva", "urine"] }, "markers": [ { "id": 195, "name": "Abnormal Bleeding Profile", "slug": "abnormal-bleeding-profile", "description": "Abnormal Bleeding Profile", "lab_id": 27, "provider_id": "116004", "type": "biomarker", "unit": null, "price": "N/A", "aoe": null, "a_la_carte_enabled": true } ], "is_delegated": false, "auto_generated": false } ``` # Get PSC info Source: https://docs.junction.com/api-reference/lab-testing/psc-info GET /v3/order/psc/info Retrieve order PSC info via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/psc/info?zip_code=85004&lab_id=27' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_psc_info(zip_code="85004", lab_id=27) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPscInfo({ zipCode: "85004", labId: 27 }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.GetPscInfoLabTestsRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPscInfo( GetPscInfoLabTestsRequest.builder() .zipCode("85004") .labId(27) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPscInfo(context.TODO(), &junction.GetPscInfoLabTestsRequest{ ZipCode: "85004", LabId: 27, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "lab_id": 27, "slug": "labcorp", "patient_service_centers": [ { "metadata": { "name": "LABCORP", "state": "AZ", "city": "Phoenix", "zip_code": "85006", "first_line": "1300 N 12th St", "second_line": "Ste 300", "phone_number": "480-878-3988", "fax_number": "844-346-5903", "hours": null }, "distance": "25", "capabilities": ["stat"] } ] } ``` # PSC Appointment Availability Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/appointment-psc-availability POST /v3/order/psc/appointment/availability Create or submit order PSC appointment availability via the Junction API. Requires authentication with your team API key. Use the `allow_stale` parameter for faster responses via the Availability Cache. This feature is currently in closed beta. See [PSC Appointment Scheduling](/lab/walk-in/psc-appointment-scheduling#availability-cache) for more info. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/psc/appointment/availability' \ --header 'accept: application/json' \ --header 'x-vital-api-key: {YOUR_KEY}' \ --data ' { "lab": "quest", "zip_code": "85004", "radius": "25" } ' ``` ```json Response theme={null} { "slots": [ { "location": { "location": { "lng": -112.0568538, "lat": 33.4631386 }, "address": { "first_line": "1300 N 12th St", "second_line": "Ste 300", "city": "Phoenix", "state": "AZ", "zip_code": "85006", }, "code": "23070", "name": "QUEST", "iana_timezone": "America/Los_Angeles" }, "date":"2023-05-09", "slots": [ { "booking_key": "foo123", "start": "2023-05-09T17:00:00+00:00", "end": "2023-05-09T19:00:00+00:00", "expires_at": "2023-05-09T12:39:57.827000+00:00", "price": 0.0, "is_priority": true, "num_appointments_available": 1 }, ... ], }, { "location": { "location": { "lng": -112.0568538, "lat": 33.4631386 }, "address": { "first_line": "1300 N 12th St", "second_line": "Ste 300", "city": "Phoenix", "state": "AZ", "zip_code": "85006", }, "code": "23070", "name": "QUEST" }, "date":"2023-05-10", "slots": [ { "booking_key": "bar456", "start": "2023-05-10T12:00:00+00:00", "end": "2023-05-10T14:00:00+00:00", "expires_at": "2023-05-09T12:39:57.852000+00:00", "price": 0.0, "is_priority": true, "num_appointments_available": 1 }, ... ], }, ], "timezone": null } ``` # Book PSC Appointment Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/appointment-psc-booking POST /v3/order/{order_id}/psc/appointment/book Create or submit order PSC appointment book via the Junction API. Requires authentication with your team API key. This endpoint supports optional `idempotency_key` and Async Confirmation features. These features are currently in closed beta. See [PSC Appointment Scheduling](/lab/walk-in/psc-appointment-scheduling#beta-features) for more info. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/psc/appointment/book' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "booking_key": "foo123" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.book_psc_appointment( "", booking_key="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.bookPscAppointment({ orderId: "", body: { bookingKey: "", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.types.AppointmentBookingRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().bookPscAppointment( "", AppointmentBookingRequest.builder() .bookingKey("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.BookPscAppointment(context.TODO(), &junction.BookPscAppointmentLabTestsRequest{ OrderId: "", Body: &junction.AppointmentBookingRequest{ BookingKey: "", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-15T16:00:00+00:00", "end_at": "2023-05-15T18:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "patient_service_center", "provider": "quest", "status": "pending", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true, "external_id": "ABCDEF" } ``` # PSC Appointment Cancellation Reasons Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/appointment-psc-cancellation-reasons GET /v3/order/psc/appointment/cancellation-reasons Retrieve order PSC appointment cancellation-reasons via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/psc/appointment/cancellation-reasons' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_psc_appointment_cancellation_reason() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPscAppointmentCancellationReason(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPscAppointmentCancellationReason(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPscAppointmentCancellationReason(context.TODO()) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json theme={null} [ { "id": "5c0257ef-6fea-4a22-b20a-3ddab573d5c9", "name": "Other", "is_refundable": true } ] ``` # Cancel PSC Appointment Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling PATCH /v3/order/{order_id}/psc/appointment/cancel Partially update order PSC appointment cancel via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request PATCH \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/psc/appointment/cancel' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "cancellation_reason_id": "7dfd7da5-ed6e-40bb-a7e4-c8003f0c10a9" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.cancel_psc_appointment( "", cancellation_reason_id="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelPscAppointment({ orderId: "", cancellationReasonId: "", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelPscAppointment( "", VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest.builder() .cancellationReasonId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelPscAppointment(context.TODO(), &junction.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest{ OrderId: "", CancellationReasonId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "patient_service_center", "provider": "quest", "status": "cancelled", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` # Reschedule PSC Appointment Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/appointment-psc-rescheduling PATCH /v3/order/{order_id}/psc/appointment/reschedule Partially update order PSC appointment reschedule via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request PATCH \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/psc/appointment/reschedule' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "booking_key": "bar456" } ' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.reschedule_psc_appointment( "", booking_key="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.reschedulePscAppointment({ orderId: "", body: { bookingKey: "", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ReschedulePscAppointmentLabTestsRequest; import com.junction.api.types.AppointmentRescheduleRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().reschedulePscAppointment( "", ReschedulePscAppointmentLabTestsRequest.builder() .body( AppointmentRescheduleRequest.builder() .bookingKey("") .build() ) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.ReschedulePscAppointment(context.TODO(), &junction.ReschedulePscAppointmentLabTestsRequest{ OrderId: "", Body: &junction.AppointmentRescheduleRequest{ BookingKey: "", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit":"14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "patient_service_center", "provider": "quest", "status": "confirmed", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` # Get PSC Appointment Source: https://docs.junction.com/api-reference/lab-testing/psc-scheduling/get-psc-appointment GET /v3/order/{order_id}/psc/appointment Retrieve order PSC appointment via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order/413d7205-f8a9-42ed-aa4a-edb99e481ca0/psc/appointment' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_psc_appointment("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPscAppointment({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPscAppointment(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPscAppointment(context.TODO(), &junction.GetPscAppointmentLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "patient_service_center", "provider": "quest", "status": "confirmed", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` # Register Testkit Order Source: https://docs.junction.com/api-reference/lab-testing/register-order POST /v3/order/testkit/register Create or submit order testkit register via the Junction API. Requires authentication with your team API key. Patient name fields (`first_name`, `last_name`) must follow specific validation rules due to lab restrictions. See [Patient Name Validation](/lab/workflow/order-requirements#patient-name-validation) for complete details. ```python Python theme={null} from junction import Gender, Junction, PatientAddressWithValidation, PatientDetailsWithValidation from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.testkit.register( sample_id="", user_id="", patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="1990-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddressWithValidation( receiver_name="John Doe", first_line="123 Main St", second_line="Apt. 1", city="San Francisco", state="CA", zip="94111", country="US", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.testkit.register({ sampleId: "", userId: "", patientDetails: { firstName: "John", lastName: "Doe", dob: "1990-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { receiverName: "John Doe", firstLine: "123 Main St", secondLine: "Apt. 1", city: "San Francisco", state: "CA", zip: "94111", country: "US", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.testkit.requests.RegisterTestkitRequest; import com.junction.api.types.Gender; import com.junction.api.types.PatientAddressWithValidation; import com.junction.api.types.PatientDetailsWithValidation; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.testkit().register( RegisterTestkitRequest.builder() .sampleId("") .patientDetails( PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("1990-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build() ) .patientAddress( PatientAddressWithValidation.builder() .firstLine("123 Main St") .city("San Francisco") .state("CA") .zip("94111") .country("US") .build() ) .userId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Testkit.Register(context.TODO(), &junction.RegisterTestkitRequest{ SampleId: "", UserId: junction.String(""), PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "1990-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddressWithValidation{ ReceiverName: junction.String("John Doe"), FirstLine: "123 Main St", SecondLine: junction.String("Apt. 1"), City: "San Francisco", State: "CA", Zip: "94111", Country: "US", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order/testkit/register' \ --header 'Accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --data ' { "user_id":"63661a2b-2bb3-4125-bb1a-b590f64f057f", "sample_id":"123123123", "patient_details":{ "first_name": "John", "last_name": "Doe", "dob": "2020-01-01", "gender": "male", "phone_number": "+1123456789", "email": "email@email.com" }, "patient_address":{ "receiver_name": "John Doe", "street": "123 Main St.", "street_number": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "US" }, "consents":[ {"consentType": "terms-of-use"}, {"consentType": "telehealth-informed-consent"}, {"consentType": "notice-of-privacy-practices"} ], "physician":{ "first_name": "Doctor", "last_name": "Doc", "npi": "123123123" } } ' ``` ```json Response theme={null} { "order": { "id": "96edc6ef-3b2c-412b-b9e5-96f361f93aec", "team_id": "b080b20c-e162-4cf1-9c7d-8faee72ee08e", "user_id": "9f1e094e-1641-466b-b668-d4d3300e569f", "patient_details": { "first_name": "John", "last_name": "Doe", "phone_number": "+11234567890", "email": "doe@email.com", "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+11234567890" }, "shipping_details": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+11234567890" }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "health_insurance_id": "7695cc28-f9e5-400d-95d2-ec7d9ec580df", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "received", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.awaiting_registration" }, { "id": 3, "created_at": "2022-01-02T00:00:00Z", "status": "received.testkit.requisition_created" }, { "id": 4, "created_at": "2022-01-03T00:00:00Z", "status": "received.testkit.testkit_registered" } ] }, "status": "string", "message": "string" } ``` # Get Requisition Form PDF Source: https://docs.junction.com/api-reference/lab-testing/requisition-pdf GET /v3/order/{order_id}/requisition/pdf Retrieve order requisition pdf via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//requisition/pdf' \ --header 'accept: application/pdf' \ --header 'x-vital-api-key: YOUR_API_KEY' \ --output file.pdf ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_order_requistion_pdf("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getOrderRequistionPdf({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getOrderRequistionPdf(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetOrderRequistionPdf(context.TODO(), &junction.GetOrderRequistionPdfLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Resend order webhooks Source: https://docs.junction.com/api-reference/lab-testing/resend-order-events POST /v3/order/resend_events Replay the latest webhook event for one or more orders via the Junction API. At least one of `order_ids` or `start_at` is required. When using `start_at`, `end_at` defaults to the current time and the window cannot exceed 60 days. ```bash cURL theme={null} curl --request POST \ --url https://api.sandbox.junction.com/v3/order/resend_events \ --header 'x-vital-api-key: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data '{ "order_ids": ["0ee312e2-6773-4a21-a6e1-506882cd98ed"] }' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.order.resend_events( order_ids=["0ee312e2-6773-4a21-a6e1-506882cd98ed"], ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.order.resendEvents({ orderIds: ["0ee312e2-6773-4a21-a6e1-506882cd98ed"], }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.order.requests.ResendWebhookBody; import java.util.List; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.order().resendEvents( ResendWebhookBody.builder() .orderIds(List.of("0ee312e2-6773-4a21-a6e1-506882cd98ed")) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Order.ResendEvents(context.TODO(), &junction.ResendWebhookBody{ OrderIds: []string{"0ee312e2-6773-4a21-a6e1-506882cd98ed"}, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "order_ids": ["0ee312e2-6773-4a21-a6e1-506882cd98ed"] } ``` # Get Order Transaction Results Source: https://docs.junction.com/api-reference/lab-testing/results/get-order-transaction-results GET /v3/order_transaction/{transaction_id}/result Retrieve order transaction result via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order_transaction//result' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.order_transaction.get_transaction_result("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.orderTransaction.getTransactionResult({ transactionId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.orderTransaction().getTransactionResult(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.OrderTransaction.GetTransactionResult(context.TODO(), &junction.GetTransactionResultOrderTransactionRequest{ TransactionId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "metadata": { "age": 19, "dob": "18/08/1993", "clia_number": "12331231", "patient": "Bob Smith", "provider": "Dr. Jack Smith", "laboratory": "LabCorp", "date_reported": "2020-01-01", "date_collected": "2022-02-02", "specimen_number": "123131", "date_received": "2022-01-01", "status": "final", "interpretation": "abnormal" }, "results": [ { "name": "Sex Horm Binding Glob, Serum", "slug": "sex-horm-binding-glob-serum", "value": 30.4, "result": "30.4", "type": "numeric", "unit": "nmol/L", "timestamp": "2024-10-31T09:08:00+00:00", "notes": "Final", "min_range_value": 24.6, "max_range_value": 122, "is_above_max_range": false, "is_below_min_range": false, "interpretation": "normal", "loinc": "13967-5", "loinc_slug": "sex-hormone-binding-globulin-moles-vol", "provider_id": "082016", "source_markers": [ { "marker_id": 229, "name": "Testosterone Free, Profile I", "slug": "testosterone-free-profile-i", "provider_id": "140226" } ] } ], "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "completed", "orders": [ { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2022-01-04T00:00:00Z", "low_level_status": "redraw_available", "low_level_status_created_at": "2022-01-04T00:00:00Z", "origin": "initial" }, { "id": "15db29d7-ffeb-4540-9513-3c38f26b87aa", "created_at": "2020-01-10T00:00:00Z", "updated_at": "2022-01-14T00:00:00Z", "low_level_status": "completed", "low_level_status_created_at": "2022-01-14T00:00:00Z", "origin": "redraw" } ] } } ``` # Get Order Transaction Results PDF Source: https://docs.junction.com/api-reference/lab-testing/results/get-order-transaction-results-pdf GET /v3/order_transaction/{transaction_id}/result/pdf Retrieve order transaction result pdf via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order_transaction//result/pdf' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.order_transaction.get_transaction_result_pdf("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.orderTransaction.getTransactionResultPdf({ transactionId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.orderTransaction().getTransactionResultPdf(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.OrderTransaction.GetTransactionResultPdf(context.TODO(), &junction.GetTransactionResultPdfOrderTransactionRequest{ TransactionId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} "PDF with results" ``` # Get Results Source: https://docs.junction.com/api-reference/lab-testing/results/get-results GET /v3/order/{order_id}/result Retrieve order result via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//result' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_result_raw("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getResultRaw({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getResultRaw(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetResultRaw(context.TODO(), &junction.GetResultRawLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "metadata": { "age": 19, "dob": "18/08/1993", "clia_number": "12331231", "patient": "Bob Smith", "provider": "Dr. Jack Smith", "laboratory": "LabCorp", "date_reported": "2020-01-01", "date_collected": "2022-02-02", "specimen_number": "123131", "date_received": "2022-01-01", "status": "final", "interpretation": "abnormal" }, "results": [ { "name": "Sex Horm Binding Glob, Serum", "slug": "sex-horm-binding-glob-serum", "value": 30.4, "result": "30.4", "type": "numeric", "unit": "nmol/L", "timestamp": "2024-10-31T09:08:00+00:00", "notes": "Final", "min_range_value": 24.6, "max_range_value": 122, "is_above_max_range": false, "is_below_min_range": false, "interpretation": "normal", "loinc": "13967-5", "loinc_slug": "sex-hormone-binding-globulin-moles-vol", "provider_id": "082016", "source_markers": [ { "marker_id": 229, "name": "Testosterone Free, Profile I", "slug": "testosterone-free-profile-i", "provider_id": "140226" } ] } ], "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "completed", "orders": [ { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2022-02-04T00:00:00Z", "low_level_status": "completed", "low_level_status_created_at": "2022-02-04T00:00:00Z", "origin": "initial" } ] } } ``` # Get Results Metadata Source: https://docs.junction.com/api-reference/lab-testing/results/get-results-metadata GET /v3/order/{order_id}/result/metadata Retrieve order result metadata via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//result/metadata' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_result_metadata("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getResultMetadata({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getResultMetadata(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetResultMetadata(context.TODO(), &junction.GetResultMetadataLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "age": 19, "dob": "18/08/1993", "clia_number": "12331231", "patient": "Bob Smith", "provider": "Dr. Jack Smith", "laboratory": "Quest Diagnostics", "date_reported": "2020-01-01", "date_collected": "2022-02-02", "specimen_number": "123131", "date_received": "2022-01-01", "status": "final", "interpretation": "normal" } ``` # Get Results PDF Source: https://docs.junction.com/api-reference/lab-testing/results/get-results-pdf GET /v3/order/{order_id}/result/pdf Retrieve order result pdf via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url '{{BASE_URL}}/v3/order//result/pdf' \ --header 'accept: application/json' \ --header 'x-vital-api-key: YOUR_API_KEY' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_result_pdf("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getResultPdf({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getResultPdf(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetResultPdf(context.TODO(), &junction.GetResultPdfLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} "Returns PDF of test data - .pdf" ``` # Simulate Order Source: https://docs.junction.com/api-reference/lab-testing/simulate-order POST /v3/order/{order_id}/test Create or submit order test via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url '{{BASE_URL}}/v3/order//test' \ --header 'x-vital-api-key: {YOUR_KEY}' ``` # Get Available Tests Source: https://docs.junction.com/api-reference/lab-testing/tests GET /v3/lab_tests Retrieve lab tests via the Junction API. Requires authentication with your team API key. > **Deprecated:** This endpoint is deprecated. Please use the paginated version `/v3/lab_test` instead. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.get(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().get(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.Get(context.TODO(), &junction.GetLabTestsRequest{}) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} [ { "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "sample_type": "dried blood spot", "method": "testkit", "price": 10, "is_active": true, "lab": { "slug": "USSL", "name": "US Specialty Lab", "first_line_address": "123 Main St", "city": "New York", "zipcode": "10001" }, "markers": [ { "name": "Thyroid Stimulating Hormone", "slug": "tsh", "description": "" } ] } } ] ``` # Get Available Tests Source: https://docs.junction.com/api-reference/lab-testing/tests-paginated GET /v3/lab_test Retrieve lab test via the Junction API. Requires authentication with your team API key. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get_paginated() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.getPaginated(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().getPaginated(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.GetPaginated(context.TODO(), &junction.GetPaginatedLabTestsRequest{}) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "data": [ { "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "sample_type": "dried blood spot", "method": "testkit", "price": 10, "is_active": true, "lab": { "slug": "USSL", "name": "US Specialty Lab", "first_line_address": "123 Main St", "city": "New York", "zipcode": "10001" }, "markers": [ { "name": "Thyroid Stimulating Hormone", "slug": "tsh", "description": "" } ] } } ], "next_cursor": null } ``` # Accept Unmatched Result Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/accept-unmatched-result POST /v3/unmatched_result/{raw_result_id}/accept Accept a match for an unmatched lab result via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Create Unmatched Result Test Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/create-unmatched-result-test POST /v3/unmatched_result_test Create a Sandbox test run that generates an unmatched lab result via the Junction API. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. This endpoint is available only in Sandbox and requires unmatched-result testing to be enabled for your team. Every request requires an `X-Idempotency-Key` header. # Get Unmatched Result Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/get-unmatched-result GET /v3/unmatched_result/{raw_result_id} Retrieve a lab result that requires match review via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Get Unmatched Result Test Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/get-unmatched-result-test GET /v3/unmatched_result_test/{run_id} Retrieve the status and generated artifacts for a Sandbox unmatched-result test run via the Junction API. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. This endpoint is available only in Sandbox and requires unmatched-result testing to be enabled for your team. # List Unmatched Result Test Cases Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/list-unmatched-result-test-cases GET /v3/unmatched_result_test/case List the supported Sandbox unmatched-result test cases and their requirements via the Junction API. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. This endpoint is available only in Sandbox and requires unmatched-result testing to be enabled for your team. # List Unmatched Results Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/list-unmatched-results GET /v3/unmatched_result List lab results that require match review via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Resolve Unmatched Result Source: https://docs.junction.com/api-reference/lab-testing/unmatched-results/resolve-unmatched-result POST /v3/unmatched_result/{raw_result_id}/resolve Reject or escalate an unmatched lab result via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. # Update Order Draw Completed Source: https://docs.junction.com/api-reference/lab-testing/update-order-draw-completed PATCH /v3/order/{order_id}/draw_completed Partially update order draw completed via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. Update an on-site collection order when the draw has been completed. ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.update_on_site_collection_order_draw_completed("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.updateOnSiteCollectionOrderDrawCompleted({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().updateOnSiteCollectionOrderDrawCompleted(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.UpdateOnSiteCollectionOrderDrawCompleted(context.TODO(), &junction.UpdateOnSiteCollectionOrderDrawCompletedLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "order": { "id": "ea7eae96-2c25-404f-b043-bfc08584610d", "team_id": "c26a9cc7-cdff-4f23-a5f6-74d40088c16a", "user_id": "63661a2b-2bb3-4125-bb1a-b590f64f057f", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "priority": false, "health_insurance_id": "33ec11aa-d8bf-4f46-950d-c9171be3c22f", "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z" }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit" }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.on_site_collection.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.on_site_collection.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.on_site_collection.draw_completed" } ] }, "status": "string", "message": "string" } ``` # Bulk Export Source: https://docs.junction.com/api-reference/link/bulk-export POST /v2/link/bulk_export Create or submit link bulk export via the Junction API. Requires authentication with your team API key. If you are planning to migrate connections, please [chat with us through support channels](/home/getting-support). Link Migration endpoints are disabled by default. You should [pause the connections](/api-reference/link/bulk-pause) before bulk exporting them. Pausing stops Junction systems from refreshing the connections, ensuring the exported data is the most up-to-date. # Bulk Import Source: https://docs.junction.com/api-reference/link/bulk-import POST /v2/link/bulk_import Create or submit link bulk import via the Junction API. Requires authentication with your team API key. If you are planning to migrate connections, please [chat with us through support channels](/home/getting-support). Link Migration endpoints are disabled by default. Import existing provider connections to your [Bring Your Own OAuth](/wearables/connecting-providers/bring-your-own-oauth/overview) application credentials. Before migrating any connection through this endpoint, you must first [configure your BYOO app credential](/wearables/connecting-providers/bring-your-own-oauth/overview#setting-up-your-oauth-credentials) for the data provider on your Junction Team. Note that these connections cannot be migrated: 1. Any connection that is bound to an OAuth application credential not in your possession. 2. Any connection that is not bound to the OAuth application credential set on your Junction Team. ### Asynchronous execution The Bulk Import endpoint enqueues all connections you submitted to a persistent background operation. It then responds *202 Accepted* immediately afterwards. You can inspect the status of the resulting background operation through the [List Bulk Ops](/api-reference/link/list-bulk-ops) endpoint. Optionally, you may opt into the `wait_for_completion` mode, which would respond with 200 OK only if the operation does complete within 20 seconds. Otherwise, the endpoint responds 202 Accepted. You can submit any number of β€” or even all β€” connections through the Bulk Import API within a short period of time. Enqueuing is fast and does not disrupt the progress of the background operation. # Bulk Pause Source: https://docs.junction.com/api-reference/link/bulk-pause POST /v2/link/bulk_pause Create or submit link bulk pause via the Junction API. Requires authentication with your team API key. If you are planning to migrate connections, please [chat with us through support channels](/home/getting-support). Link Migration endpoints are disabled by default. # Bulk Trigger Historical Pull Source: https://docs.junction.com/api-reference/link/bulk-trigger-historical-pull POST /v2/link/bulk_trigger_historical_pull Create or submit link bulk trigger historical pull via the Junction API. Requires authentication with your team API key. If you are planning to migrate connections, please [chat with us through support channels](/home/getting-support). Link Migration endpoints are disabled by default. ### Asynchronous execution The Bulk Trigger Historical Pull endpoint enqueues all trigger requests you submitted to a persistent background operation. It then responds *202 Accepted* immediately afterwards. You can inspect the status of the resulting background operation through the [List Bulk Ops](/api-reference/link/list-bulk-ops) endpoint. Optionally, you may opt into the `wait_for_completion` mode, which would respond with 200 OK only if the operation does complete within 20 seconds. Otherwise, the endpoint responds 202 Accepted. You can trigger historical pull on any number of β€” or even all β€” connections through the Bulk Trigger Historical Pull API within a short period of time. Enqueuing is fast and does not disrupt the progress of the background operation. #### Managing provider API rate limits Junction transparently batches and throttles the trigger requests. This is to avoid exhausting the provider API rate limits of your Bring Your Own OAuth custom credentials. You can submit as many trigger requests as needed. | Provider | Historical Pull Triggering Rate | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Garmin | 2 connections every 1 minute | | Fitbit, Polar | 250 connections at a time; no time-based throttling | | Strava | 1 connection every 15 minutes | | Oura | 150 connections every 5 minutes | | Withings | 8 connections every 1 minute, assuming your app uses the [Withings Enterprise Plan](https://developer.withings.com/developer-guide/v3/withings-solutions/withings-api-plans/). | | All other providers | 8 connections every 1 minute | #### Historical Pull Range Bulk Trigger Historical Pull respects any restricting [User Ingestion Bounds](/wearables/providers/data-ingestion-bounds) and/or any [Team Data Pull Preferences](/wearables/providers/introduction#customizing-historical-data-pull-range) you have specified. If you have specified a large number of days to pull, you should be aware that: 1. The background operation will take a longer time to run to completion. 2. It may still cause temporary disruption to data polling and webhook processing, even after the triggering has been throttled. # Complete Password Provider MFA Source: https://docs.junction.com/api-reference/link/complete-password-provider-mfa POST /v2/link/provider/password/{provider}/complete_mfa Create or submit link provider password complete mfa via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/provider/password/{provider}/complete_mfa \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-link-token: ' \ --data ' { "mfa_code": "012345" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment, PasswordProviders } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.link.completePasswordProviderMfa({ provider: PasswordProviders.Whoop, mfaCode: "", }); ``` ```python Python theme={null} from junction import Junction, PasswordProviders from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.link.complete_password_provider_mfa( PasswordProviders.WHOOP, mfa_code="", ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.CompletePasswordProviderMfaBody; import com.junction.api.types.PasswordProviders; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.link().completePasswordProviderMfa( PasswordProviders.WHOOP, CompletePasswordProviderMfaBody.builder() .mfaCode("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Link.CompletePasswordProviderMfa(context.TODO(), &junction.CompletePasswordProviderMfaBody{ Provider: junction.PasswordProvidersWhoop, MfaCode: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Create Code Source: https://docs.junction.com/api-reference/link/create-code POST /v2/link/code/create Create or submit link code create via the Junction API. Requires authentication with your team API key. Used for Junction iOS apps to share Apple HealthKit with you. Please refer [here](/wearables/vital-app/introduction) for more information. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/code/create\?user_id\=1875c190-0cd6-46c1-8670-5b56a7794b78 \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.link.codeCreate({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.link.code_create(user_id="") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.CodeCreateLinkRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.link().codeCreate( CodeCreateLinkRequest.builder() .userId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Link.CodeCreate(context.TODO(), &junction.CodeCreateLinkRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Generate a link token Source: https://docs.junction.com/api-reference/link/generate-link-token POST /v2/link/token Create or submit link token via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/token \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-api-key: ' \ --data ' { "user_id": "1875c190-0cd6-46c1-8670-5b56a7794b78" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.link.token({ userId: "", provider: "oura", }); ``` ```python Python theme={null} from junction import Junction, Providers from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.link.token(user_id="", provider=Providers.OURA) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.LinkTokenExchange; import com.junction.api.types.Providers; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.link().token( LinkTokenExchange.builder() .userId("") .provider(Providers.OURA) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) provider := junction.ProvidersOura response, err := c.Link.Token(context.TODO(), &junction.LinkTokenExchange{ UserId: "", Provider: &provider, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Link Demo provider Source: https://docs.junction.com/api-reference/link/link-demo-provider POST /v2/link/connect/demo Create or submit link connect demo via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/connect/demo \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-link-token: ' \ --data ' { "user_id": "1875c190-0cd6-46c1-8670-5b56a7794b78", "provider": "fitbit" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment, DemoProviders } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.link.connectDemoProvider({ userId: "", provider: DemoProviders.AppleHealthKit, }); ``` ```python Python theme={null} from junction import DemoProviders, Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.link.connect_demo_provider( user_id="", provider=DemoProviders.APPLE_HEALTH_KIT, ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.DemoConnectionCreationPayload; import com.junction.api.types.DemoProviders; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.link().connectDemoProvider( DemoConnectionCreationPayload.builder() .userId("") .provider(DemoProviders.APPLE_HEALTH_KIT) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Link.ConnectDemoProvider(context.TODO(), &junction.DemoConnectionCreationPayload{ UserId: "", Provider: junction.DemoProvidersAppleHealthKit, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Link Email provider Source: https://docs.junction.com/api-reference/link/link-email-provider POST /v2/link/provider/email/{provider} Create or submit link provider email via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/provider/email/{provider} \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-link-token: ' \ --data ' { "email": "test@email.com", "region": "us" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const tokenResponse = await client.link.token({ userId: "" }); const data = await client.link.connectEmailAuthProvider({ provider: "freestyle_libre", email: "", vitalLinkToken: tokenResponse.linkToken, }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) token_response = client.link.token(user_id="") data = client.link.connect_email_auth_provider( email="", vital_link_token=token_response.link_token, ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.EmailProviderAuthLink; import com.junction.api.resources.link.requests.LinkTokenExchange; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var tokenResponse = client.link().token( LinkTokenExchange.builder() .userId("") .build() ); var data = client.link().connectEmailAuthProvider( "freestyle_libre", EmailProviderAuthLink.builder() .email("") .vitalLinkToken(tokenResponse.getLinkToken()) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) tokenResponse, err := c.Link.Token(context.TODO(), &junction.LinkTokenExchange{ UserId: "", }) if err != nil { return err } response, err := c.Link.ConnectEmailAuthProvider(context.TODO(), &junction.EmailProviderAuthLink{ Provider: "freestyle_libre", Email: "", VitalLinkToken: &tokenResponse.LinkToken, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Link OAuth provider Source: https://docs.junction.com/api-reference/link/link-oauth-provider GET /v2/link/provider/oauth/{oauth_provider} Retrieve link provider OAuth via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/link/provider/oauth/{oauth_provider} \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-link-token: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment, OAuthProviders } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const tokenResponse = await client.link.token({ userId: "" }); const data = await client.link.generateOauthLink({ oauthProvider: OAuthProviders.Oura, vitalLinkToken: tokenResponse.linkToken, }); ``` ```python Python theme={null} from junction import Junction, OAuthProviders from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) token_response = client.link.token(user_id="") data = client.link.generate_oauth_link( OAuthProviders.OURA, vital_link_token=token_response.link_token, ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.GenerateOauthLinkLinkRequest; import com.junction.api.resources.link.requests.LinkTokenExchange; import com.junction.api.types.OAuthProviders; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var tokenResponse = client.link().token( LinkTokenExchange.builder() .userId("") .build() ); var data = client.link().generateOauthLink( OAuthProviders.OURA, GenerateOauthLinkLinkRequest.builder() .vitalLinkToken(tokenResponse.getLinkToken()) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) tokenResponse, err := c.Link.Token(context.TODO(), &junction.LinkTokenExchange{ UserId: "", }) if err != nil { return err } response, err := c.Link.GenerateOauthLink(context.TODO(), &junction.GenerateOauthLinkLinkRequest{ OauthProvider: junction.OAuthProvidersOura, VitalLinkToken: &tokenResponse.LinkToken, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Link Password provider Source: https://docs.junction.com/api-reference/link/link-password-provider POST /v2/link/provider/password/{provider} Create or submit link provider password via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/link/provider/password/{provider} \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-link-token: ' \ --data ' { "username": "test", "password": "test" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment, PasswordProviders } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.link.connectPasswordProvider({ provider: PasswordProviders.Whoop, username: "", password: "", }); ``` ```python Python theme={null} from junction import Junction, PasswordProviders from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.link.connect_password_provider( PasswordProviders.WHOOP, username="", password="", ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.link.requests.IndividualProviderData; import com.junction.api.types.PasswordProviders; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.link().connectPasswordProvider( PasswordProviders.WHOOP, IndividualProviderData.builder() .username("") .password("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Link.ConnectPasswordProvider(context.TODO(), &junction.IndividualProviderData{ Provider: junction.PasswordProvidersWhoop, Username: "", Password: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # List Bulk Ops Source: https://docs.junction.com/api-reference/link/list-bulk-ops GET /v2/link/bulk_op Retrieve link bulk op via the Junction API. Requires authentication with your team API key. If you are planning to migrate connections, please [chat with us through support channels](/home/getting-support). Link Migration endpoints are disabled by default. # Create Dashboard URL Source: https://docs.junction.com/api-reference/org-management/connect/create-dashboard-url post /v1/org/{org_id}/ehr_integration/create_dashboard_url Create a post-authorization URL that launches Junction Dashboard for a Junction Connect member. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/create_dashboard_url \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456", "integration_team_id": "clinic_123", "modality": "feature_embed", "feature": "order_creation", "environment": "sandbox" }' ``` # Create Integration-Managed Member Source: https://docs.junction.com/api-reference/org-management/connect/create-member post /v1/org/{org_id}/ehr_integration/member Create an integration-managed member that can sign in through Junction Connect launch flows. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456", "name": "Alex Kim", "email": "alex@example.com", "avatar": "https://example.com/avatar.png", "team_role_bindings": [] }' ``` # Delete Integration-Managed Member Source: https://docs.junction.com/api-reference/org-management/connect/delete-member delete /v1/org/{org_id}/ehr_integration/member/{member_id} Remove an integration-managed member from your Junction organization using the EHR integration endpoint. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member/{member_id} \ --header 'X-Management-Key: ' ``` # Get Junction Connect Configuration Source: https://docs.junction.com/api-reference/org-management/connect/get-configuration get /v1/org/{org_id}/ehr_integration/configuration Get the Junction Connect integration configuration for an organization. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/configuration \ --header 'X-Management-Key: ' ``` # Get Integration-Managed Member Source: https://docs.junction.com/api-reference/org-management/connect/get-member get /v1/org/{org_id}/ehr_integration/member/{member_id} Get an integration-managed member by Junction member ID. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member/{member_id} \ --header 'X-Management-Key: ' ``` # Junction Connect Source: https://docs.junction.com/api-reference/org-management/connect/junction-connect Configure and launch Junction Connect sessions through the Management API. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. [Junction Connect](/connect/overview) lets you launch Junction Dashboard experiences from your own web application as either a Link Out or a Feature Embed. See the [Junction Connect Getting Started guide](/connect/getting-started) for the end-to-end integration flow. You configure and launch Junction Connect through the [Management API](/api-details/junction-management-api): * Configure your Junction Connect integration through ["Org Config β†’ Junction Connect"](https://app.junction.com/org/ehr-integration) in the [Junction Dashboard](https://app.junction.com), or programmatically with the [Get Configuration](/api-reference/org-management/connect/get-configuration) and [Set Configuration](/api-reference/org-management/connect/set-configuration) endpoints. * Create and manage integration-managed members with the [Create Member](/api-reference/org-management/connect/create-member), [List Members](/api-reference/org-management/connect/list-members), [Get Member](/api-reference/org-management/connect/get-member), [Resolve Member](/api-reference/org-management/connect/resolve-member), [Update Member](/api-reference/org-management/connect/update-member), and [Delete Member](/api-reference/org-management/connect/delete-member) endpoints. * Launch a session with the [Create Dashboard URL](/api-reference/org-management/connect/create-dashboard-url) endpoint. # List Integration-Managed Members Source: https://docs.junction.com/api-reference/org-management/connect/list-members get /v1/org/{org_id}/ehr_integration/member List integration-managed members for an organization. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member \ --header 'X-Management-Key: ' ``` # Managing Patients Source: https://docs.junction.com/api-reference/org-management/connect/managing-patients Create and manage patients in Junction Connect teams through the Junction API. Patients in Junction Connect teams are Junction users. You manage them through the [Junction API](/api-details/junction-api), using one of its [team-scoped authentication methods](/api-details/junction-api#authentication): * Authenticate with a **Team API Key**. * Authenticate with a **Team API Access Token** created through the [Create Team API Access Token](/api-reference/org-management/team-api-access-token/create-team-api-access-token) endpoint. Common patient-management operations include: * Create a patient with the [Create user](/api-reference/user/create-user) endpoint. * Retrieve a patient with the [Get User](/api-reference/user/get-user) endpoint. * Retrieve patient demographics with the [Get User Demographics](/api-reference/user/get-info-latest) endpoint. * Set patient demographics with the [Update User Demographics](/api-reference/user/upsert-info) endpoint. Use these endpoints to provision patients upfront, then launch the Junction Connect [Order Creation feature](/connect/overview#features) with a preselected patient by using the `order_creation:{user_id}` feature slug. See the [full Core Platform API reference](/api-reference/user/create-user) for all available user-management endpoints. # Managing Teams Source: https://docs.junction.com/api-reference/org-management/connect/managing-teams Create, update, list, and delete teams in your Junction organization through the Management API endpoints. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. Junction Connect works with any team in your organization. You manage teams through the [Management API](/api-details/junction-management-api): * Create a team with the [Create Team](/api-reference/org-management/team/create-team) endpoint. * Update settings of a team with the [Update Team](/api-reference/org-management/team/update-team) endpoint. * Get current settings of a team with the [Get Team](/api-reference/org-management/team/get-team) endpoint. * Get current settings of a team by the *integration team ID* with the [Resolve Team](/api-reference/org-management/team/resolve-team) endpoint. * Delete a team with the [Delete Team](/api-reference/org-management/team/delete-team) endpoint. * List all your teams with the [List Teams](/api-reference/org-management/team/list-teams) endpoint. # Resolve Integration-Managed Member Source: https://docs.junction.com/api-reference/org-management/connect/resolve-member post /v1/org/{org_id}/ehr_integration/resolve_member Get an integration-managed member by your integration member reference. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/resolve_member \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456" }' ``` # Set Junction Connect Configuration Source: https://docs.junction.com/api-reference/org-management/connect/set-configuration put /v1/org/{org_id}/ehr_integration/configuration Create or update the Junction Connect integration configuration for an organization. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request PUT \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/configuration \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "slug": "my-clinical-practice", "modalities": ["feature_embed", "link_out"], "origin_configs": [ { "origin": "https://app.example.com", "session_continuation_url": "https://app.example.com/junction/session-continuation" } ] }' ``` # Update Integration-Managed Member Source: https://docs.junction.com/api-reference/org-management/connect/update-member patch /v1/org/{org_id}/ehr_integration/member/{member_id} Update profile attributes and team role bindings for an integration-managed member. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request PATCH \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member/{member_id} \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "name": "Alex Kim", "email": "alex@example.com", "team_role_bindings": [] }' ``` # Using Junction API Source: https://docs.junction.com/api-reference/org-management/connect/using-junction-api Use the Junction API to manage patients and access Junction's team-scoped platform capabilities. Use the [Junction API](/api-details/junction-api) alongside Junction Connect to work with patient and clinical data in a team. To create, retrieve, and update patients and their demographics, see [Managing Patients](/api-reference/org-management/connect/managing-patients). Authenticate Junction API requests using one of its [team-scoped authentication methods](/api-details/junction-api#authentication): * Authenticate with a **Team API Key**. * Authenticate with a **Team API Access Token** created through the [Create Team API Access Token](/api-reference/org-management/team-api-access-token/create-team-api-access-token) endpoint. Through the Junction API, you can: * manage users and demographics information in your Team with the [Core API](/api-reference/user/create-user); * manage user connections, pull ingested device data, and inspect connection backfill statuses through the [Devices API](/wearables/connecting-providers/introduction); * order lab tests, manage appointments and pull the results through the [Lab Testing API](/lab/overview/introduction); and * aggregate ingested device data with the [Junction Sense API](/sense/overview). See the [Junction API overview](/api-details/junction-api) for links to each API category, available environments, regional endpoints, and authentication options. # Webhooks and Events Source: https://docs.junction.com/api-reference/org-management/connect/webhooks-and-events Receive Junction events through webhooks or stream them to supported ETL pipeline destinations. Use Junction webhooks and events alongside Junction Connect to react to patient, device, and lab testing updates as they happen. Start with the [Webhooks and Events introduction](/webhooks/introduction), then review the [event structure](/webhooks/event-structure) and [retry policy](/webhooks/retry-policy). The [Event Catalog](/event-catalog) provides schemas and example payloads for every event type. Lab testing examples include: * [Order created](/event-catalog/labtest.order.created) and [order updated](/event-catalog/labtest.order.updated) events. * [Appointment created](/event-catalog/labtest.appointment.created) and [appointment updated](/event-catalog/labtest.appointment.updated) events. * The [critical result](/event-catalog/labtest.result.critical) webhook, emitted when a lab result contains a critical value requiring urgent clinical attention. See [Critical Results](/lab/results/critical-results) for the full workflow. For higher-volume delivery, [ETL Pipelines](/webhooks/etl-pipelines/overview) continuously stream Junction events to supported destinations such as Google Cloud Pub/Sub, RabbitMQ, and Azure Event Hubs. Webhooks and ETL Pipelines use the same event payload schemas. # Create or Resend Invite Source: https://docs.junction.com/api-reference/org-management/invite/create-or-resend-invite post /v1/org/{org_id}/invite Post org invite via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/invite \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "email": "" }' ``` # List Invites Source: https://docs.junction.com/api-reference/org-management/invite/list-invites get /v1/org/{org_id}/invite Get org invite via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/invite \ --header 'X-Vital-Org-Key: ' ``` # Revoke Invite Source: https://docs.junction.com/api-reference/org-management/invite/revoke-invite delete /v1/org/{org_id}/invite/{invite_id} Delete org invite via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/invite/{invite_id} \ --header 'X-Vital-Org-Key: ' ``` # Get Lab Accounts Source: https://docs.junction.com/api-reference/org-management/lab-accounts/get-lab-accounts get /v1/org/{org_id}/lab_account/{env}/{region} Get org lab account via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/lab_account/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Update Lab Account Teams Source: https://docs.junction.com/api-reference/org-management/lab-accounts/update-lab-account-teams patch /v1/org/{org_id}/lab_account/{env}/{region}/{account_id} Patch org lab account via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request PATCH \ --url https://api.management.junction.com/v1/org/{org_id}/lab_account/{env}/{region}/{account_id} \ --header 'X-Vital-Org-Key: ' \ --data '{ "team_id_allowlist": "" }' ``` # Create Management Key Source: https://docs.junction.com/api-reference/org-management/management-keys/create-management-key post /v1/org/{org_id}/management_key Post org management key via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/management_key \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "label": "", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" }' ``` # Delete Management Key Source: https://docs.junction.com/api-reference/org-management/management-keys/delete-management-key delete /v1/org/{org_id}/management_key/{key_id} Delete org management key via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/management_key \ --header 'X-Vital-Org-Key: ' ``` # List Management Keys Source: https://docs.junction.com/api-reference/org-management/management-keys/list-management-keys get /v1/org/{org_id}/management_key Get org management key via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/management_key \ --header 'X-Vital-Org-Key: ' ``` # List Members Source: https://docs.junction.com/api-reference/org-management/member/list-members get /v1/org/{org_id}/member Get org member via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/member \ --header 'X-Vital-Org-Key: ' ``` # Delete Member Source: https://docs.junction.com/api-reference/org-management/member/remove-member delete /v1/org/{org_id}/member/{member_id} Delete org member via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/member/{member_id} \ --header 'X-Vital-Org-Key: ' ``` # Get Org Source: https://docs.junction.com/api-reference/org-management/org/get-org get /v1/org/{org_id} Get org via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id} \ --header 'X-Vital-Org-Key: ' ``` # Patch Org Source: https://docs.junction.com/api-reference/org-management/org/update-org patch /v1/org/{org_id} Patch org via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request PATCH \ --url https://api.management.junction.com/v1/org/{org_id} \ --header 'X-Vital-Org-Key: ' ``` # Create Team API Access Token Source: https://docs.junction.com/api-reference/org-management/team-api-access-token/create-team-api-access-token post /v1/org/{org_id}/team/{team_id}/create_access_token Create a short-lived Junction API access token for a team. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. The access token expires after 10 minutes and acts with Team Admin privileges for the selected team. This endpoint is rate limited to prevent abuse. Cache and reuse the access token when appropriate, or use Team API Keys for long-lived access. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id}/create_access_token \ --header 'X-Management-Key: ' ``` # Create Team API Key Source: https://docs.junction.com/api-reference/org-management/team-api-keys/create-team-api-key post /v1/org/{org_id}/team_api_keys/{env}/{region} Post org team API keys via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team_api_keys/{env}/{region} \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "label": "", "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" }' ``` # Delete Team API Keys Source: https://docs.junction.com/api-reference/org-management/team-api-keys/delete-team-api-keys delete /v1/org/{org_id}/team_api_keys/{env}/{region} Delete org team API keys via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/team_api_keys/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # List Team API Keys Source: https://docs.junction.com/api-reference/org-management/team-api-keys/list-team-api-keys get /v1/org/{org_id}/team_api_keys/{env}/{region} Get org team API keys via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team_api_keys/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Delete Org Team Custom Credentials Source: https://docs.junction.com/api-reference/org-management/team-custom-credentials/delete-team-custom-credentials delete /v1/org/{org_id}/team_custom_credentials/{env}/{region} Delete org team custom credentials via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/team_custom_credentials/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Get Org Team Custom Credentials Source: https://docs.junction.com/api-reference/org-management/team-custom-credentials/get-team-custom-credentials get /v1/org/{org_id}/team_custom_credentials/{env}/{region} Get org team custom credentials via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team_custom_credentials/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Create Org Prepare Team Custom Credentials Source: https://docs.junction.com/api-reference/org-management/team-custom-credentials/prepare-team-custom-credentials POST /v1/org/{org_id}/prepare_team_custom_credentials/{env}/{region} Create or submit org prepare team custom credentials via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/prepare_team_custom_credentials/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Set Team Custom Credentials Source: https://docs.junction.com/api-reference/org-management/team-custom-credentials/upsert-team-custom-credentials post /v1/org/{org_id}/team_custom_credentials/{env}/{region} Post org team custom credentials via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ### OAuth Providers Bring Your Own OAuth (BYOO) is available for [the Grow and Scale plans](https://tryvital.io/pricing). While most credentials are active immediately once set through this endpoint, some credentials may not. Check out the [Bring Your Own OAuth](/wearables/connecting-providers/bring-your-own-oauth/overview#through-the-org-management-api) documentation for more information. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team_custom_credentials/{env}/{region} \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", "provider": "oura", "client_id": "", "client_secret": "", "details": { "fitbit": { "is_hr_enabled": true, "workout_verify_token": "", "sleep_verify_token": "", "body_verify_token": "" } } }' ``` # Delete Team Data Pull Preferences Source: https://docs.junction.com/api-reference/org-management/team-data-pull-preferences/delete-team-data-pull-preferences delete /v1/org/{org_id}/team_data_pull_preferences/{env}/{region} Delete org team data pull preferences via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. Deleting preferences for a provider will revert to the default settings. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/team_data_pull_preferences/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Get Team Data Pull Preferences Source: https://docs.junction.com/api-reference/org-management/team-data-pull-preferences/get-team-data-pull-preferences get /v1/org/{org_id}/team_data_pull_preferences/{env}/{region} Get org team data pull preferences via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team_data_pull_preferences/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` The endpoint will return the default Junction settings if no custom preferences are set. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Post Team Data Pull Preferences Source: https://docs.junction.com/api-reference/org-management/team-data-pull-preferences/upsert-team-data-pull-preferences post /v1/org/{org_id}/team_data_pull_preferences/{env}/{region} Post org team data pull preferences via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team_data_pull_preferences/{env}/{region} \ --header 'X-Vital-Org-Key: ' \ --data '{ "team_ids": [ "" ], "providers": { "oura": { "default": { "historical_days_to_pull": 120 }, "resource_overrides": { "sleep": { "historical_days_to_pull": 180 } } } } }' ``` By setting a higher value, you acknowledge your awareness of *the facts of API life* that: 1. historical pulls may take longer to complete; 2. historical pulls may run into provider rate limiting; and 3. regular data polling may consequentially be delayed as a knock-on effect. Provider rate limiting typically happens at OAuth application level. Therefore, Junction recommends [Bring Your Own OAuth](/wearables/connecting-providers/bring-your-own-oauth/overview) if you want to set an extended historical pull range. This creates a rate limit quota dedicated to your Junction Team, not being shared with other Junction customers. The Team Data Pull Preferences you specified are *advisory*. There are scenarios in which Junction systems may not adhere strictly to your stated preferences. ## Supported Providers | Provider | Default | Configurable | Remarks | | ---------------------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Abbott LibreView](https://www.libreview.com) | 90 days | ❌ | - | | [Fitbit](https://www.fitbit.com/global/uk/home) | 90 days | ⚠️ | Activity and heartrate timeseries data are fixed to 14 days. | | [Garmin](https://www.garmin.com) | 90 days | βœ… | - | | [Google Fit](https://www.google.com/fit/) | 90 days | βœ… | - | | [Oura](https://ouraring.com) | 180 days | βœ… | - | | [Peloton](https://www.onepeloton.com) | 180 days | βœ… | - | | [Strava](https://www.strava.com) | 14 days | βœ… | - | | [Wahoo](https://wahoofitness.com) | 180 days | βœ… | - | | [WHOOP](https://www.whoop.com) | 180 days | βœ… | - | | [Zwift](https://zwift.com) | 270 days | βœ… | - | | [Withings](https://www.withings.com) | 90 days | βœ… | - | | [8Sleep](https://www.eightsleep.com) | 90 days | βœ… | - | | [Apple HealthKit](https://www.apple.com/uk/ios/health/) (SDK) | 30 days | βœ… | - | | [Android Health Connect](https://developer.android.com/health-connect) (SDK) | 30 days | ❌ | Google restricts access to historical data to [30 days before the first successful permission request](https://developer.android.com/health-and-fitness/guides/health-connect/develop/frequently-asked-questions#time-range). | | [Hammerhead](https://www.hammerhead.io) | 30 days | βœ… | - | | [Dexcom](https://www.dexcom.com) | 30 days | βœ… | - | | [Dexcom (G6 And Older)](https://www.dexcom.com) | 1 day | ❌ | - | | [MyFitnessPal](https://www.myfitnesspal.com) | 14 days | βœ… | - | | [Polar](https://www.polar.com/accesslink-api/#polar-accesslink-api) | 28 days | ❌ | Polar only supports historical backfill for Sleep and Sleep Stream resources. | | [Cronometer](https://www.cronometer.com) | 28 days | βœ… | - | The configurable maximum is 365 days at this time. # Delete Team ETL Pipelines Source: https://docs.junction.com/api-reference/org-management/team-etl-pipeline/delete-team-etl-pipelines delete /v1/org/{org_id}/team_etl_pipelines/{env}/{region} Delete org team ETL pipelines via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/team_etl_pipelines/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Get Team ETL Pipelines Source: https://docs.junction.com/api-reference/org-management/team-etl-pipeline/get-team-etl-pipelines get /v1/org/{org_id}/team_etl_pipelines/{env}/{region} Get org team ETL pipelines via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team_etl_pipelines/{env}/{region} \ --header 'X-Vital-Org-Key: ' ``` # Set Team ETL Pipelines Source: https://docs.junction.com/api-reference/org-management/team-etl-pipeline/upsert-team-etl-pipelines post /v1/org/{org_id}/team_etl_pipelines/{env}/{region} Post org team ETL pipelines via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team_etl_pipelines/{env}/{region} \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "team_ids": [ "3c90c3cc-0d44-4b50-8888-8dd25736052a" ], "push_historical_data": true, "provider_raw_data": true, "preferences": { "preferred": "cloud_pubsub", "enabled": [ "cloud_pubsub" ] }, "cloud_pubsub": { "project": "", "topic": "", "message_ordering": true }, "rabbitmq": { "uri": "", "exchange": "" }, "svix": { "regional": true }, "event_type_prefixes": [ "" ] }' ``` # Get Team Scope Requirements Source: https://docs.junction.com/api-reference/org-management/team-scope-requirements/get-team-scope-requirements get /v1/org/{org_id}/team/{team_id}/scope_requirements Get org team scope requirements via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id}/scope_requirements \ --header 'X-Vital-Org-Key: ' ``` # Set Team Scope Requirements Source: https://docs.junction.com/api-reference/org-management/team-scope-requirements/upsert-team-scope-requirements post /v1/org/{org_id}/team/{team_id}/scope_requirements Post org team scope requirements via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id}/scope_requirements \ --header 'Content-Type: application/json' \ --header 'X-Vital-Org-Key: ' \ --data '{ "fitbit": null, "oura": { "user_must_grant": ["daily"], "user_may_grant": ["workout"] } }' ``` # Create Webhook Source: https://docs.junction.com/api-reference/org-management/team-webhook/create post /v1/org/{org_id}/team/{team_id}/{environment}/webhook Post org team webhook via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Delete Webhook Source: https://docs.junction.com/api-reference/org-management/team-webhook/delete delete /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id} Delete org team webhook via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Get Webhook Source: https://docs.junction.com/api-reference/org-management/team-webhook/get get /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id} Get org team webhook via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Get Webhook Headers Source: https://docs.junction.com/api-reference/org-management/team-webhook/get-headers get /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id}/headers Get org team webhook headers via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Get Webhook Secret Source: https://docs.junction.com/api-reference/org-management/team-webhook/get-secret get /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id}/secret Get org team webhook secret via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # List Webhooks Source: https://docs.junction.com/api-reference/org-management/team-webhook/list get /v1/org/{org_id}/team/{team_id}/{environment}/webhook Get org team webhook via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Patch Webhook Source: https://docs.junction.com/api-reference/org-management/team-webhook/patch patch /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id} Patch org team webhook via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Rotate Webhook Secret Source: https://docs.junction.com/api-reference/org-management/team-webhook/rotate-secret post /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id}/secret/rotate Post org team webhook secret rotate via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Update Webhook Headers Source: https://docs.junction.com/api-reference/org-management/team-webhook/update-headers put /v1/org/{org_id}/team/{team_id}/{environment}/webhook/{webhook_id}/headers Put org team webhook headers via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Create Team Source: https://docs.junction.com/api-reference/org-management/team/create-team post /v1/org/{org_id}/team Create an organization team. Junction Connect integrations can provide an integration team reference. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "name": "", "region": "us", "integration_team_id": "", "lab_tests_patient_sms_communication_enabled": true, "lab_tests_patient_email_communication_enabled": true }' ``` # Delete Team Source: https://docs.junction.com/api-reference/org-management/team/delete-team delete /v1/org/{org_id}/team/{team_id} Delete org team via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request DELETE \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id} \ --header 'X-Vital-Org-Key: ' ``` # Get Team Source: https://docs.junction.com/api-reference/org-management/team/get-team get /v1/org/{org_id}/team/{team_id} Get org team via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id} \ --header 'X-Vital-Org-Key: ' ``` # List Teams Source: https://docs.junction.com/api-reference/org-management/team/list-teams get /v1/org/{org_id}/team Get org team via the Junction API. Requires authentication with your team API key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request GET \ --url https://api.management.junction.com/v1/org/{org_id}/team \ --header 'X-Vital-Org-Key: ' ``` # Resolve Team Source: https://docs.junction.com/api-reference/org-management/team/resolve-team post /v1/org/{org_id}/resolve_team Look up a Junction team by your own integration team reference and retrieve its current settings. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/resolve_team \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_team_id": "clinic_123" }' ``` # Update Team Source: https://docs.junction.com/api-reference/org-management/team/update-team patch /v1/org/{org_id}/team/{team_id} Update an organization team. Junction Connect integrations can update the integration team reference. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. ```bash cURL theme={null} curl --request PATCH \ --url https://api.management.junction.com/v1/org/{org_id}/team/{team_id} \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "name": "", "integration_team_id": "", "sandbox": { "lab_tests_patient_sms_communication_enabled": true, "lab_tests_patient_email_communication_enabled": true }, "production": { "lab_tests_patient_sms_communication_enabled": true, "lab_tests_patient_email_communication_enabled": true } }' ``` # List of Providers Source: https://docs.junction.com/api-reference/providers GET /v2/providers Retrieve providers via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/providers/ \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.providers.getAll(); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.providers.get_all() ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.providers().getAll(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Providers.GetAll(context.TODO(), nil) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Create a Continuous Query Source: https://docs.junction.com/api-reference/sense/continuous-query/create post /v1/org/{org_id}/team/{team_id}/{environment}/continuous_query Post org team continuous query via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Get User Result Table Source: https://docs.junction.com/api-reference/sense/continuous-query/get-result-table get /aggregate/v1/user/{user_id}/continuous_query/{query_id_or_slug}/result_table Get aggregate user continuous query result table via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. # Get Continuous Query Task History Source: https://docs.junction.com/api-reference/sense/continuous-query/get-task-history get /aggregate/v1/user/{user_id}/continuous_query/{query_id_or_slug}/task_history Get aggregate user continuous query task history via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. # List all Continuous Queries Source: https://docs.junction.com/api-reference/sense/continuous-query/list get /v1/org/{org_id}/team/{team_id}/{environment}/continuous_query Get org team continuous queries via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Update a Continuous Query Source: https://docs.junction.com/api-reference/sense/continuous-query/update patch /v1/org/{org_id}/team/{team_id}/{environment}/continuous_query/{query_id} Patch org team continuous query via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). The base URL of this endpoint is `https://api.management.junction.com/`. The endpoint accepts only [Management Key](/api-details/junction-management-api#authentication) (`X-Management-Key`). Team API Key is not accepted. # Query a single user Source: https://docs.junction.com/api-reference/sense/query-one post /aggregate/v1/user/{user_id}/query Post aggregate user query via the Junction API. Requires authentication with your team API key. Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. JSON is the default output format. Each query instruction outputs one entry containing a dataframe to the `$.results` array, in the declaration order of the query instructions. ```json theme={null} { "results": [ { "table": { "index": [...], "min": [...], "max": [...], "mean": [...], "newest": [...] } } ] } ``` Specify `Accept: application/vnd.vital.tar+gzip+parquet` in your request header. The response body is a gzipped Tarball of multiple Parquet files, namely `0.parquet`, `1.parquet`, `2.parquet`, etc. The numbering corresponds to the declaration order of the query instructions. # Create user insurance Source: https://docs.junction.com/api-reference/user/create-insurance-beta POST /v2/user/{user_id}/insurance Create or submit user insurance via the Junction API. Requires authentication with your team API key. If insurance is covered by Medicare or Medicaid, we have closed beta support for inferring the plan to use based on a patient's address. This endpoint supports `payor_code`s with values of `MEDFED` (Medicare) and `MAIDFED` (Medicaid) to do this. For example, supplying a `payor_code` of `MEDFED` for a patient that lives in Arizona will create insurance data using Arizona's Medicare plan payor code. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/{user_id}/insurance \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data ' { "payor_code": "UNITE", "member_id": "test", "group_id": "123", "relationship": "Self", "insured": { "first_name": "John", "last_name": "Doe", "email": "john@email.com", "phone_number": "+1123123123", "gender": "Male", "dob": "1999-01-01", "address": { "first_line": "Some Street", "second_line": null, "zip": "85004", "state": "AZ", "city": "Phoenix", "country": "US" } } } ' ``` # Create Portal URL Source: https://docs.junction.com/api-reference/user/create-portal-url POST /v2/user/{user_id}/create_portal_url Create a Portal URL for a user via the Junction API. Requires authentication with your team API key. Interested in this feature? Get in touch with your Customer Success Manager. Create a URL to Junction User Portal pre-authorized to a particular User. Junction User Portal requires that demographics have been specified for the User: * Use the [Get User Demographics](/api-reference/user/get-info-latest) endpoint to review currently set demographics; * Use the [Update User Demographics](/api-reference/user/upsert-info) endpoint to update the user's demographics. If you attempt to create a Portal URL for a user without demographics, you will get a **422 Unprocessable Entity** response. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/{{USER_ID}}/create_portal_url \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data '{"context":"launch"}' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.createPortalUrl({ userId: "", context: "launch", }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment from junction.user import CreateUserPortalUrlBodyContext client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.create_portal_url( "", context=CreateUserPortalUrlBodyContext.LAUNCH, ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.CreateUserPortalUrlBody; import com.junction.api.resources.user.types.CreateUserPortalUrlBodyContext; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().createPortalUrl( "", CreateUserPortalUrlBody.builder() .context(CreateUserPortalUrlBodyContext.LAUNCH) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.CreatePortalUrl(context.TODO(), &junction.CreateUserPortalUrlBody{ UserId: "", Context: junction.CreateUserPortalUrlBodyContextLaunch, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Create Sign-In Token Source: https://docs.junction.com/api-reference/user/create-sign-in-token POST /v2/user/{user_id}/sign_in_token Create or submit user sign in token via the Junction API. Requires authentication with your team API key. Create a [Junction Sign-In Token](/wearables/sdks/authentication#junction-sign-in-token) for your mobile apps to sign in with [Junction Mobile SDKs](/wearables/sdks/authentication). Avoid requesting Junction Sign-In Token every time your mobile app relaunches. Your mobile app only needs to sign in once with the Junction Mobile SDK. A signed-in session is persistent on device. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/{{USER_ID}}/sign_in_token \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getUserSignInToken({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_user_sign_in_token("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getUserSignInToken(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetUserSignInToken(context.TODO(), &junction.GetUserSignInTokenUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Create user Source: https://docs.junction.com/api-reference/user/create-user POST /v2/user Create or submit user via the Junction API. Requires authentication with your team API key. When the supplied `client_user_id` conflicts with an existing user, the 400 Bad Request error response includes the Junction User ID (`user_id`) and the creation date (`created_on`) of the conflicting user. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/ \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data ' { "client_user_id": "your_unique_id" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.create({ clientUserId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.create(client_user_id="") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.UserCreateBody; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().create( UserCreateBody.builder() .clientUserId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Create(context.TODO(), &junction.UserCreateBody{ ClientUserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Delete user Source: https://docs.junction.com/api-reference/user/delete-user DELETE /v2/user/{user_id} Remove user via the Junction API. Requires authentication with your team API key. Deleting a user would also [deregister all their provider connections](/api-reference/user/deregister-a-provider) immediately. Junction erases the user data after a 7-day grace period. If you wish to undo a user deletion for any reason, you can undo the deletion through the [Undo User Deletion](/api-reference/user/undo-delete-user) API. Note that undoing would not restore any provider connections. ```bash cURL theme={null} curl --request DELETE \ --url {{BASE_URL}}/v2/user/{user_id} \ --header 'x-vital-api-key: ' \ --header 'Accept: application/json' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.delete({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.delete("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().delete(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Delete(context.TODO(), &junction.DeleteUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Deregister Connection Source: https://docs.junction.com/api-reference/user/deregister-a-provider DELETE /v2/user/{user_id}/{provider} Deregister a provider connection via the Junction API. Requires authentication with your team API key. Deregistration has well-defined behavior only on [cloud-based providers](/wearables/providers/introduction#cloud-based-providers). If your Junction Health SDK uses [the default Auto Connect mode](/wearables/sdks/health/connection-policies#auto-connect-mode-default), deregistering an Apple HealthKit, Health Connect or Samsung Health connection has no effect. For explicit connection and disconnection of Apple HealthKit, Health Connect and Samsung Health connections, see the [opt-in Explicit Connect mode](/wearables/sdks/health/connection-policies#explicit-connect-mode). You can also pause [Health SDK data sync](/wearables/sdks/health/overview#pausing-data-synchronization) client-side, or [sign-out the user](/wearables/sdks/vital-core#reset-the-sdk-sign-out) from the SDK. ```bash cURL theme={null} curl --request DELETE \ --url {{BASE_URL}}/v2/user/{user_id}/{provider} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.deregisterProvider({ userId: "", provider: "oura", }); ``` ```python Python theme={null} from junction import Junction, Providers from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.deregister_provider("", Providers.OURA) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.types.Providers; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().deregisterProvider("", Providers.OURA); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.DeregisterProvider(context.TODO(), &junction.DeregisterProviderUserRequest{ UserId: "", Provider: junction.ProvidersOura, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get User Demographics Source: https://docs.junction.com/api-reference/user/get-info-latest GET /v2/user/{user_id}/info/latest Retrieve user info latest via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/{user_id}/info/latest \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getLatestUserInfo({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_latest_user_info("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getLatestUserInfo(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetLatestUserInfo(context.TODO(), &junction.GetLatestUserInfoUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "first_name": "John", "last_name": "Doe", "email": "john@email.com", "phone_number":"+1123123123", "gender": "Male", "dob": "1999-01-01", "address": { "first_line": "Some Street", "second_line": null, "zip_code": "85004", "state": "AZ", "city": "Phoenix" } } ``` # Get latest insurance Source: https://docs.junction.com/api-reference/user/get-latest-insurance GET /v2/user/{user_id}/insurance/latest Retrieve user insurance latest via the Junction API. Requires authentication with your team API key. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/{user_id}/insurance/latest \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ ``` ```json Response theme={null} { "payor_code": "UNITE", "member_id": "test", "group_id": "123", "relationship": "Self", "insured": { "first_name": "John", "last_name": "Doe", "email": "john@email.com", "phone_number":"+1123123123", "gender": "Male", "dob": "1999-01-01", "address": { "first_line": "Some Street", "second_line": null, "zip_code": "85004", "state": "AZ", "city": "Phoenix" } } } ``` # Get User Source: https://docs.junction.com/api-reference/user/get-user GET /v2/user/{user_id} Retrieve user via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/{user_id} \ --header 'x-vital-api-key: ' \ --header 'Accept: application/json' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.get({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().get(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Get(context.TODO(), &junction.GetUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get users Source: https://docs.junction.com/api-reference/user/get-users GET /v2/user Retrieve users via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/ \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getAll(); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_all() ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getAll(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetAll(context.TODO(), nil) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get User Connections Source: https://docs.junction.com/api-reference/user/get-users-connected-providers GET /v2/user/providers/{user_id} Retrieve user providers via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/providers/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getConnectedProviders({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_connected_providers("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getConnectedProviders(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetConnectedProviders(context.TODO(), &junction.GetConnectedProvidersUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "providers": [ { "name": "Fitbit", "slug": "fitbit", "logo": "https://example.com/fitbit.png", "status": "connected", "created_on": "2010-01-23T12:34:56+00:00", "resource_availability": { "body": { "status": "available", "scope_requirements": { "user_granted": { "required": [ "weight" ], "optional": [] }, "user_denied": { "required": [], "optional": [] } } }, "sleep": { "status": "unavailable", "scope_requirements": { "user_granted": { "required": [], "optional": [] }, "user_denied": { "required": [ "sleep" ], "optional": [ "heartrate", "oxygen_saturation", "respiratory_rate" ] } } } }, "error_details": null } ] } ``` # Update user Source: https://docs.junction.com/api-reference/user/patch-user PATCH /v2/user/{user_id} Partially update user via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request PATCH \ --url {{BASE_URL}}/v2/user/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data ' { "fallback_time_zone": "Europe/London", "fallback_birth_date": "1980-03-13" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.patch({ userId: "", fallbackTimeZone: "Europe/London", fallbackBirthDate: "1980-03-13", }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.user.patch( "", fallback_time_zone="Europe/London", fallback_birth_date="1980-03-13", ) ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.UserPatchBody; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); client.user().patch( "", UserPatchBody.builder() .fallbackTimeZone("Europe/London") .fallbackBirthDate("1980-03-13") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) fallbackTimeZone := "Europe/London" fallbackBirthDate := "1980-03-13" err := c.User.Patch(context.TODO(), &junction.UserPatchBody{ UserId: "", FallbackTimeZone: &fallbackTimeZone, FallbackBirthDate: &fallbackBirthDate, }) if err != nil { return err } ``` # Refresh User Data Source: https://docs.junction.com/api-reference/user/refresh-user-data POST /v2/user/refresh/{user_id} Create or submit user refresh via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/refresh/{user_id} \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.refresh({ userId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.refresh("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().refresh(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Refresh(context.TODO(), &junction.RefreshUserRequest{ UserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Get User by Client User ID Source: https://docs.junction.com/api-reference/user/resolve-user GET /v2/user/resolve/{client_user_id} Retrieve user resolve via the Junction API. Requires authentication with your team API key. ```bash cURL theme={null} curl --request GET \ --url {{BASE_URL}}/v2/user/resolve/{client_user_id} \ --header 'x-vital-api-key: ' \ --header 'Accept: application/json' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.getByClientUserId({ clientUserId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.get_by_client_user_id("") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().getByClientUserId(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.GetByClientUserId(context.TODO(), &junction.GetByClientUserIdUserRequest{ ClientUserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Undo User Deletion Source: https://docs.junction.com/api-reference/user/undo-delete-user POST /v2/user/undo_delete Create or submit user undo delete via the Junction API. Requires authentication with your team API key. You can undo any [user deletion](/api-reference/user/delete-user) that is still in its 7-day grace period. Undoing a deletion does not restore any provider connections. You cannot undo a deletion if you have already [created a new user](/api-reference/user/create-user) using the same `client_user_id`. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/undo_delete \ --header 'x-vital-api-key: ' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data ' { "client_user_id": "8DS6YRVBCSQQ4S0" } ' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.undoDelete({ clientUserId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.undo_delete(client_user_id="") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.UndoDeleteUserRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().undoDelete( UndoDeleteUserRequest.builder() .clientUserId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) clientUserId := "" response, err := c.User.UndoDelete(context.TODO(), &junction.UndoDeleteUserRequest{ ClientUserId: &clientUserId, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` # Update User Demographics Source: https://docs.junction.com/api-reference/user/upsert-info PATCH /v2/user/{user_id}/info Partially update user info via the Junction API. Requires authentication with your team API key. Patient name fields (`first_name`, `last_name`) must follow specific validation rules due to lab restrictions. See [Patient Name Validation](/lab/workflow/order-requirements#patient-name-validation) for complete details. ```bash cURL theme={null} curl --request PATCH \ --url {{BASE_URL}}/v2/user/{user_id}/info \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data ' { "first_name": "John", "last_name": "Doe", "email": "john@email.com", "phone_number":"+1123123123", "gender": "Male", "dob": "1999-01-01", "address": { "first_line": "Some Street", "second_line": null, "zip_code": "85004", "state": "AZ", "city": "Phoenix" } } ' ``` ```json Response theme={null} { "first_name": "John", "last_name": "Doe", "email": "john@email.com", "phone_number":"+1123123123", "gender": "Male", "dob": "1999-01-01", "address": { "first_line": "Some Street", "second_line": null, "zip_code": "85004", "state": "AZ", "city": "Phoenix" } } ``` # API Source: https://docs.junction.com/changelog/core/api Changelog of core Junction API updates including lab test result interpretation, user ingestion bounds, and Sense query improvements. ### Error for closed beta endpoint calls is now JSON (Nov 2025) Previously, if you tried to access an endpoint in closed beta and for which your team was not enabled, it would return a plain text error body. It now returns a JSON error body to align with the rest of our API. ### Lab Test Result Interpretation Filtering (June 2025) You can now filter lab test orders by result interpretation using the new `interpretation` query parameter in the [GET /orders](/api-reference/lab-testing/get-orders) endpoint. The new filtering capability allows you to query orders based on their clinical interpretation: **Query Parameter:** * **`interpretation`** - Filter by result interpretation of the lab test * Type: `enum | null` * Available options: `normal`, `abnormal`, `critical` * Note: This enum is non-exhaustive **Response Enhancement:** Order responses now include a new `interpretation` field providing the clinical assessment of the test results: * **`interpretation`** - Interpretation of the order result * Type: `enum | null` * Available options: `normal`, `abnormal`, `critical` * Note: This enum is non-exhaustive This enhancement enables you to programmatically identify and prioritize critical lab results, improving clinical workflow efficiency and patient care monitoring. Check out the [GET /orders](/api-reference/lab-testing/get-orders) endpoint documentation. ### Webhook Management Endpoints (May 2025) You can now programmatically manage your webhooks via the [Webhooks API](/api-reference/org-management/team-webhook/list). The new endpoints allow you to: * **CRUD** (create/read/update/delete) your webhooks * Manage webhook **headers** * Update webhook **secrets** Org Management API is available for [the Scale plan](https://tryvital.io/pricing). ### Team Management Keys (May 2025) [Junction Management API](/api-details/junction-management-api) now supports Management Keys (previously *Org Keys*) that are scoped to one or more Teams. As a recap, there are now two types of Management Keys: | Type | Remarks | | ------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | Org Management Key | Full control of the organization β€” notably can create or delete Teams. | | Team Management Key | Scoped control over one or more Teams. But it cannot access Org-level resources or actions, e.g., creating or deleting Teams. | All Management Keys β€” Org or Team β€” are accepted by the `X-Management-Key` header, as well as the deprecated `X-Vital-Org-Key` header. Selected customers can now manage Management Keys in the [Junction Dashboard](https://app.junction.com/) through: | Type | Remarks | | ------------------- | -------------------------------------------------------------------------- | | Org Management Key | The **Org Config** page; accessible via the top-left corner Dropdown Menu. | | Team Management Key | The **Team Config** page. | Check out: * the [Create Management Key](/api-reference/org-management/management-keys/create-management-key) endpoint documentation; * the [List Management Keys](/api-reference/org-management/management-keys/list-management-keys) endpoint documentation; and * the [Delete Management Key](/api-reference/org-management/management-keys/delete-management-key) endpoint documentation. If you intend to create a Team Management Key that binds to 2 or more Teams, you must use the [Create Management Key](/api-reference/org-management/management-keys/create-management-key) API endpoint. Junction Dashboard does not support creating a key for more than one Team. Note that Management Keys cannot be used as Team API Keys to access the Junction API. However, you can [manage Team API Keys](/api-reference/org-management/team-api-keys/create-team-api-key) through a Management Key. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). ### `X-Management-Key` header for Junction Management API (April 2025) [Junction Management API](/api-details/junction-management-api) now accepts Management Keys (previously *Org Keys*) in the `X-Management-Key` header, in addition to the `X-Vital-Org-Key` header. We will continue to support the `X-Vital-Org-Key` header, though we recommend moving over to `X-Management-Key` to avoid confusion, especially if you do plan to adopt Team Management Keys. [Junction Management API](/api-details/junction-management-api) is available for [the Scale plan](https://tryvital.io/pricing). ### Enhanced Historical Data Pull Status Tracking (May 2025) We've added a new "Retrying" state to the Historical Pull Status page and the historical introspection endpoint, helping you distinguish temporary issues from permanent failures. Additionally, failed historical pulls now include extra error information, making troubleshooting easier and more efficient. This applies to connections established after May 9th. ### Prepare Team Custom Credentials endpoint (Aug 2024) The new [Prepare Team Custom Credentials](/api-reference/org-management/team-custom-credentials/prepare-team-custom-credentials) endpoint provides instructions for preparation of [Bring Your Own OAuth](/wearables/connecting-providers/bring-your-own-oauth/overview) custom credentials. You can use the information to configure things like OAuth callback URI and the Webhook URI (if applicable), before activating it on your Junction Team through the [Set Team Custom Credential](/api-reference/org-management/team-custom-credentials/upsert-team-custom-credentials) endpoint. Org Management API is available for [the Scale plan](https://tryvital.io/pricing). ### Azure Event Hub: Flexible routing (Aug 2024) You can now configure your [Azure Event Hub destination in ETL Pipelines](/webhooks/etl-pipelines/azure-event-hubs) to route Junction data events to different Event Hubs based on their event type prefix. Check out the [ETL Pipelines - Azure Event Hub](/webhooks/etl-pipelines/azure-event-hubs#multiple-event-hubs) documentation. ETL Pipelines are available for [the Scale plan](https://tryvital.io/pricing). ### Azure Event Hubs as ETL Pipeline destination (Jun 2024) You can now receive [events](/webhooks/introduction) from Junction directly with your Azure Event Hubs. Check out the [ETL Pipelines](/webhooks/etl-pipelines/azure-event-hubs) documentation. ETL Pipelines are available for [the Scale plan](https://tryvital.io/pricing). ### Manage Team Brand Information (Apr 2024) You can now manage Brand Information of your Junction Teams through the Org Management API. Team Brand Information is used in: 1. the Junction-hosted [Link widget](/wearables/connecting-providers/introduction); 2. all user communications in [Junction Lab Testing](/lab/overview/introduction) sent on your behalf; and 3. the Junction-hosted Appointment Booking page for [Junction Lab Testing](/lab/overview/introduction). Org Management API is available for [the Scale plan](https://tryvital.io/pricing). Check out the [Update Team](/api-reference/org-management/team/update-team) and [Create Team](/api-reference/org-management/team/create-team) endpoint documentation. ### Junction Orgs and Org Management API (Apr 2024) We have introduced Junction Org, a new level that groups all your Junction Teams. Your Junction Teams have been transparently grouped and migrated to the new structure. We introduced this to provide a unified billing and administrative experience for customers having these use cases: 1. multi-region presence; or 2. user organization with diverging team-level configurations. We introduced the Org Management API because customers have asked for programmatic access to dynamically create Junction Teams and manage different aspects of their Junction Teams. Org Management API is available for [the Scale plan](https://tryvital.io/pricing). Check out the [Org Management API](/api-reference/org-management) documentation. ### New webhook event top-level fields (Mar 2024) All events now include Team ID, User ID and Client User ID as top-level fields. We introduced this because this helps reduce a Junction User ID β†’ Client User ID database lookup on your end. Check out the [Webhook Event Structure](/webhooks/event-structure) documentation. #### Before ```json Basic event structure theme={null} { "data": { # ... event specific data }, "event_type": "daily.data.glucose.created", } ``` #### After ```json Basic event structure theme={null} { "data": { # ... event specific data }, "event_type": "daily.data.glucose.created", "user_id": "4a29dbc7-6db3-4c83-bfac-70a20a4be1b2", "client_user_id": "01HW3FSNVCHC3B2QB5N0ZAAAVG", "team_id": "6b74423d-0504-4470-9afb-477252ccf67a" } ``` ### Improved error response for User creation conflicts (Mar 2024) The [Create User](/api-reference/user/create-user) endpoint has improved handling of conflicts in Client User ID. We introduced this because the user creation endpoint being idempotent can help simplify your application logic. When the supplied `client_user_id` conflicts with an existing user, the 400 Bad Request response now includes the Junction User ID (`user_id`) and the creation date (`created_on`) of the conflicting user. Check out the [Create User](/api-reference/user/create-user) endpoint documentation. ### User Undo Deletion (Feb 2024) You can now undo user deletion that is still in the 7-day grace period. Check out the [User Undo Deletion](/api-reference/user/undo-delete-user) endpoint documentation. # Dashboard Source: https://docs.junction.com/changelog/core/dashboard Changelog of Junction Dashboard updates including compendium search, lab account selection, and patient demographics improvements. ### Cross-Compendium Marker Search (Mar 2026) The Dashboard now includes a cross-compendium search tool that lets you search for markers across multiple labs and convert lab tests from one provider to another. ## Search * **Cross-lab search** – Search for markers across Quest, Labcorp, BioReference, and Sonora Quest from a single interface. * **CPT code filtering** – Narrow results by entering one or more CPT codes. * **Related markers** – View alternative canonical test candidates and related markers across labs. * **Match confidence** – Each result shows how it relates to your query (exact match, subset, superset, or overlap) along with a confidence score. ## Convert * **Lab test conversion** – Convert an existing lab test or a list of provider IDs from one lab to another. * **Candidate selection** – Review and select from ranked conversion candidates before creating a new panel. * **Direct panel creation** – Create a new lab test panel directly from your search or conversion results. ### Lab Account Selection in Order Flow (Feb 2026) The order creation flow now includes a lab account selection step. When your team has multiple lab accounts, a new screen lets you choose which account to use before selecting panels. Each account card shows the lab name, provider account ID, geographic coverage, and supported billing types. ## Order Flow Changes * **Lab account selection screen** – Appears after patient selection when your team has 2+ customer lab accounts. If only one account exists, it is auto-selected. * **Filtered panels and markers** – After selecting a lab account, only panels and markers available under that lab are shown. * **Review screen** – The selected lab account is displayed on the order review screen with a dropdown to change it. Switching to a different lab resets the order set and AoE answers; switching within the same lab preserves them. Lab account selection is available in production environments when the feature is enabled for your team. ### Managing Org and Team Management Keys (June 2025) You can now provision and manage Management Keys through the Junction Dashboard: * Org Management Keys, through the new Org Config page. * Team Management Keys, through the Team Config page of a specific team. You can manage Team Management Keys also through the Management API β€” check out the [Create Management Keys](/api-reference/org-management/management-keys/create-management-key) and [List Management Keys](/api-reference/org-management/management-keys/list-management-keys) endpoint documentation. You must be an Org Admin or using an Org Management Key to manage Team Management Keys. Only Org Admins can manage Org Management Keys, and it must be done through the Junction Dashboard. ### Managing Brand Information (June 2025) We have updated the **Branding and Communications** tab (previously *White-Labelling*) in the Team Config page. You can now review and update your Team's brand information through this page. Team Brand Information is used in: 1. All patient communication in [Junction Lab Testing](/lab/overview/introduction) sent on your behalf; 2. the Junction-hosted Appointment Booking page for [Junction Lab Testing](/lab/overview/introduction); and 3. the Junction-hosted [Link Widget](/wearables/connecting-providers/introduction). You can also manage this information programmatically through the Management API β€” check out the [Update Team](/api-reference/org-management/team/update-team) and [Create Team](/api-reference/org-management/team/create-team) endpoint documentation. ### Introducing Team Admin Roles (May 2025) Introducing **Team Admin** roles for the Junction Dashboard users. Choose between organization-wide and team-specific admin privileges when adding members. ## What's New * **Two Permission Levels** – When inviting new members to your organization, you can now choose between **Org Admin** and **Team Admin** roles. * **Team-Specific Access** – **Team Admins** can be granted access to specific teams by providing a list of team IDs during invitation or role modification. ## Role Capabilities ### Org Admin * Full access to all organization resources and teams * Can view and edit roles of all organization members * Complete access to billing information and organization settings ### Team Admin * Access limited to specifically assigned teams * Cannot view or edit roles of other organization members * No access to teams outside their allowed list * Cannot view or modify billing information or other organization-level settings ### Improved Order Search experience (Aug 2024) We have improved the search and filtering capabilities in the Orders page, helping you quickly locate specific orders and information. #### Basic filters Order searching now supports these filtering criteria: * Patient or Recipient (in the case of at-home kits) β€” First or Last name * Patient Email * Patient Date of Birth * in the YYYY-MM-DD format. * e.g., "1988" will filter for all patients born in 1988. * e.g., "1988-03" will filter for all patients born in March of 1988 and "1988-03-07" will filter for all patients born on March 7th, 1988. * User ID * Client User ID * Order ID * Order Status Only one Basic filter can be active at any given time. This is because Basic filters are mutually exclusive with each other. ### Date filters On top of the basic filters, you can now filter by date range based on either: * the Order Creation date * For scheduled tests, the order creation date is considered instead of the scheduled date. * the Order Last Updated date * This allows you to filter orders based on the date at which the order status was last updated. Dates are currently filtered with respect to the UTC timezone. ### Status filters Filter based on the most recent status of the order. Note that some statuses are unique to a collection modality such as Mobile Phlebotomy or Self-Collected Test Kits. You can apply multiple Status filters at the same time. These stack as a logical OR among themselves. ### Order Type filters Filter based on the order type: At-Home Phlebotomy, Walk-In Test, At-Home Test Kit. You can apply multiple Order Type filters at the same time. These stack as a logical OR among themselves. ### Activation Type filters Filter for: 1. Scheduled Orders that would not begin execution until the specified target date; or 2. Current Orders that have been executed and are being fulfilled. ### Improved User Search and Introspection experience (Jun 2024) The Users page in the Junction Dashboard is now a search-first experience with more filtering and sorting options available. You can now also click on specific users to inspect device connection status and the patient details. Find your user by typing their Client User ID or Junction User ID into the search bar. For lab testing users: Name, Email and Phone Number are also supported. Click on a user to reveal the new User Details page: #### The General tab Shows an overview of all patient details and user settings associated with the Junction User ID. #### The Connections tab Provides device connection availability and data ingestion insights of the Junction User. You can also obtain this same information programmatically through the [Introspection API](/api-reference/data/introspection/user-resources). # API Source: https://docs.junction.com/changelog/lab-testing/api Changelog of Junction Lab Testing API updates including custom requisition comments, report parsing, and order management enhancements. ### Unmatched Results API (July 2026) We introduced the Unmatched Results API for reviewing lab results that could not be safely attached to an order automatically. ## New Endpoints * [**GET /v3/unmatched\_result**](/api-reference/lab-testing/unmatched-results/list-unmatched-results) – List lab results that require match review. * [**GET /v3/unmatched\_result/\{raw\_result\_id}**](/api-reference/lab-testing/unmatched-results/get-unmatched-result) – Retrieve an unmatched result and its candidate orders. * [**POST /v3/unmatched\_result/\{raw\_result\_id}/accept**](/api-reference/lab-testing/unmatched-results/accept-unmatched-result) – Accept a proposed match. * [**POST /v3/unmatched\_result/\{raw\_result\_id}/resolve**](/api-reference/lab-testing/unmatched-results/resolve-unmatched-result) – Reject a result or escalate it to Junction's operations team. ## New Webhook Event The `labtest.match_review.created` event notifies your webhook when an unmatched result becomes available for customer review. This feature is currently in closed beta. Contact your Customer Success Manager to enable it. See the [Unmatched Results integration guide](/lab/workflow/unmatched-results) for the complete review workflow. ### Lab account delegation status enforced (May 2026) We will soon be enforcing that at least one physician is supplied on order creation for Labcorp, Quest, and Sonora Quest labs *if your order is configured to use a delegated lab account*. Up until now, even if the order should be delegated, we would allow a fallback to using Junction physicians if a physician wasn't provided in the order. Going forward, non-delegated orders will use Junction physicians, but delegated orders must supply a physician. There will be a grace period to give you time to ensure your integration is always supplying a physician for delegated orders. Details of how to check your delegation status are below. Please contact your customer success manager with any questions. You can view the lab account for a given team using the [team-level Get Lab Accounts endpoint](/api-reference/lab-testing/lab_accounts), or all lab accounts for an org using the [org-level Get Lab Accounts endpoint](/api-reference/org-management/lab-accounts/get-lab-accounts). Each will include the `delegated_flow` for each lab account in the response body. Delegated flow values of either `order_delegated` or `fully_delegated` mean that we expect you to be supplying your own physicians in order requests. This only applies when you're using your own lab account or a Junction subaccount. If you only order with Junction platform accounts, these are non-delegated and orders will continue to use our physicians. Whenever possible, we recommend specifying the lab account ID in requests. Here are some example scenarios. #### You haven't created any client lab accounts and you place a Labcorp order This order will use Junction's Labcorp account and Junction physicians. You don't need to specify the lab account ID or include physicians in the request. #### You are using a non-delegated Junction subaccount and place a Quest order This order will use the Junction subaccount. Please provide the lab account ID. Since the lab account isn't delegated, you don't need to supply physicians in the request. ```json theme={null} { "order" { ... "lab_account_id": "" ... } } ``` #### You are using your own delegated Quest account This order will use your own account. Please provide the lab account ID. Since the lab account is delegated, you must supply physician information in the request. ```json theme={null} { "order" { ... "lab_account_id": "", "physician": { "first_name": "", "last_name": "", "npi": "", } ... } } ``` ### PSC Appointment Scheduling API Improvements (April 2026) We have introduced three opt-in features to the PSC Appointment Scheduling API to help improve the availability and reliability of the end patient experience. You can now: * [Query PSC availability through our minutely-updated cache](/lab/walk-in/psc-appointment-scheduling-opt-ins#availability-cache) to improve your slot searching and selection experience. * [Specify an Idempotency Key](/lab/walk-in/psc-appointment-scheduling-opt-ins#idempotency-key) to ensure that your booking CTA is resilient against any network connectivity issues. * [Adopt the Async Confirmation flow](/lab/walk-in/psc-appointment-scheduling-opt-ins#async-confirmation) to buffer your booking experience from any instability and unavailability of the underlying PSC Provider API. Check out the [PSC Appointment Scheduling: Opt-in Features](/lab/walk-in/psc-appointment-scheduling-opt-ins) for details. ### Status details for order events and top-level `last_event` field (Mar 2026) Each order event in API responses and webhook bodies now has a nullable `status_detail` field. If populated, it will contain more granular information about the status. The latest event for an order is now available on the order body. It holds the same data as the last item in the `events` list. ### Access Notes & Appointment Notes for At-Home Phlebotomy (Mar 2026) You can now provide instructions for phlebotomists through two new optional fields on at-home phlebotomy appointments. ## New Fields * **`access_notes`** (on patient address) – Set at order creation. Provides location access instructions such as gate codes, parking details, or entrance directions. Automatically forwarded to the phlebotomy provider on every booking and reschedule. * **`appointment_notes`** (on appointment) – Set at booking, request, or reschedule time. Provides per-appointment special instructions such as "Please bring photo ID" or "Patient prefers left arm". Can be updated on each reschedule. ## Updated Endpoints * **POST /v3/order** – `patient_address` now accepts an optional `access_notes` field. * **POST /v3/order//phlebotomy/appointment/book** – Request body now accepts an optional `appointment_notes` field. * **POST /v3/order//phlebotomy/appointment/request** – Request body now accepts an optional `appointment_notes` field. * **PATCH /v3/order//phlebotomy/appointment/reschedule** – Request body now accepts an optional `appointment_notes` field. Both fields are returned in the appointment response. See the [At-Home Phlebotomy overview](/lab/at-home-phlebotomy/overview#access-notes-and-appointment-notes) for details. ### Custom Comments on Requisitions (Mar 2026) You can now add clinical comments during order creation that are forwarded to the lab requisition. Comments can also be configured as defaults on a per-lab-account basis. ## How It Works * **Order-level comments** – Provide free-text clinical context (up to 1,000 characters) when creating an order through the Dashboard or the API. * **Lab-account defaults** – Configure default clinical notes on a lab account. These are automatically included on every order placed under that account. * **Merging behavior** – When both order-level and lab-account-level comments are present, they are concatenated on the requisition. ## Supported Labs * Quest * Sonora Quest * Labcorp * BioReference ### Lab Report Parsing API (Feb 2026) Introducing the Lab Report Parsing API – extract structured biomarker data from lab report files and match results to standardized LOINC codes. ## Overview The Lab Report Parsing API enables you to digitize lab results from any source. Upload a PDF, JPEG, or PNG lab report, and Junction extracts structured data with LOINC standardization. ## New Endpoints * **POST /lab\_report/v1/parser/job** – Upload a lab report to create a parsing job * **GET /lab\_report/v1/parser/job/** – Retrieve job status and extracted results ## Key Features * **Multi-format support** – Parse PDF, JPEG, and PNG lab reports up to 10 MB * **LOINC matching** – Extracted biomarkers are matched to standardized LOINC codes for cross-lab comparability * **Human review option** – Flag jobs for manual verification before completion * **Structured output** – Get biomarker name, value, unit, reference range, and interpretation ## Webhook Events * **lab\_report.parsing\_job.created** – Triggered when a new parsing job is submitted * **lab\_report.parsing\_job.updated** – Triggered when a parsing job status changes (completed, failed, pending review) ## Use Cases * **Patient uploads** – Allow patients to submit lab reports from other providers * **Historical data import** – Digitize paper records and legacy PDFs * **Multi-source aggregation** – Combine results from various labs using LOINC standardization This feature is currently in beta. Contact your account manager to enable it. Check out the [Lab Report Parsing documentation](/lab/report-parsing/overview) to get started. ### Lab Account Selection in Ordering Flow (Feb 2026) You can now scope orders to a specific lab account during creation. A new team-level lab accounts endpoint lets you list available accounts, and a new `lab_account_id` parameter on the order creation endpoint lets you specify which account to use. ## New Endpoint * **GET /v3/lab\_test/lab\_account** – List lab accounts accessible to your team. Supports optional `lab_account_id` and `status` query parameters. ## Updated Endpoints * **POST /v3/order/create** – New optional `lab_account_id` parameter to specify which lab account to use. If omitted, the backend resolves the appropriate account automatically. * **POST /v3/order/import** – Now accepts lab accounts in `PENDING` status, enabling order imports while accounts are still being set up. * **GET /v3/lab\_tests/markers** – New optional `lab_slug` query parameter to filter markers by lab. When a lab account is selected, you can use this to retrieve only the markers available under that lab. ## Behavior * When `lab_account_id` is provided, available panels and markers are filtered to those supported by the selected account's lab. * When recreating an order with `update_reason=INCORRECT_LAB`, the backend now resolves a fresh lab account rather than carrying forward the incorrect one. ### Idempotency of Ordering (Sep 2025) We've added idempotency behavior on the order endpoint, to prevent duplicate orders. Check out the [documentation](/lab/overview/idempotency). ### Enhanced Lab Order Management with Result Interpretation Filtering (June 2025) We've enhanced the Orders page with new filtering and visualization capabilities for lab test result interpretations, making it easier to identify and prioritize critical patient results. ## What's New * **Interpretation Filter** – Filter orders by clinical result interpretation using the new "Interpretation" dropdown filter * **Critical Value Indicators** – The orders table now displays visual indicators for orders with critical results * **Enhanced Order Details** – Order detail views now include interpretation badges highlighting critical findings ## Filter Options The new Interpretation filter allows you to quickly locate orders based on their clinical assessment: * **Normal** – Orders with results within normal reference ranges * **Abnormal** – Orders with results outside normal ranges but not critically urgent * **Critical** – Orders with results requiring immediate clinical attention ## Visual Enhancements ### Orders Table * Critical value indicators help you quickly spot high-priority results that need immediate attention * Clear visual distinction between normal, abnormal, and critical interpretations ### Order Details View * Prominent badges display the interpretation status for easy identification * Critical results are highlighted with distinctive styling to ensure they don't go unnoticed You can combine the Interpretation filter with existing filters like Order Status, Date Range, and Order Type for more precise result filtering. This enhancement improves clinical workflow efficiency by enabling healthcare teams to quickly identify and prioritize orders requiring immediate attention. ### Introducing Panel Renaming & Archiving (May 2025) We've added more control to how you manage test panels. Now you can skip the support email and work directly in the Test Catalog to: * Rename panels * Archive outdated or unused panels to keep things clean * View archived panels using the "Status" filter and "unarchive" to make panels active again Existing orders tied to archived panels will remain active and processable. [Full product guide β†’](https://support.tryvital.com/articles/1278554980-managing-lab-panels) ### Problem in Transit Order Statuses (Mar 2025) Testkit orders now support two new statuses representing problems in transit. Refer to the [lab test lifecycle documentation](/lab/workflow/lab-test-lifecycle). We're introducing two new statuses for the `OrderLowLevelStatus` enum (`problem_in_transit_lab` and `problem_in_transit_customer`) and two for the `OrderStatus` enum (`collecting_sample.testkit.problem_in_transit_customer` and `collecting_sample.testkit.problem_in_transit_lab`)β€”and we may make further changes in the future. To ensure future compatibility, we ask that you avoid exhaustive matching on enum values. Code that assumes all current values are exhaustive could break or fail to compile with SDK upgrades. Here's how to verify and ensure you benefit from future enhancements: 1. Look for areas in your code where you take an action based on the values of a Junction-defined enum. For example, you might have Python code like this: ```python Python theme={null} match status: case OrderStatus.TESTKIT_ORDERED: handle_ordered() case OrderStatus.TESTKIT_AWAITING_REGISTRATION: handle_awaiting_registration() # other cases... ``` 2. Check that unknown values in your code paths are handled gracefullyβ€”for example, by using default cases. Logging unknown values can help you stay informed. ```python Python theme={null} match status: # previous cases... case unknown_status: logger.warning(f"Unknown status received: {repr(unknown_status)}") ``` 3. Make sure you're running the latest version of our SDK. 4. You're good to go. Once you've checked the code paths won't break if Junction-defined enums start including new values, no further action is needed. ### Source Marker Identification for Results (Nov 2024) Results now feature the source orderable marker from which they originated. Refer to the [documentation](/lab/results/result-formats). ### PSC Appointment Scheduling API (Oct 2024) Walk-in Phlebotomy orders now allow for appointment booking directly with Junction. Refer to the [documentation](/lab/walk-in/order-lifecycle). ### Phlebotomy Availability API - Start Date Query (Sep 2024) You can now supply a `start_date` to the [Appointment Availability API](/api-reference/lab-testing/at-home-phlebotomy/appointment-availability). The API always responds with 14 days' worth of slots. ### Γ€ La Carte Ordering (Sep 2024) Junction now supports ordering Γ  la carte, as well as a revamped ordering flow. Check out the [Ordering](/lab/workflow/ordering) documentation. ### Partial Results Webhook (Jul 2024) Junction now supports sending webhooks for partial results, on a team-by-team configuration. Check out the [Partial Results Notifications](/lab/workflow/partials) documentation. ### Patient Service Center (PSC) Availability API (Jul 2024) It is now possible to verify lab PSC availability in regard to a zip code, radius or order. Check out the [Patient Service Center](/lab/overview/locations) documentation. ### Create Lab Tests With Provider IDs (Jun 2024) It is now possible to create lab tests using the Laboratory's unique provider ID. This allows payloads to be shared across sandbox and production. Check out the [Create a Lab Test](/lab/workflow/create-test) documentation. ### Ask on Order Entry (AOE) (Jun 2024) You can now order panels with AOE requirements via the API. Check out the [AOE](/lab/workflow/aoe) documentation. # Deprecations Source: https://docs.junction.com/changelog/lab-testing/deprecations Deprecated features in the Junction Lab Testing API, including the lab_test_id field replaced by order_set in order creation. ### `lab_test_id` in the [POST /v3/order](/api-reference/lab-testing/create-order) endpoint. `lab_test_id` is deprecated in favor of the `order_set` field. More information [here](/lab/workflow/ordering). In the `order` payload, remove the usage of `lab_test_id` ```json theme={null} { "lab_test_id": "some_id" # Remove this } ``` In the `order` payload, add the `order_set` object. ```json theme={null} { "order_set": { "lab_test_ids": ["some_id"] } } ``` ### `value` field in the `results` object We are removing the `value` field from the [results object](/api-reference/lab-testing/results/get-results), as it does not accurately capture all possible result values. In turn, we've introduced the `result` field. Parse the `result` field in accordance with the `result_type` field. [More information here](/lab/results/result-formats#resulttype). ### `requisition_form_url` in the `order` object This field is a signed GCP bucket URL, which is only active for 7 days. It will be removed in favor of the [download PDF](/api-reference/lab-testing/requisition-pdf) endpoint. ### `GET /v3/lab_tests` in favor of `GET /v3/lab_test` The deprecation cycle ends on **1 October 2026**. The API endpoint will be removed afterwards. The endpoint `GET /v3/lab_tests` is deprecated in favor of `GET /v3/lab_test`. The new endpoint will return a paginated list of lab tests and supports two new parameters: `lab_test_limit` and `next_cursor`. # API Source: https://docs.junction.com/changelog/wearables/api Changelog of Junction Wearables API updates including Sense readiness scores, WHERE clause support, and derived readiness query tables. ### Junction Sense: ALIGN clause (May 2026) Junction Sense queries now support a new `.align()` clause that fills empty time buckets in your aggregated output with values carried over from neighboring buckets. Use it when you want a contiguous time series from sparse input - for example a daily weight composite from a once-a-week weigh-in. The ALIGN clause supports three carry operators: * **`"carry_forward"`** - fills empty buckets with the most recent prior non-empty value. Use for causal or streaming scenarios where only past data should influence the current value. * **`"carry_backward"`** - fills empty buckets with the next subsequent non-empty value. Use for retrospective analysis where a measurement on day N applies back to days N-1, N-2, etc. * **`"carry_nearest"`** - fills empty buckets with the value from the nearest non-empty bucket in either direction. Ties prefer the past value. Each operator takes a duration argument (`max_age` for forward/backward, `span` for nearest) that caps how far the carry will reach. Buckets beyond the cap remain as explicit nulls in the output. **Example - daily weight trend from sparse weigh-ins:** ```python theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Body.col("weight_kilogram").mean(), ).group_by( va.date_trunc(va.Body.index(), 1, "day"), ).align("carry_forward", max_age=va.period(14, "day")) ``` A user who weighs once a week now produces a row for every day in the spine, with the last known weight carried forward for up to 14 days. Days beyond 14d of the last weigh-in remain as explicit null rows. When you group by additional dimensions like `Source.col("source_provider")`, carry stays within each partition - values do not cross provider boundaries. For the full reference including operator semantics, validation rules, and per-partition behavior, see the [ALIGN clause documentation](/sense/query-dsl/align-clause). ### Junction Sense: Menstrual Cycle resource (April 2026) Junction Sense now supports the `menstrual_cycle` query table, covering cycle-level scalars and the nested daily logs. Check out the updated [Column expressions](/sense/query-dsl/column-expressions#menstrualcycle) reference for the full field mapping. * New query table: `menstrual_cycle`, with scalar columns (`period_start`, `period_end`, `cycle_end`, `is_predicted`, `source_*`) and list-of-struct columns (`menstrual_flow`, `cervical_mucus`, `basal_body_temperature`, `intermenstrual_bleeding`, `contraceptive`, `detected_deviations`, `ovulation_test`, `home_pregnancy_test`, `home_progesterone_test`, `sexual_activity`). * New index expression: `{ "index": "menstrual_cycle" }` / `MenstrualCycle.index()`. * Aggregate the nested daily logs with the [list-column aggregation](/sense/query-dsl/list-column-aggregation) Example β€” period end, cycle end, and mean basal body temperature, one row per cycle: ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.MenstrualCycle.col("period_end").newest(), va.MenstrualCycle.col("cycle_end").newest(), va.MenstrualCycle.col("basal_body_temperature") .unnest_and_select(lambda col: col.field("value").mean()) .mean(), ).group_by( va.date_trunc(va.MenstrualCycle.index(), 1, "day") ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "func": "newest", "arg": { "menstrual_cycle": "period_end" } }, { "func": "newest", "arg": { "menstrual_cycle": "cycle_end" } }, { "func": "mean", "arg": { "select": { "func": "mean", "arg": { "field_for": "menstrual_cycle", "basal_body_temperature": "value" } }, "from": { "unnest": { "menstrual_cycle": "basal_body_temperature" } } } } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "menstrual_cycle" } } ] } ``` ### Junction Sense: list-column aggregation (April 2026) Junction Sense now supports aggregating the elements of list columns via a scalar-output subquery - for example, counting meaningful flow days per cycle or summing elements of a scalar-element list. Check out [List-column aggregation](/sense/query-dsl/list-column-aggregation) for the full reference. * New select-expression variant for list columns: a scalar-output subquery with `select` / `from` (UNNEST) / optional `where`, producing one scalar per outer row. Wrap the subquery in an outer aggregate (e.g. `.mean()`) to use it inside a GROUP BY. * `arg` in the subquery's `select` has three shapes: `null` (SQL `COUNT(*)`), a struct-field reference (struct-element lists), or `{ "element": true }` (scalar-element lists). * Inside an UNNEST `where` over a scalar-element list (e.g. a list of string tags), the reserved identifier `element` refers to the element value itself. Example β€” count only the meaningful flow entries within each menstrual cycle: ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.MenstrualCycle.index(), va.MenstrualCycle.col("menstrual_flow") .unnest_and_select(lambda col: col.count()) .where("flow != 'none'") ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "index": "menstrual_cycle" }, { "select": { "func": "count", "arg": null }, "from": { "unnest": { "menstrual_cycle": "menstrual_flow" } }, "where": "flow != 'none'" } ] } ``` ### Junction Sense `awakenings` macro (April 2026) Junction Sense now exposes a new Sleep Macro that counts the number of awakenings during a sleep session. Check out [Sleep Analysis](/sense/query-dsl/sleep-analysis) for more details. * `awakenings` counts transitions from a sleeping phase (deep, light, or REM) to an awake phase, computed from sleep cycle hypnogram data. * Use this macro in the Select clause of Junction Sense queries to surface consistent awakening counts across providers. Syntax: ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.Sleep.awakenings() ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "value_macro": "awakenings" } ] } ``` ### Junction Sense Readiness Scores (March 2026) Junction Sense now supports Readiness Scores, a new query table that provides daily readiness insights derived from sleep. Use it to query sleep, recovery, stress and strain scores, their zones, and chronotype without building custom scoring logic. Check out the [Readiness Scores](/sense/query-dsl/readiness-scores) documentation for full details. * New query table: `derived_readiness` * New index expression: `{ "index": "derived_readiness" }` / `DerivedReadiness.index()` * Works with standard Query DSL patterns (`select`, `where`, `group_by`, and aggregations). ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.DerivedReadiness.col("recovery_score").mean(), va.DerivedReadiness.col("strain_score").max(), ).group_by( va.date_trunc(va.DerivedReadiness.index(), 1, "week") ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "func": "mean", "arg": { "derived_readiness": "recovery_score" } }, { "func": "max", "arg": { "derived_readiness": "strain_score" } } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "week" }, "arg": { "index": "derived_readiness" } } ] } ``` ### Junction Sense WHERE clause (September 2025) Junction Sense now accepts a `where` clause so you can filter input rows before aggregation. * Compose SQL-style predicates with `>`, `>=`, `<`, `<=`, `=`, `!=`, `NOT`, `AND`, `OR`, and parentheses grouping. * Filters always run before `group_by` evaluation when both clauses are present. * Check out the [WHERE clause](/sense/query-dsl/where-clause) documentation for more details. ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Sleep.score().mean(), va.Sleep.col("stage_asleep_second").sum(), ).group_by( va.date_trunc(va.Sleep.index(), 1, "day"), va.Sleep.col("state"), ).where( "type = 'long_sleep'" ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "func": "mean", "arg": { "value_macro": "sleep_score" } }, { "func": "sum", "arg": { "sleep": "stage_asleep_second" } } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "sleep" } }, { "sleep": "state" } ], "where": "type = 'long_sleep'" } ``` ### Junction Sense sleep macros (September 2025) Junction Sense now exposes two new Sleep Macros to help you pinpoint when users fall asleep and wake up within a session. Check out [Sleep Analysis](/sense/query-dsl/sleep-analysis) for more details. * `asleep_at` returns the first instant at which the user is considered to be asleep, i.e., session start + sleep latency. * `awake_at` returns the time at which the user has stopped sleeping, sans any brief awakening. Use these macros in the Select clause of Junction Sense queries to surface consistent bedtime and wake-up timestamps across providers. Syntax: ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.Sleep.asleep_at(), va.Sleep.awake_at() ) ``` ```jsonc JSON DSL theme={null} { "select": [ { "value_macro": "asleep_at" }, { "value_macro": "awake_at" } ] } ``` ### Device metadata and source device tracking (August 2025) We have added device tracking with new API endpoints and enhanced data attribution. Eligible data resources now include `source.device_id` when the originating device can be determined, enabling better tracking and device-specific analytics. Check out the [Device ID attribution documentation](/wearables/providers/data-attributions#device-id) on what data resources are eligible for Device ID attributions in this initial release. The new [Get User Devices](/api-reference/data/device/get-devices) and [Get Device Details](/api-reference/data/device/get-device) endpoints allow you to retrieve detailed device information for connected users. We've also added [Provider Device Created](/event-catalog/provider.device.created) and [Provider Device Updated](/event-catalog/provider.device.updated) webhook events to notify you when device information becomes available or changes. ### Detecting password expiration in password-based connections (July 2025) The [Link Password Provider endpoint](/api-reference/link/link-password-provider), the [Get User Connections endpoint](/api-reference/user/get-users-connected-providers) and the [Provider Connection Error events](/event-catalog/provider.connection.error) now report password expiration using the `provider_password_expired` error type. This mainly affects [Abbott LibreView patient-based connections](/wearables/guides/abbott-libreview#abbott-libreview-for-patient-based-connections). ### Introducing Universal Group By Support to Junction Sense (June 2025) Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. Junction Sense can now group and aggregate the data by any [Table Column expression](/sense/query-dsl/column-expressions#table-column-expression) and/or any [Source Column expression](/sense/query-dsl/column-expressions#source-column-expression). This gives you more options on how the data should be dissected β€” not just by calendar units, but now also by Data Source fields and categorical values from the data itself. Check out the [Group By clause](/sense/query-dsl/group-by-clause) documentation. If both the *Provider* and *Source Type* Source Columns are present in the [Group By clause](/sense/query-dsl/group-by-clause), the implicit [Data Prioritization](/sense/data-prioritization) behavior would be disabled. #### Example queries ```python Python DSL theme={null} # Group Summary Data by Week, Provider and Source Type va.select(...).group_by( va.date_trunc(va.Sleep.index(), 1, "week"), va.Source.col("source_provider"), va.Source.col("source_type"), ) # Group Timeseries Data by Day, Provider and Source Type va.select(...).group_by( va.date_trunc(va.Timeseries.index(), 1, "day"), va.Source.col("source_provider"), va.Source.col("source_type"), ) # Group Electrocardiogram Voltage Data by Hour and Lead Type va.select(...).group_by( va.date_trunc(va.Timeseries.index(), 1, "hour"), va.Timeseries.col("electrocardiogram_voltage").field("type"), ) # Group Sleep Breathing Disturbance by Hour and Elevated vs. Not Elevated va.select(...).group_by( va.date_trunc(va.Timeseries.index(), 1, "hour"), va.Timeseries.col("sleep_breathing_disturbance").field("type"), ) ``` ```jsonc JSON DSL theme={null} # Group Summary Data by Week, Provider and Source Type { "group_by": [ { "date_trunc": { "value": 1, "unit": "week" }, "arg": { "index": "sleep" } }, { "source": "source_provider" }, { "source": "source_type" } ] } # Group Timeseries Data by Day, Provider and Source Type { "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "timeseries" } }, { "source": "source_provider" }, { "source": "source_type" } ] } # Group Electrocardiogram Voltage Data by Hour and Lead Type { "group_by": [ { "date_trunc": { "value": 1, "unit": "hour" }, "arg": { "index": "timeseries" } }, { "timeseries": "electrocardiogram_voltage", "field": "type" }, ] } # Group Sleep Breathing Disturbance by Hour and Elevated vs. Not Elevated { "group_by": [ { "date_trunc": { "value": 1, "unit": "hour" }, "arg": { "index": "timeseries" } }, { "timeseries": "sleep_breathing_disturbance", "field": "type" }, ] } ``` ### Introducing Timeseries Data Support to Continuous Query (June 2025) Junction Sense is in **closed beta**. Interested in Junction Sense? Get in touch with your Customer Success Manager. We have expanded Continuous Query to support **timeseries resources** in addition to the previously available summary resources. With a few simple configuration steps, Continuous Query enables you to: 1. Extract aggregations of high‑volume timeseries data collected across all your active user device connections; and 2. Offload this concern to Junction, allowing you to simplify your data pipeline and focus on extracting actionable signals. You can now select timeseries resources in a Query: * For each resource, you can select all specific fields of interest. * You can select multiple timeseries resources simultaneously, even though they are of different types (discrete, interval, or blood pressure). Check out the [Table Column expression](/sense/query-dsl/column-expressions) documentation. #### Examples of Timeseries Table Column expressions ```python Python DSL theme={null} select( # Blood Pressure Timeseries.col("blood_pressure").field("systolic"), Timeseries.col("blood_pressure").field("diastolic"), Timeseries.col("blood_pressure").field("timezone_offset"), # Discrete Samples Timeseries.col("heartrate").field("value"), Timeseries.col("heartrate").field("timezone_offset"), # Interval Samples Timeseries.col("body_temperature_delta").field("value"), Timeseries.col("body_temperature_delta").field("duration"), Timeseries.col("body_temperature_delta").field("sensor_location"), Timeseries.col("body_temperature_delta").field("timezone_offset"), # Workout Interval Samples Timeseries.col("workout_distance").field("value"), Timeseries.col("workout_distance").field("duration"), Timeseries.col("workout_distance").field("sport"), Timeseries.col("workout_distance").field("workout_id"), ) ``` ```jsonc JSON DSL theme={null} [ # Blood Pressure { "timeseries": "blood_pressure", "field": "systolic" }, { "timeseries": "blood_pressure", "field": "diastolic" }, { "timeseries": "blood_pressure", "field": "timezone_offset" }, # Discrete Samples { "timeseries": "heartrate", "field": "value" }, { "timeseries": "heartrate", "field": "timezone_offset" }, { "timeseries": "heartrate", "field": "type" }, # Interval Samples { "timeseries": "body_temperature_delta", "field": "value" }, { "timeseries": "body_temperature_delta", "field": "duration" }, { "timeseries": "body_temperature_delta", "field": "sensor_location" }, { "timeseries": "body_temperature_delta", "field": "timezone_offset" }, # Workout Interval Samples { "timeseries": "workout_distance", "field": "value" }, { "timeseries": "workout_distance", "field": "duration" }, { "timeseries": "workout_distance", "field": "sport" }, { "timeseries": "workout_distance", "field": "workout_id" }, ] ``` ### External User ID of User Connections (April 2025) We now expose the *External User ID* of User Connections in the [Provider Connection Created](/event-catalog/provider.connection.created) event and [Get User Connections](/api-reference/user/get-users-connected-providers) endpoint. The External User ID is the unique user identifier supplied by the provider, e.g., the Fitbit User ID for Fitbit connections. | Connection type | Content | | ----------------------------- | ------------------------------------------------- | | OAuth Providers | User unique identifier; provider-specific formats | | Password Providers | Username | | Email Providers | Email | | Junction Mobile SDK Providers | null (not available at this time) | Check out the [Provider Connection Created](/event-catalog/provider.connection.created) event and [Get User Connections](/api-reference/user/get-users-connected-providers) endpoint documentation. ### Link API Improvements (Jan 2025) We have increased Link Token expiry from 15 minutes to 60 minutes. We have also added an `on_error=redirect` Link Token option, which forces any error scenario to redirect to your specified `redirect_url`, disabling any in-built error handling behavior in the Link Widget. Check out the [Link Error](/wearables/connecting-providers/errors) format and the [Generate a Link Token](/api-reference/link/generate-link-token) endpoint documentation. ### Extendable Historical Date Ranges (Jul 2024) We now offer the ability to set custom historical data ranges for wearables providers, with resource-level granularity. You can now extend the historical pull range for a number of supported providers using the [Org Management API](/api-reference/org-management/team-data-pull-preferences/upsert-team-data-pull-preferences). Org Management API is available for [the Scale plan](https://tryvital.io/pricing). Check out the [Set Data Pull Preferences](/api-reference/org-management/team-data-pull-preferences/upsert-team-data-pull-preferences), [Get Data Pull Preferences](/api-reference/org-management/team-data-pull-preferences/get-team-data-pull-preferences), [Delete Data Pull Preferences](/api-reference/org-management/team-data-pull-preferences/delete-team-data-pull-preferences) endpoint documentation for more details. ### Introspection: Historical Pull Timeline (May 2024) The Historical Pull Introspection endpoint now reports the execution timeline of historical pulls. The timeline tracks when the historical pull was scheduled, started, and eventually ended (success or failure). This improves the visibility around the latency of historical pulls, as well as providing more indicators of an incomplete execution. Check out the [Historical Pull Introspection](/api-reference/data/introspection/historical-pulls) endpoint documentation. ### Team Scope Requirements (Apr 2024) You can now tailor what scopes Junction would request from your Users using the [Org Management API](/api-reference/org-management/team-scope-requirements/upsert-team-scope-requirements). This applies when your user connects to an [OAuth provider](/wearables/connecting-providers/auth_types) which supports scopes. Junction ensures that any new provider connection can be established only when the user has granted all the scopes specified in the `user_must_grant` scope list. The scopes specified as `user_may_grant` would be requested alongside the `user_must_grant` scopes. However, unlike `user_must_grant`, they do not prevent the connection from being established. Org Management API is available for [the Scale plan](https://tryvital.io/pricing). Check out the [Set Team Scope Requirements](/api-reference/org-management/team-scope-requirements/upsert-team-scope-requirements) and [Get Team Scope Requirements](/api-reference/org-management/team-scope-requirements/get-team-scope-requirements) endpoint documentation on how to enable the setting. ### Reject Duplicate Connections (Apr 2024) You can now configure your Junction Team through the [Org Management API](/api-reference/org-management/team/update-team) to reject duplicate wearable connections. When the `reject_duplicate_connection` setting is enabled on the Team, Junction checks whether or not the provider-reported user ID is already connected to an existing User in your Team. If so, the Link API would report the [`duplicate_connection` error](/wearables/connecting-providers/errors). Org Management API is available for [the Scale plan](https://tryvital.io/pricing). Check out the [Update Team](/api-reference/org-management/team/update-team) and [Create Team](/api-reference/org-management/team/create-team) endpoint documentation on how to enable the setting. Check out the [Link Errors](/wearables/connecting-providers/errors) documentation on how to catch the `duplicate_connection` error. ### Link Error reporting (Apr 2024) The Link API now reports errors in terms of a predefined set of [Error Types](/wearables/connecting-providers/errors) on which your application logic can depend. We introduced this because there has not been a dependable way for your application logic to understand why a connection attempt has failed, and in turn this prevents your application from providing actionable messages to your end users. Depending on how you initiate the Link flow, the Link Error would be reported either as a URL query parameter, or as part of the JSON response. Check out the [Link Errors](/wearables/connecting-providers/errors) documentation for the detailed guidance. ### Understanding Resource Availability (Apr 2024) When a user connection to a provider is established, the webhook event now includes a resource availability report of the connection. We introduced this because it helps you understand what resources would and would not be available on a new connection. We also provide insights into how partial consents from users during the OAuth authentication flow can influence the resource availability, so that you can take actions accordingly. This resource availability report is based on the permissions *(also known as API access scopes)* the user has granted during the authentication process. In some cases, a provider resource may be available, but some information could be absent due to some optional scopes having been denied by the user. The availability report includes a full breakdown of granted and denied scopes by their optionality. If the provider has no concept of API access scopes, we report all resources as available. You can also query this information at any time through the [Get User Connections](/api-reference/user/get-users-connected-providers) endpoint. Check out the [Provider Connection Created](/event-catalog/provider.connection.created) (`provider.connection.created`) event schema and the [Get User Connections](/api-reference/user/get-users-connected-providers) endpoint documentation. ### Fallback Birth Date for Heart Rate Zones (Feb 2024) You can now set a Fallback Birth Date on a user. Junction can use this to compute more accurate workout Heart Rate Zones, when the provider exposes neither heart rate zones nor user age to Junction. Check out the [Heart Rate Zones](/wearables/providers/heart-rate-zones#fallback-birth-date) documentation. ### Grouped Timeseries (Feb 2024) You can now get grouped timeseries data. This initial release groups data by [Source Type](/wearables/providers/data-attributions#source-type) from [supported providers](/wearables/providers/data-attributions#supported-providers). Check out the [Blood Oxygen](/api-reference/data/timeseries/blood-oxygen) endpoint documentation for an example. ### Historical Pull Introspection (Dec 2023) You can now introspect the status of all one-off user historical data pulls. It also provides the pulled date-time range, as well as a rough estimate of the amount of data ingested (in terms of "days with data"). Check out the [Historical Pull Introspection](/api-reference/data/introspection/historical-pulls) endpoint documentation. ### User Resources Introspection (Dec 2023) You can now introspect user data ingestion statistics. For example, the endpoint provides: 1. Oldest and newest data timestamp 2. The number of objects sent in `*.created` events 3. The status and time of the last ingestion attempt (polling or push) Check out the [User Resources Introspection](/api-reference/data/introspection/user-resources) endpoint documentation. ### Junction Sign-In Token for Mobile SDKs (Nov 2023) Junction Sign-In Token is a new, user-scoped Authentication scheme for Junction Mobile SDKs. It grants only user-scoped access to your mobile app sign-ins. This allows you to keep your Junction Team API Keys as server-side secrets. We encourage all customers using Junction Team API Keys in their production mobile apps to migrate to the Junction Sign-In Token scheme. Check out the [SDK Authentication](/wearables/sdks/authentication#junction-sign-in-token) guide on how to migrate to this scheme. Check out the [Create Sign-In Token](/api-reference/user/create-sign-in-token) endpoint documentation on how to generate tokens for your mobile app sign-ins. # Deprecations Source: https://docs.junction.com/changelog/wearables/deprecations Deprecated features in the Junction Wearables API, including the hypnogram timeseries type and redefined Source/Provider terminology. ### Non-grouped timeseries endpoints The deprecation cycle ends on **14 September 2026**. The API endpoints will be removed afterwards. We have introduced [Get Grouped Timeseries](/changelog/wearables/api#grouped-timeseries-feb-2024) endpoints since February 2024. Check out the [Get Heartrate](/api-reference/data/timeseries/heartrate) endpoint for an example. It has been supported by all Junction API SDKs (backend), as well as all relevant Junction Mobile SDKs (Native iOS, Native Android, Flutter) since 2024 as well. The [Get Grouped Timeseries](/changelog/wearables/api#grouped-timeseries-feb-2024) endpoints have several advantages: 1. They use cursor-based pagination, allowing you to fetch and process data incrementally. 2. They expose the [data source attributions](/wearables/providers/data-attributions), which are absent from the legacy endpoints. | Category | Status | API endpoint path | API SDKs | | ----------------------- | ------------- | --------------------------------------------- | --------------------------- | | Get Grouped Timeseries | 🟒 Supported | `/v2/timeseries/{user_id}/{resource}/grouped` | `vitals.{resource}_grouped` | | Get Timeseries (Legacy) | ⚠️ Deprecated | `/v2/timeseries/{user_id}/{resource}` | `vitals.{resource}` | For Junction API SDKs, the client methods for the Get Timeseries (Legacy) endpoints have been marked as deprecated since 2024. Make sure you use the latest Junction API SDK releases, and take action on all the deprecations. For relevant Junction Mobile SDKs (Native iOS, Native Android, Flutter), there is no action for you to take assuming you use the latest SDK releases. For direct API calls, make sure your request URL paths include `/grouped`, your logic expects the grouped timeseries response schema, and that you handle pagination. ### The `hypnogram` timeseries type The deprecation cycle ends on ~~31 January 2025~~ **14 September 2026**. The resource will be removed afterwards. We have introduced a new Sleep Cycle summary type (`sleep_cycle`) which captures the detailed hypnogram of a sleep session. It replaces the existing `hypnogram` timeseries type. More details can be found here: [Sleep Cycle Summary](/api-reference/data/sleep-cycle/get-summary) Start processing the new `historical.data.sleep_cycle.created`, `daily.data.sleep_cycle.created` and `daily.data.sleep_cycle.updated` events. Stop processing the `historical.timeseries.hypnogram.created`, `daily.timeseries.hypnogram.created` and `daily.timeseries.hypnogram.updated` events. ### Redefining Source and Provider The deprecation cycle ends on ~~31 July 2024~~ **14 September 2026**. The deprecated fields will be removed afterwards. Junction has redefined what *Source* and *Provider* mean across our API and event schemas: | Entity | Definition | | -------- | ----------------------------------------------------------------------------------------------------- | | Source | The source context of a specific piece of data (summary or timeseries resources). | | Provider | Static metadata of a wearable data provider (an app, a platform, a service, or Junction Mobile SDKs). | A *Source* context comprises: * the Provider (slug only) * the [Source Type](/wearables/providers/data-attributions#source-type) * the [App ID](/wearables/providers/data-attributions#app-id) (*optional*) We also have plans for the *Source* context to include source device metadata where available. A *Provider* object is a short description of a wearable data provider. It comprises the familiar `name`, `logo` and `slug` trio you have been receiving in many data events. To migrate to the new definitions, Junction is announcing the following deprecations: Inside the Source context located at `$.data.source`, the `name`, `logo`, and `slug` fields are now deprecated. Junction no longer embeds these *Provider* object fields in every data event, except for the provider slug. Using the [Steps data event](/event-catalog/daily.data.steps.created) as an illustration, originally the `source` field described the wearable data provider. As part of this redefinition, the `source` field is reappropriated to track the *Source* context of the `steps` timeseries value group. So we have added a few new *Source* context fields, and marked several *Provider* fields as deprecated: ```json daily.data.steps.created (Current) theme={null} { "event_type": "daily.data.steps.created", "data": { "data": [...], "source": { /** 🟒 BEGIN: New source fields **/ "provider": "oura", "type": "ring", "app_id": null, /** 🟒 END: New source fields **/ /** ⚠️ BEGIN: Deprecated provider fields, to be removed **/ "name": "Oura", "slug": "oura", "logo": "https://example.com/oura.svg" /** ⚠️ END: Deprecated provider fields, to be removed **/ } }, "user_id": "fb58770e-8b7b-4416-a5bd-8433786d10dc" } ``` Once the deprecation cycle ends, Junction will remove the deprecated fields: ```json daily.data.steps.created (Future) theme={null} { "event_type": "daily.data.steps.created", "data": { "data": [...], "source": { /** 🟒 BEGIN: New source fields **/ "provider": "oura", "type": "ring", "app_id": null /** 🟒 END: New source fields **/ } }, "user_id": "fb58770e-8b7b-4416-a5bd-8433786d10dc" } ``` Stop parsing `name`, `logo` and `slug` when processing the `$.data.source` field in **all Data Events** (daily.data.\*). If you need the Provider information, you can obtain it through the [Get Providers](/api-reference/providers) endpoint. This applies to: * Get Activity: `GET /v2/summary/activity/*` * Get Body: `GET /v2/summary/body/*` * Get Meal: `GET /v2/summary/meal/*` * Get Profile: `GET /v2/summary/profile/*` * Get Sleep: `GET /v2/summary/sleep/*` * Get Workouts: `GET /v2/summary/workouts/*` Similar to changes to the Data Events, the `name`, `logo`, and `slug` sub-fields under the `source` field in each and every summary are now deprecated. Junction no longer embeds these *Provider* object fields in every summary, except for the provider slug. Using the [Get Profile endpoint](/api-reference/data/profile/get-summary) as an illustration, the `source` object has been reappropriated as the *Source* context of this Profile summary. So we have added a few new *Source* context fields, and marked several *Provider* fields as deprecated: ```json Profile (Current) theme={null} { "id": "eadba0c7-4e81-4d17-962c-9ebe0629c08f", "date": "2022-08-04", "height": 183, "source": { /** 🟒 BEGIN: New source fields **/ "provider": "oura", "type": "app", "app_id": null, /** 🟒 END: New source fields **/ /** ⚠️ BEGIN: Deprecated provider fields, to be removed **/ "name": "Oura", "slug": "oura", "logo": "https://example.com/oura.svg" /** ⚠️ END: Deprecated provider fields, to be removed **/ }, "user_id": "71937dd3-aebe-46b7-ab64-c287bd75b2a6" } ``` Once the deprecation cycle ends, Junction will remove the deprecated fields: ```json Profile (Future) theme={null} { "id": "eadba0c7-4e81-4d17-962c-9ebe0629c08f", "date": "2022-08-04", "height": 183, "source": { /** 🟒 BEGIN: New source fields **/ "provider": "oura", "type": "app", "app_id": null /** 🟒 END: New fields **/ }, "user_id": "71937dd3-aebe-46b7-ab64-c287bd75b2a6" } ``` Stop parsing `name`, `logo` and `slug` fields in **all Get Summary endpoint** responses. If you need the Provider information, you can obtain it through the [Get Providers](/api-reference/providers) endpoint. This applies to: * Provider Connection Created: `provider.connection.created`. Junction has renamed the `source` field in this event to `provider`, aligning with the redefinition of *Source* and *Provider*. To illustrate the change, originally the `source` field described the wearable data provider. As part of this redefinition, `source` no longer applies in this context. Junction has introduced an identical `provider` field as its replacement: ```json provider.connection.created (Current) theme={null} { "event_type": "provider.connection.created", "data": { "user_id": "71937dd3-aebe-46b7-ab64-c287bd75b2a6", "resource_availability": {...}, /** 🟒 BEGIN: New field **/ "provider": { "name": "Oura", "slug": "oura", "logo": "https://logo_url.com" }, /** ⚠️ BEGIN: Deprecated field, to be removed **/ "source": { "name": "Oura", "slug": "oura", "logo": "https://logo_url.com" } /** ⚠️ END: Deprecated field, to be removed **/ } } ``` Once the deprecation cycle ends, Junction will remove the deprecated `source` field: ```json provider.connection.created (Future) theme={null} { "event_type": "provider.connection.created", "data": { "user_id": "71937dd3-aebe-46b7-ab64-c287bd75b2a6", "resource_availability": {...} /** 🟒 BEGIN: New field **/ "provider": { "name": "Oura", "slug": "oura", "logo": "https://logo_url.com" }, /** 🟒 END: New field **/ } } ``` Update your `provider.connection.created` event parsing logic to parse the `provider` field, and stop parsing the `source` field. ### The `is_final` flag in `historical.data.*.created` events The deprecation cycle ends on ~~30 June 2024~~ **14 September 2026**. The deprecated fields will be removed afterwards. We are removing the `is_final` flag from the Historical Pull Completed (`historical.data.*.created`) events. For each resource, Junction now signals one Historical Pull Completed event, only after we have finished fetching all data chunks. This means `is_final` no longer has a meaning, since the event itself is *final*. Stop parsing `is_final` as a required field when processing `historical.data.*.created` events. # Providers and Resources Source: https://docs.junction.com/changelog/wearables/providers Changelog of wearable provider updates including Health SDK Explicit Connect mode, sync progress logs, and provider-specific improvements. ### Strava is BYOO-only (July 2026) New Strava connections and reconnects now require [Bring Your Own OAuth](/wearables/connecting-providers/bring-your-own-oauth/overview) credentials. Junction's default Strava OAuth application is unavailable for new Strava connections. Teams that need Strava should configure their own Strava OAuth application before connecting users. See the [Strava guide](/wearables/guides/strava) for setup details. ### Sleep summary extension: `recovery_readiness_score` (April 2026) The Sleep summary now includes `recovery_readiness_score`, a value between 0 and 100 representing the provider's recovery or readiness proxy. * Currently sourced from Oura readiness score, WHOOP recovery score, and Ultrahuman recovery. * Available as a regular column in Continuous Query: `Sleep.col("recovery_readiness_score")` / `{ "sleep": "recovery_readiness_score" }`. ### Samsung Health via Junction Health SDK (March 2026) Junction Health SDK now supports Samsung Health as an SDK-based connection on Android phones. Samsung Health uses the same Sync On App Launch and opt-in Background Sync model as Health Connect. On Expo and React Native, the Health SDK now accepts an optional `provider` argument throughout the entire API surface. Health Connect remains the default provider, so you must pass `"samsung_health"` explicitly to target Samsung Health. Check out the [Samsung Health guide](/wearables/guides/samsung-health) for the Samsung Health setup requirements and details. Check out the [Junction Health SDK overview](/wearables/sdks/health/overview) for documentation on the shared API surface. This feature is available on Android SDK 5.0.0+ and React Native SDK 6.0.0+. ### Health SDK: Explicit Connect mode (Sep 2025) The Health SDK now supports an opt-in **[Explicit Connect mode](/wearables/sdks/health/connection-policies#explicit-connect-mode)**, which enables your application to explicitly control the moment of Health Connect connection creation and disconnection. The opt-in Explicit Connect mode also allows remote disconnection through the [Deregister Connection](/api-reference/user/deregister-a-provider) endpoint, which was not supported in the default [Auto Connect](/wearables/sdks/health/connection-policies#auto-connect-mode-default) mode. If your device connection management UX is built upon an explicit notion of connecting and disconnecting Apple HealthKit and Health Connect connections β€” as if they are like their cloud-based counterparts β€” you might find the [Explicit Connect](/wearables/sdks/health/connection-policies#explicit-connect-mode) mode more appealing. Check out the [Health SDK Connection Policies](/wearables/sdks/health/connection-policies) documentation for further details. This feature is available on iOS SDK 1.8.0+, Android SDK 4.2.0+, React Native SDK 5.4.0+ and Flutter SDK 4.6.0+. ### Health Connect sync progress logs in Junction Dashboard (Sep 2025) Health Connect integrations using Android SDK 4.2.0 or above now report client-side sync progress regularly to the Junction Dashboard. Similar to the iOS SDK equivalent, this report includes metadata of any exception that had disrupted a sync attempt. We hope that this brings more visibility into Health Connect sync issues. This feature is available on Android SDK 4.2.0+, React Native SDK 5.4.0+ and Flutter SDK 4.6.0+. ### Expanded Apple HealthKit data type coverage (April 2025) Junction iOS SDK 1.6.0 has expanded the HealthKit data type coverage: | Type | Remarks | `VitalResource` | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | | Workout Stream timeseries | Workout Distance β€” including cycling, swimming, rowing, cross-country skiing, downhill snow sports, paddle sports, skating sports, walking, running, and wheelchair.
Workout Swimming Stroke | As part of `Workout` | | Timeseries | Heart Rate Recovery One Minute | `HeartRateRecoveryOneMinute` | Workout Stream timeseries data always have [Workout ID](/wearables/providers/data-attributions#workout-id) and [Sport](/wearables/providers/data-attributions#sport) attributions. For more information, check out: #### Data Events * the [Workout Distance data events](/event-catalog/daily.data.workout_distance.created) in the Event Catalog; * the [Workout Swimming Stroke data events](/event-catalog/daily.data.workout_swimming_stroke.created) in the Event Catalog; * the [Heart Rate Recovery One Minute data events](/event-catalog/daily.data.heart_rate_recovery_one_minute.created) in the Event Catalog; #### Data access API * the [Get Workout Distance](/api-reference/data/timeseries/workout-distance) endpoint documentation; * the [Get Workout Swimming Stroke](/api-reference/data/timeseries/workout-swimming-stroke) endpoint documentation; and * the [Get Heart Rate Recovery One Minute](/api-reference/data/timeseries/heart-rate-recovery-one-minute) endpoint documentation. ### Summary Ingestion Timestamps (April 2025) Activity, Body, Sleep, Sleep Cycle, Workout, Meal and Menstrual Cycle now expose ingestion timestamps: | Field | Remarks | | ------------ | --------------------------------------------------------------------------- | | `created_at` | The time at which Junction first ingested this summary. | | `updated_at` | The time at which Junction ingested the most recent update to this summary. | For more information, check out: #### Data Events * the [Activity data events](/event-catalog/daily.data.activity.created) in the Event Catalog; * the [Body data events](/event-catalog/daily.data.body.created) in the Event Catalog; * the [Sleep data events](/event-catalog/daily.data.sleep.created) in the Event Catalog; * the [Sleep Cycle data events](/event-catalog/daily.data.sleep_cycle.created) in the Event Catalog; * the [Workout data events](/event-catalog/daily.data.workouts.created) in the Event Catalog; * the [Menstrual Cycle data events](/event-catalog/daily.data.menstrual_cycle.created) in the Event Catalog; and * the [Meal data events](/event-catalog/daily.data.meal.created) in the Event Catalog. #### Data access API * the [Get Activity](/api-reference/data/activity/get-summary) endpoint documentation; * the [Get Body](/api-reference/data/body/get-summary) endpoint documentation; * the [Get Sleep](/api-reference/data/sleep/get-summary) endpoint documentation; * the [Get Sleep Cycle](/api-reference/data/sleep-cycle/get-summary) endpoint documentation; * the [Get Workout](/api-reference/data/workouts/get-summary) endpoint documentation; * the [Get Menstrual Cycle](/api-reference/data/menstrual-cycle/get-summary) endpoint documentation; and * the [Get Meal](/api-reference/data/meal/get-summary) endpoint documentation. ### Expanded Apple HealthKit data type coverage (March 2025) Junction iOS SDK 1.5.0 has expanded the HealthKit data type coverage: | Type | Remarks | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Profile summary | Wheelchair Mode usage | | Activity summary | Wheelchair Mode support (distance and push count) | | Body summary | Lean Body Mass, Body Mass Index, Waist Circumference | | Timeseries resources | Lean Body Mass, Body Mass Index, Waist Circumference, Wheelchair Push, Distance (Wheelchair Mode support), Stand Hour, Stand Duration, Sleep Apnea Alert, Sleep Breathing Disturbance, FEV1, Forced Vital Capacity, Peak Expiratory Flow Rate, Inhaler Usage, Fall, UV Exposure, Daylight Exposure, Handwashing, Basal Body Temperature | For more information, check out: #### Data Events * the [Profile data events](/event-catalog/daily.data.profile.created) in the Event Catalog; * the [Activity data events](/event-catalog/daily.data.activity.created) in the Event Catalog; * the [Body data events](/event-catalog/daily.data.body.created) in the Event Catalog; * the [Lean Body Mass data events](/event-catalog/daily.data.lean_body_mass.created) in the Event Catalog; * the [Body Mass Index data events](/event-catalog/daily.data.body_mass_index.created) in the Event Catalog; * the [Waist Circumference data events](/event-catalog/daily.data.waist_circumference.created) in the Event Catalog; * the [Wheelchair Push data events](/event-catalog/daily.data.wheelchair_push.created) in the Event Catalog; * the [Distance data events](/event-catalog/daily.data.distance.created) in the Event Catalog; * the [Stand Hour data events](/event-catalog/daily.data.stand_hour.created) in the Event Catalog; * the [Stand Duration data events](/event-catalog/daily.data.stand_duration.created) in the Event Catalog; * the [Sleep Apnea Alert data events](/event-catalog/daily.data.sleep_apnea_alert.created) in the Event Catalog; * the [Sleep Breathing Disturbance data events](/event-catalog/daily.data.sleep_breathing_disturbance.created) in the Event Catalog; * the [FEV1 data events](/event-catalog/daily.data.forced_expiratory_volume_1.created) in the Event Catalog; * the [Forced Vital Capacity data events](/event-catalog/daily.data.forced_vital_capacity.created) in the Event Catalog; * the [Peak Expiratory Flow Rate data events](/event-catalog/daily.data.peak_expiratory_flow_rate.created) in the Event Catalog; * the [Inhaler Usage data events](/event-catalog/daily.data.inhaler_usage.created) in the Event Catalog; * the [Fall data events](/event-catalog/daily.data.fall.created) in the Event Catalog; * the [UV Exposure data events](/event-catalog/daily.data.uv_exposure.created) in the Event Catalog; * the [Daylight Exposure data events](/event-catalog/daily.data.daylight_exposure.created) in the Event Catalog; * the [Handwashing data events](/event-catalog/daily.data.handwashing.created) in the Event Catalog; and * the [Basal Body Temperature data events](/event-catalog/daily.data.basal_body_temperature.created) in the Event Catalog. #### Data access API * the [Get Profile](/api-reference/data/profile/get-summary) endpoint documentation; * the [Get Activity](/api-reference/data/activity/get-summary) endpoint documentation; * the [Get Body](/api-reference/data/body/get-summary) endpoint documentation; * the [Get Lean Body Mass](/api-reference/data/timeseries/lean-body-mass) endpoint documentation; * the [Get Body Mass Index](/api-reference/data/timeseries/body-mass-index) endpoint documentation; * the [Get Waist Circumference](/api-reference/data/timeseries/waist-circumference) endpoint documentation; * the [Get Wheelchair Push](/api-reference/data/timeseries/wheelchair-push) endpoint documentation; * the [Get Distance](/api-reference/data/timeseries/distance) endpoint documentation; * the [Get Stand Hour](/api-reference/data/timeseries/stand-hour) endpoint documentation; * the [Get Stand Duration](/api-reference/data/timeseries/stand-duration) endpoint documentation; * the [Get Sleep Apnea Alert](/api-reference/data/timeseries/sleep-apnea-alert) endpoint documentation; * the [Get Sleep Breathing Disturbance](/api-reference/data/timeseries/sleep-breathing-disturbance) endpoint documentation; * the [Get FEV1](/api-reference/data/timeseries/forced-expiratory-volume-1) endpoint documentation; * the [Get Forced Vital Capacity](/api-reference/data/timeseries/forced-vital-capacity) endpoint documentation; * the [Get Peak Expiratory Flow Rate](/api-reference/data/timeseries/peak-expiratory-flow-rate) endpoint documentation; * the [Get Inhaler Usage](/api-reference/data/timeseries/inhaler-usage) endpoint documentation; * the [Get Fall](/api-reference/data/timeseries/fall) endpoint documentation; * the [Get UV Exposure](/api-reference/data/timeseries/uv-exposure) endpoint documentation; * the [Get Daylight Exposure](/api-reference/data/timeseries/daylight-exposure) endpoint documentation; * the [Get Handwashing](/api-reference/data/timeseries/handwashing) endpoint documentation; and * the [Get Basal Body Temperature](/api-reference/data/timeseries/basal-body-temperature) endpoint documentation. ### Improved LibreView practice connection process (Jan 2025) You can now connect LibreView patients in [46 regions in the EU environment](/wearables/guides/abbott-libreview#-junction-eu-region) and [8 regions in the US environment](/wearables/guides/abbott-libreview#-junction-us-region). Previously, the Link API and Link Widget listed only the regions to which our practice account was registered. However, these practice accounts can often connect to patients in a larger geographical area beyond the region of registration. For example, patients in most EMEA countries can connect through our Netherlands practice account. Therefore, we have now changed: 1. Link Widget to display an exhaustive list of regions which our practice account can reach; and 2. Link API to accept any ISO 3166-1 code that is on the list. In other words, say if you have a patient domiciled in Belgium, it is no longer necessary to teach them to choose "Netherlands" when connecting through the Link Widget. They can now intuitively choose "Belgium" when asked by the Link Widget. Check out the [Abbott LibreView](/wearables/guides/abbott-libreview) guide and the [Connect Email Provider](/api-reference/link/link-email-provider) endpoint for more information. ### Electrocardiogram, Heart Rate Alert and AFib Burden (Dec 2024) Junction now supports collecting Electrocardiogram (ECG) data and a couple of related data points from a set of providers: | Resource | Apple HealthKit \[3] | Fitbit | Withings | Kardia | | ------------------------------------------------------- | ------------------------------- | ----------------- | ----------------- | ----------------- | | Electrocardiogram Summary
`electrocardiogram` | βœ… | - | βœ… | βœ… | | ECG Voltage timeseries
`electrocardiogram_voltage` | βœ… | - | βœ… | βœ… | | Heart Rate Alert
`heart_rate_alert` | βœ… \[1] | βœ… \[2] | βœ… \[2] | βœ… \[2] | | AFib Burden
`afib_burden` | βœ… | - | - | - | \[1] Irregular rhythm alerts, high heart rate alerts and low heart rate alerts.
\[2] Irregular rhythm alerts only.
\[3] Requires Junction iOS SDK 1.3.0+, Junction Flutter SDK 4.4.0+ or Junction React Native SDK 5.1.0+.
For more information, check out: * the [Get Electrocardiogram](/api-reference/data/electrocardiogram/get-summary) endpoint documentation; * the [Get Electrocardiogram Voltage](/api-reference/data/timeseries/electrocardiogram-voltage) endpoint documentation; * the [Get Heart Rate Alert](/api-reference/data/timeseries/heart-rate-alert) endpoint documentation; * the [Get AFib Burden](/api-reference/data/timeseries/afib-burden) endpoint documentation; * the [Electrocardiogram data events](/event-catalog/daily.data.electrocardiogram.created) in the Event Catalog; * the [Electrocardiogram Voltage data events](/event-catalog/daily.data.electrocardiogram_voltage.created) in the Event Catalog; * the [Heart Rate Alert data events](/event-catalog/daily.data.heart_rate_alert.created) in the Event Catalog; and * the [AFib Burden data events](/event-catalog/daily.data.afib_burden.created) in the Event Catalog. ### Sleep Cycle Summary Type (Nov 2024) We are introducing a new Sleep Cycle summary type (`sleep_cycle`) which captures the detailed hypnogram of a sleep session. The existing hypnogram timeseries type is deprecated in favor of this new summary type. Check out the [Get Sleep Cycle](/api-reference/data/sleep-cycle/get-summary) endpoint and the [Sleep Cycle data events](/event-catalog/daily.data.sleep_cycle.created) in the Event Catalog for more information. ### Body Summary model extension (Nov 2024) The Body Summary model now includes 4 new fields: * `water_percentage` - The percentage of water in the body. * `muscle_mass_percentage` - The percentage of muscle mass in the body. * `visceral_fat_index` - Provider's score of visceral fat levels. * `bone_mass_percentage` - The percentage of bone mass in the body. At the time of writing, all four are only available from the Withings provider. Check out the [Get Body Summary](/api-reference/data/body/get-summary) endpoint and the [Body Created](/event-catalog/daily.data.body.created) event for more information. ### Sleep Type (Nov 2024) Sleep summaries now have a new *Sleep Type* field. Junction maps the Sleep Type from the source provider whenever possible. If this is unavailable at source, Junction infers the Sleep Type based on the sleep session duration. | Sleep Type | Description | | ------------------ | -------------------------------------------------------- | | `long_sleep` | >=3 hours of sleep | | `short_sleep` | \<3 hours of sleep | | `acknowledged_nap` | User-acknowledged naps, typically under 3 hours of sleep | | `unknown` | The sleep session recording is ongoing. | Check out the [Get Sleep endpoint](/api-reference/data/sleep/get-summary) and the [Sleep data events](/event-catalog/daily.data.sleep.created) in the Event Catalog for more information. ### Apple HealthKit data sync improvements (Aug 2024) An overhauled Apple HealthKit sync engine is now available across all Junction Mobile SDK platforms. The changes bring historical data sync incrementality, prioritization, network resiliency and reduced resource usage. 1. Most resources now use a resumable sync & upload process. * This enables the SDK to make constant forward progress, especially when you have specified a very large historical pull stage (60-365 days) through the [Team Data Pull Preferences](/api-reference/org-management/team-data-pull-preferences/upsert-team-data-pull-preferences) API. 2. The SDK now prioritizes syncing of summary types over timeseries data. * During the historical pull stage, all timeseries resources would be suppressed until all the summary types have been successfully uploaded. * After the historical pull stage, the SDK would make forward progress on summary types, before it proceeds to deal with the more CPU-time-consuming timeseries data that are more prone to operating system throttling. 3. With an updated iOS App Target configuration, the SDK would now self-register as a `BGProcessingTask` or `BGHealthResearchTask` (iOS 17+) to the iOS BackgroundTasks framework. * This would provide the SDK an additional opportunity to complete any resource sync that is not able to complete during normal HealthKit background delivery. * Please refer to the [Apple HealthKit guide](/wearables/guides/apple-healthkit#1-setup-app-entitlements) on how to update your iOS App Target configuration in Xcode. | Platform | Release Note | | ------------ | ------------------------------------------------------------------------------------------------- | | Native iOS | [vital-ios 1.2.2](https://github.com/tryVital/vital-ios/releases/tag/1.2.2) | | Flutter | [vital-flutter 4.2.1](https://github.com/tryVital/vital-flutter/releases/tag/vital_health-v4.2.1) | | React Native | [vital-react-native 4.2.1](https://github.com/tryVital/vital-react-native/releases/tag/4.2.1) | ### Menstrual Cycle Tracking (July 2024) Menstrual cycle tracking data can now be collected through the Apple HealthKit and Android Health Connect integrations. Ask for data permission on the `MenstrualCycle` resource from the user through the Junction Health SDK. Check out the [Get Menstrual Cycles](/api-reference/data/menstrual-cycle/get-summary) endpoint and the [Menstrual Cycle data events](/event-catalog/daily.data.menstrual_cycle.created) in the Event Catalog for more information. ### Steps count in workouts (May 2024) Workouts now include the total steps count during the session (if available). Check out the [Get Workouts](/api-reference/data/workouts/get-summary) endpoint and the [Workout Created](/event-catalog/daily.data.workouts.created) event for more information. ### New Abbott LibreView integration (May 2024) Junction has introduced a new Abbott LibreView provider (`abbott_libreview`). It uses password authentication, accepting LibreView patient account credentials. This is an alternative option to our practice-based Freestyle Libre provider (`freestyle_libre`). With `abbott_libreview`, Junction uses the provided LibreView patient account credentials to connect directly to LibreView. There is no involvement of a LibreView practice in this integration. Note that both practice-based and patient-based connections would continue to be supported in parallel. The `abbott_libreview` integration does not replace the `freestyle_libre` integration. Check out the [Abbott LibreView / Freestyle Libre](/wearables/guides/abbott-libreview) guide for more information. ### Removed Fitbit and Oura required scopes (May 2024) The Fitbit profile scope and Oura email scope are no longer required for establishing connections. For Fitbit specifically, please be aware of the [updated Fitbit Time Zone resolution precedences](/wearables/guides/fitbit#time-zone-resolution). When your user refuses to grant both the activity and the profile scope, Fitbit data are more likely to be timestamped incorrectly on a UTC time basis due to inaccurate or unavailable time zone information. We have now updated our Fitbit and Oura integrations not to depend on these scopes to be **minimally functional**. If you are interested in requiring your users to grant certain scopes when connecting an OAuth provider, check out the [Team Scope Requirements](/changelog/wearables/api#team-scope-requirements-apr-2024) changelog entry and the [Set Team Scope Requirements](/api-reference/org-management/team-scope-requirements/upsert-team-scope-requirements) endpoint for more information. ### Freestyle Libre: India region (Apr 2024) Our Freestyle Libre integration now supports the LibreView India region. Check out the [Abbott LibreView](/wearables/guides/abbott-libreview#bring-your-own-practice) documentation for more information. ### Health Connect Background Sync (Mar 2024) Junction Mobile SDK now includes an experimental Background Sync feature for Android Health Connect. The feature is available through the following Junction Mobile SDK releases: | Platform | Version | | -------------- | ------- | | Native Android | 2.0.0+ | | Flutter | 3.2.0+ | | React Native | 3.1.0+ | Check out the following documentation for information, integration guidance, as well as caveats of the experimental Background Sync: * [Junction Health SDK: Automatic Data Sync](/wearables/sdks/health/overview#automatic-data-sync) for a general overview * [Android Health Connect integration guide](/wearables/guides/android-health-connect#background-sync), which includes guidance on the experimental Background Sync feature. ### Expanded Source Type attribution (Feb 2024) Data from Fitbit, Oura, Garmin and Freestyle Libre now comes with Source Type attributions. Check out the [Data Attributions](/wearables/providers/data-attributions#source-type) documentation for more information. # Callbacks Source: https://docs.junction.com/connect/callbacks Receive postMessage callbacks from Feature Embed iframes. Interested in this feature? Get in touch with your Customer Success Manager. When running in the `feature_embed` modality, the Junction iframe notifies your host page of significant events by posting a message to the parent window via the [Web Messaging API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). Callbacks are only emitted from Feature Embed iframes. They are never emitted in the `link_out` modality. ## Listening for callbacks Add a `message` event listener to the host window and filter by the `type` field: ```ts theme={null} // Replace with your organization's slug from Junction Connect configuration. const JUNCTION_ORIGIN = "https://.ehr.junction.com"; window.addEventListener("message", (event) => { // Always validate the origin before acting on the message. if (event.origin !== JUNCTION_ORIGIN) { return; } const message = event.data; switch (message.type) { case "urn:junction:order:created": console.log("Order created", message.data); break; case "urn:junction:order:creation_cancelled": console.log("Order creation cancelled", message.data); break; } }); ``` Always check `event.origin` before reading `event.data`. Reject any message whose origin does not match your Junction subdomain. ## Security Each Junction organization is served from a dedicated subdomain: `https://.ehr.junction.com`, where `` is the unique slug from your [Junction Connect configuration](/connect/concepts#configuration). Junction always targets your registered origin explicitly β€” it never posts to `"*"`. The target origin is resolved from the iframe's `ancestorOrigins` or `document.referrer`. If the origin cannot be resolved, the message is silently dropped rather than broadcast. Your listener must independently validate `event.origin` before trusting the payload, since any page on your origin may receive `message` events. ## Callback reference ### `urn:junction:order:created` Emitted when the provider successfully submits a lab order via the `order_creation` feature. **Payload** | Field | Type | Description | | ---------- | --------------- | ------------------------------------------------------------- | | `order_id` | `string (UUID)` | The Junction order ID. | | `user_id` | `string (UUID)` | The Junction user (patient) ID for whom the order was placed. | | `team_id` | `string (UUID)` | The Junction team ID the order belongs to. | **Example** ```json theme={null} { "type": "urn:junction:order:created", "data": { "order_id": "00000000-0000-0000-0000-000000000000", "user_id": "00000000-0000-0000-0000-000000000000", "team_id": "00000000-0000-0000-0000-000000000000" } } ``` **Common uses** * Close or hide the embed iframe after a successful order. * Navigate the host application to an order detail view. * Trigger a server-side webhook or audit log entry. *** ### `urn:junction:order:creation_cancelled` Emitted when the provider explicitly cancels the order creation flow before submitting. **Payload** | Field | Type | Description | | --------- | ----------------------- | ----------------------------------------------------------------------------------------------------------- | | `user_id` | `string (UUID) \| null` | The Junction user (patient) ID, if one was selected before cancellation. `null` if no patient was selected. | | `team_id` | `string (UUID)` | The Junction team ID associated with the session. | **Example** ```json theme={null} { "type": "urn:junction:order:creation_cancelled", "data": { "user_id": null, "team_id": "00000000-0000-0000-0000-000000000000" } } ``` **Common uses** * Close or hide the embed iframe. * Return the provider to a previous screen in your application. # Concepts Source: https://docs.junction.com/connect/concepts Core concepts behind Junction Connect, including orgs, teams, members, users, and integration-managed members. Interested in this feature? Get in touch with your Customer Success Manager. ## Preface Junction Connect helps you integrate Junction Dashboard features into your web application. To facilitate this, Junction Connect makes a few assumptions: 1. You programmatically manage the profiles of the providers as [integration-managed members](#integration-managed-members). 2. An integration-managed member must be at least a **team admin** of the team for Junction Connect to work. What *provider* means in your use case may differ. Here are two example mappings for your consideration: | Junction noun | Synonym | Meaning | API | | ---------------------- | ----------- | --------------------------------------------------------------------------------- | ------------------------------------------------------ | | Org | - | Your business entity. | [Management API](/api-details/junction-management-api) | | Team | - | A division in your Junction organization, containing an isolated pool of *users*. | [Management API](/api-details/junction-management-api) | | Member
Org Admin | Staff | Your members of staff. | [Management API](/api-details/junction-management-api) | | Member
Team Admin | Provider πŸ“ | Your members of staff, with access restricted to a specific set of *teams*. | [Management API](/api-details/junction-management-api) | | User | Patient | An end user of the device and lab testing services; belongs to a *team*. | [Junction API](/api-details/junction-api) |
| Junction noun | Synonym | Meaning | API | | ---------------------- | ----------- | ------------------------------------------------------------------------ | ------------------------------------------------------ | | Org | - | Your business entity. | [Management API](/api-details/junction-management-api) | | Team | - | A customer of yours. | [Management API](/api-details/junction-management-api) | | Member
Org Admin | - | Your own members of staff. | [Management API](/api-details/junction-management-api) | | Member
Team Admin | Provider πŸ“ | A customer's members of staff. | [Management API](/api-details/junction-management-api) | | User | Patient | An end user of the device and lab testing services; belongs to a *team*. | [Junction API](/api-details/junction-api) |
## Core flow Use the Junction Management API to create or resolve the team and integration-managed member for the current provider. Call [Create Dashboard URL](/api-reference/org-management/connect/create-dashboard-url) with the target member, team, modality, feature, and environment. Open the returned Dashboard URL in a top-level browser context for Link Out, or load it in an iframe for Feature Embed. ```mermaid theme={null} sequenceDiagram autonumber participant PartnerApp as Your Web App participant PartnerBackend as Your Backend participant API as Junction Management API participant Junction as Junction Web App PartnerApp->>PartnerBackend: Request dashboard URL PartnerBackend->>API: POST /v1/org/{org_id}/ehr_integration/create_dashboard_url API-->>PartnerBackend: Dashboard URL PartnerBackend-->>PartnerApp: Dashboard URL PartnerApp->>Junction: Open URL Junction->>Junction: Configure session and route to feature ``` ## Configuration You can configure Junction Connect either through ["Org Config β†’ Junction Connect"](https://app.junction.com/org/ehr-integration) in the Junction Dashboard, or programmatically via the [Set Junction Connect Configuration](/api-reference/org-management/connect/set-configuration) endpoint on the Junction Management API. | Setting | Description | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Unique slug | A unique kebab-case slug that identifies your organization, e.g., `my-clinical-practice`. Your [Fast Launch](/connect/fast-launch) subdomain is based on this slug. | | Modalities | The Junction Connect modalities you intend to use: `link_out`, `feature_embed`, both, or none. | | Allowed origins | Origins allowed to launch Link Out or Feature Embed sessions.

For each origin, you may optionally specify a publicly accessible [Session Continuation URL](/connect/session-continuation). If this is left unspecified, [Fast Launch](/connect/fast-launch) will not work, and Junction Connect will show an error screen when it encounters a launch error or an irrecoverable client session. | ## Integration-managed members To launch Junction Connect in either modality, identify the provider who should use Junction Dashboard as an integration-managed member. These members are created and managed through the Junction Management API by your backend system. Integration-managed members: * can sign in only through Junction Connect launch flows; * cannot sign in through Junction Dashboard identity providers; and * can be assigned team role bindings when created or updated. ## Feature slug [Features](/connect/overview#features) are represented by a **feature slug**. Use a feature slug when you: * create a pre-authorized [Dashboard URL](/api-reference/org-management/connect/create-dashboard-url); * assemble a [Fast Launch URL](/connect/fast-launch); or * handle a [Session Continuation request](/connect/session-continuation) from Junction Connect. # Fast Launch Source: https://docs.junction.com/connect/fast-launch Use Fast Launch URLs to reduce repeated Junction Connect launch latency when a compatible Junction session already exists. Interested in this feature? Get in touch with your Customer Success Manager. Fast Launch lets your client-side application open a Junction feature without first asking your backend to create a dashboard URL. When Junction detects an existing compatible session, it routes directly to the requested feature. If it cannot reuse a session, it redirects to your [session continuation URL](/connect/session-continuation), where your application creates a new dashboard URL. Use Fast Launch when: * you embed Junction features in iframes; and * users often move between parts of your app that embed different Junction features. ## Fast Launch URL Use your partner integration slug as the subdomain. ```text theme={null} https://{integration_slug}.ehr.junction.com/auth/launch ``` You can identify the target member and team with either partner references or Junction IDs. ```text Partner references theme={null} https://{integration_slug}.ehr.junction.com/auth/launch ?integration_member_id={integration_member_id} &integration_team_id={integration_team_id} &modality={modality} &feature={feature} &environment={environment} ``` ```text Junction IDs theme={null} https://{integration_slug}.ehr.junction.com/auth/launch ?member_id={member_id} &team_id={team_id} &modality={modality} &feature={feature} &environment={environment} ``` | Parameter | Description | | ----------------------- | --------------------------------------------------------------------------- | | `integration_member_id` | Your unique reference for the member. Mutually exclusive with `member_id`. | | `member_id` | Junction-issued member ID. Mutually exclusive with `integration_member_id`. | | `integration_team_id` | Your unique reference for the team. Mutually exclusive with `team_id`. | | `team_id` | Junction-issued team ID. Mutually exclusive with `integration_team_id`. | | `modality` | `feature_embed` or `link_out`. | | `feature` | Supported feature slug, such as `order_creation` or `team_config`. | | `environment` | `sandbox` or `production`. | ## Feature Embed flow ```mermaid theme={null} sequenceDiagram autonumber participant PartnerApp as Your Web App participant Junction as Junction Connect participant Continuation as Session Continuation URL participant API as Junction Management API PartnerApp->>Junction: Load Fast Launch URL in iframe alt Compatible Junction session exists Junction->>Junction: Route directly to requested feature else Session missing or incompatible Junction-->>PartnerApp: Redirect iframe to session continuation URL PartnerApp->>Continuation: Request with launch parameters Continuation->>Continuation: Validate app session and parameters Continuation->>API: Create dashboard URL API-->>Continuation: Post-authorization URL Continuation-->>PartnerApp: 307 redirect to post-authorization URL PartnerApp->>Junction: Open post-authorization URL Junction->>Junction: Configure session and route to feature end ``` ## Link Out flow For Link Out, open the same Fast Launch URL in a top-level browser context. If Junction can reuse the session, it routes immediately. Otherwise, it redirects the browser to your session continuation URL before returning to Junction with a new post-authorization URL. ## Implementation notes * Keep the `feature`, `modality`, and `environment` values in your own allowlist. * Prefer partner references (`integration_member_id` and `integration_team_id`) when they are already available in your client runtime. * Your session continuation endpoint must validate the current partner session before creating the dashboard URL. # Getting Started Source: https://docs.junction.com/connect/getting-started Configure Junction Connect and launch a Junction workflow from your application. Interested in this feature? Get in touch with your Customer Success Manager. Use this guide to launch Junction from your application for the first time. ## Prerequisites You need: * a Junction organization ID; * a Junction Management Key; * a registered Junction Connect integration with at least one enabled modality; * an allowed origin for your web application; and * a session continuation URL controlled by your application. Junction Management API requests use `https://api.management.junction.com/` and the `X-Management-Key` header. Use the [Set Junction Connect Configuration endpoint](/api-reference/org-management/connect/set-configuration) to set your slug, modalities, and allowed origins. See [Concepts -> Configuration](/connect/concepts#configuration) for details about each setting. Use the [Create Team endpoint](/api-reference/org-management/team/create-team). Teams can include an `integration_team_id`, which is your stable team reference. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/team \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "name": "Downtown Clinic", "region": "us", "integration_team_id": "clinic_123" }' ``` If the team already exists, use the [Resolve Team endpoint](/api-reference/org-management/team/resolve-team) to resolve it by integration reference: ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/resolve_team \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_team_id": "clinic_123" }' ``` Use the [Create Integration-Managed Member endpoint](/api-reference/org-management/connect/create-member) to create the member that should be signed in through Junction Connect. Include team role bindings for every team the member should access. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/member \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456", "name": "Alex Kim", "email": "alex@example.com", "team_role_bindings": [ { "team_id": "00000000-0000-0000-0000-000000000000", "role": "admin" } ] }' ``` If the member already exists, use the [Resolve Integration-Managed Member endpoint](/api-reference/org-management/connect/resolve-member) to resolve it by integration reference: ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/resolve_member \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456" }' ``` Skip this step unless you are launching a [feature](/connect/overview#features) that is scoped to a specific patient, such as `order_creation:{user_id}`. In that case the patient must exist as a Junction user in the destination team before you create the dashboard URL β€” the patient-scoped feature slug embeds the Junction `user_id`. Use the team-scoped Junction API (see [authentication](/api-details/junction-api#authentication) and [environments](/api-details/junction-api#environments)): * [Create user](/api-reference/user/create-user) β€” keyed by your `client_user_id`. * [Update user demographics](/api-reference/user/upsert-info) β€” set name, date of birth, and any other fields the feature requires. To launch the embed scoped to this patient, use the patient-scoped feature slug (e.g. `order_creation:{user_id}`) as the `feature` value in the next step, substituting the resolved Junction `user_id`. Use the [Create Dashboard URL endpoint](/api-reference/org-management/connect/create-dashboard-url) to create a post-authorization URL for the member, team, modality, feature, and environment. ```bash cURL theme={null} curl --request POST \ --url https://api.management.junction.com/v1/org/{org_id}/ehr_integration/create_dashboard_url \ --header 'Content-Type: application/json' \ --header 'X-Management-Key: ' \ --data '{ "integration_member_id": "user_456", "integration_team_id": "clinic_123", "modality": "feature_embed", "feature": "order_creation", "environment": "sandbox" }' ``` Use the URL returned by the [Create Dashboard URL endpoint](/api-reference/org-management/connect/create-dashboard-url). For `feature_embed`, load it in an iframe: ```html theme={null} ``` For `link_out`, open the returned URL in a top-level navigation context, such as a new tab or popup window. For faster repeated launches, use [Fast Launch](/connect/fast-launch) after you have implemented [Session Continuation](/connect/session-continuation). # Overview Source: https://docs.junction.com/connect/overview Embed Junction Dashboard experiences into your application or launch the dashboard in a separate browser context. Interested in this feature? Get in touch with your Customer Success Manager. Junction Connect enables you to integrate the Junction Dashboard provider experience seamlessly into your existing web application. This serves as an alternative to building your own provider experience on top of the [Lab Testing API](/lab/overview/introduction). ## Modalities Junction supports two Junction Connect modalities: Opens Junction Dashboard in a top-level browser context, such as a new tab or popup window. You want the provider to leave your app context and use the full Junction Dashboard. Embed a specific Junction Dashboard feature as an iframe into your web application. You want your web application to own navigation and page structure while the iframe stays focused on one Junction workflow. ## Environments Junction Connect supports launching a team into the sandbox environment or the production environment. The sandbox environment is isolated from the production environment, and provides you access to [additional testing facilities](/lab/overview/sandbox), such as creating test orders as well as order life cycle simulation. Specify your target environment through the request `environment` field in the [Create Dashboard URL](/api-reference/org-management/connect/create-dashboard-url) endpoint. For example, you can create test orders in Junction Dashboard and test the embedded order detail experience throughout the order lifecycle: 1. Create a Dashboard URL with `environment` set to `sandbox` and `feature` set to `order_creation`. 2. Open the URL and create a test order in Junction Dashboard. 3. As the order moves through its lifecycle, create a new sandbox Dashboard URL with `feature` set to `order:{id}`. 4. Load each returned URL in your embed to test the order detail experience at the relevant lifecycle state. ## Features Junction Connect supports the following features: | Feature slug | Feature | | -------------------------- | -------------------------------------------- | | `order_creation` | Order creation | | `order_creation:{user_id}` | Order creation for a specific patient (user) | | `order:{id}` | Order detail | | `team_panels` | Panel management | | `team_config` | Team configuration | While you must specify a feature to launch for both the *Link Out* and *Feature Embed* modalities, they have different behaviors: | Modality | Behavior | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Link Out | The feature controls where the Junction Dashboard lands initially. The provider can navigate away afterward and use other parts of the Junction Dashboard. | | Feature Embed | The iframe is locked to the feature you requested. | # Session Continuation Source: https://docs.junction.com/connect/session-continuation Implement the endpoint Junction calls when it needs your application to recover a Junction Connect session. Interested in this feature? Get in touch with your Customer Success Manager. Session continuation lets Junction recover a Junction Connect session when no compatible session exists, such as after prolonged inactivity or when using Fast Launch. Your session continuation URL must be a publicly accessible endpoint controlled by your application. Junction redirects the user's browser to this endpoint with launch parameters. Your application validates the current signed-in user, creates a Junction dashboard URL, and returns a `307 Temporary Redirect` to that URL. ## Requirements Your endpoint must: * validate that the browser has a valid session with your application; * verify that the requested integration member and team match the signed-in user and account context; * validate the requested modality, feature, and environment before forwarding them to Junction; * create a dashboard URL through the Junction Management API; and * respond with a `307 Temporary Redirect` to the returned post-authorization URL. Do not blindly forward query parameters into the Management API. Treat session continuation requests as untrusted input and authorize them against your application's current session. ## Continuation flow ```mermaid theme={null} sequenceDiagram autonumber participant Browser as User Browser participant Junction as Junction App participant Partner as Partner Session Continuation URL participant API as Junction Management API Browser->>Junction: Open Junction Connect or Fast Launch URL Junction->>Junction: No compatible session Junction-->>Browser: Redirect to session continuation URL Browser->>Partner: Request with launch parameters and partner credentials Partner->>Partner: Validate partner session and launch parameters Partner->>API: Create dashboard URL API-->>Partner: Post-authorization URL Partner-->>Browser: 307 Temporary Redirect Browser->>Junction: Open post-authorization URL Junction->>Junction: Configure session and route to feature ``` ## Example endpoint ```python theme={null} from typing import Annotated import httpx from fastapi import APIRouter, HTTPException, Query, Request from pydantic import BaseModel, HttpUrl from starlette.responses import RedirectResponse router = APIRouter() class CreateDashboardURLResponse(BaseModel): url: HttpUrl expires_in: int @router.get("/junction-session-continuation") async def handle_junction_session_continuation( request: Request, integration_member_id: Annotated[str, Query()], integration_team_id: Annotated[str | None, Query()] = None, team_id: Annotated[str | None, Query()] = None, modality: Annotated[str, Query()] = "feature_embed", feature: Annotated[str, Query()] = "order_creation", environment: Annotated[str, Query()] = "sandbox", ) -> RedirectResponse: session_user = await verify_valid_session_cookie(request) if session_user.integration_member_id != integration_member_id: raise HTTPException(401, "Invalid continuation request") if modality not in {"feature_embed", "link_out"}: raise HTTPException(400, "Invalid modality") if feature not in allowed_features_for_user(session_user): raise HTTPException(403, "Feature is not allowed") payload = { "integration_member_id": integration_member_id, "modality": modality, "feature": feature, "environment": environment, } if integration_team_id is not None: payload["integration_team_id"] = integration_team_id elif team_id is not None: payload["team_id"] = team_id async with httpx.AsyncClient() as client: response = await client.post( f"https://api.management.junction.com/v1/org/{org_id}/ehr_integration/create_dashboard_url", headers={"X-Management-Key": management_key}, json=payload, ) response.raise_for_status() dashboard_url = CreateDashboardURLResponse.model_validate_json(response.text) return RedirectResponse(str(dashboard_url.url), status_code=307) ``` ## Redirect status Use `307 Temporary Redirect` so the browser follows the continuation result without treating it as a permanent redirect. This keeps future session recovery requests pointed at your session continuation URL. # Continuous Query Overview Source: https://docs.junction.com/continuous-query-overview Automatically aggregate raw activity and biometric data from connected devices into structured datasets that update as new data arrives. [Continuous Query](https://docs.junction.com/api-reference/horizon-ai/aggregation/using-continuous-query) automatically transforms raw activity and biometric data from 300+ connected devices into structured, aggregated datasets that update as new data arrives. Instead of building complex data pipelines or repeatedly polling APIs, you define your query once and Junction handles the restβ€”from data ingestion and aggregation to intelligent scheduling and delivery. ## How It Works Continuous Query runs your Junction Sense Queries automatically across all users in your team. When new data arrives from connected devicesβ€”whether via cloud providers or [mobile SDKs](https://docs.junction.com/wearables/sdks/vital-health)β€”Junction intelligently schedules query re-evaluation and pushes any changes to your configured destinations. ### Key Capabilities Queries run automatically on all existing and new users in your team, eliminating manual execution Result changes are pushed to your webhook or ETL pipeline destinationsβ€”no polling required Junction monitors data connections and schedules queries in response to new data points or updates Query the latest result table through the [API](https://docs.junction.com/api-reference/horizon-ai/continuous-query/get-result-table) anytime ## Common Use Cases Track key health metrics over time to power patient dashboards, clinical insights, or wellness reports. **Example: Daily Sleep Analysis** * Analyze sleep efficiency, scores, and chronotype for primary sleep sessions * Filter for long sleep periods to focus on nighttime rest * Monitor quality trends across consecutive nights * [View example β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples#daily-main-sleep-session-analysis) **Example: Weekly Activity Summaries** * Calculate average resting heart rate and active duration * Track maximum daily calorie burn and minimum step counts * Group activity data by week for trend analysis * [View example β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples#weekly-insights-into-users-activity) Support diabetes management and metabolic health tracking with automated CGM data aggregation. **Example: First Glucose Reading of Each Day** * Capture fasting glucose values (first measurement per day) * Group by data source and provider for device comparison * Track morning glucose patterns over time * [View example β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples#first-glucose-measurement-of-the-day-grouped-by-source-type-and-provider) **Example: Daily Summaries of Metabolites** * Calculate mean glucose levels throughout the day * Combine with heart rate, HRV, and temperature data * Analyze multi-metric patterns by device source * [View example β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples#daily-aggregations-of-select-timeseries-datapoints-grouped-by-source-type-and-provider) Power adaptive training programs with continuously updated workout and activity metrics. **Example: Weekly Workout Statistics** * Track calorie expenditure ranges (min/max) across workouts * Monitor heart rate zone distribution for training intensity * Aggregate distance and active duration metrics * [View example β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples#weekly-insights-into-workout-statistics) **Use case highlights:** * Real-time metric tracking for goal progress * Device-specific analysis to handle data from multiple sources * Webhook integration for triggering adaptive training plans * Historical trend data for personalized coaching Support research protocols requiring consistent, automated data collection across participants. **Use case highlights:** * Automatic data aggregation for all enrolled participants * Consistent time-window grouping (daily, weekly, monthly) * Event notifications when new data becomes available * Result tables compatible with research analysis tools * Source-level granularity for data quality assessment Analyze health trends across user populations for public health initiatives or employer wellness programs. **Use case highlights:** * Scalable aggregation across thousands of users * Standardized metrics despite diverse device ecosystems * Automated daily/weekly rollups for reporting dashboards * ETL pipeline integration for data warehouses ## Supported Data Sources Continuous Query works with the following health data resources: * **Activity** - Steps, calories, distance, active duration, resting heart rate * **Sleep** - Duration, stages, efficiency, scores, heart rate during sleep, sleep type filtering * **Workout** - Exercise sessions, heart rate zones, distance, duration, calories * **Body** - Weight, BMI, body fat percentage, temperature * **Meal** - Nutritional intake, macros, timing * **Time Series** - Continuous measurements including heart rate, glucose, HRV, steps, body temperature Each query focuses on a single data resource, ensuring clean schemas and optimal performance. For multi-resource analysis, create separate queries and join results in your application layer. [View complete data resource documentation β†’](https://docs.junction.com/wearables/providers/resources) ## Query Capabilities ### Time-Based Aggregation Group data by day, week, month, or other time periods to create time-series datasets: * Daily summaries for dashboards and trend visualization * Weekly rollups for progress tracking * Monthly aggregations for longitudinal analysis ### Flexible Metrics Calculate meaningful insights using built-in [aggregation functions](https://docs.junction.com/api-reference/horizon-ai/aggregation/query-dsl/select-clause#aggregate-a-table-column): * **Mean/Average** - Average sleep efficiency, resting heart rate, glucose levels * **Sum** - Total steps, cumulative calories * **Min/Max** - Lowest/highest values in a period * **Standard Deviation** - Variability in metrics * **Newest/Oldest** - Most recent or first value (useful for fasting glucose, chronotype) ### Multi-Dimensional Grouping Organize data across multiple dimensions for richer analysis: * Time periods (day, week, month) * Data sources (provider, device type) * Custom fields (workout type, sleep type) [View complete grouping reference β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/query-dsl/column-expressions#table-column-expression) ### Source Prioritization When users connect multiple devices, Junction's source prioritization ensures data quality: * Configure team-level provider priorities * Override priorities at the query level for experiments * Optionally split results by data source for comparative analysis ### Filtering & Refinement Use WHERE clauses to focus on specific data subsets: * Filter for main sleep sessions (`type = 'long_sleep'`) * Target specific workout types or activity levels * Isolate data from particular device sources ## Getting Started **Step 1: Define Your Query** Use the [Query DSL](https://docs.junction.com/api-reference/horizon-ai/aggregation/query-dsl/) to specify what data to aggregate, how to group it, and which metrics to calculate. **Step 2: Validate the Query** Use the Junction Dashboard Query Editor to preview and validate the result table schema and catch any issues before creation. **Step 3: Deploy Query** Deploy your query using the [create endpoint](https://docs.junction.com/api-reference/horizon-ai/continuous-query/create) or by saving your query in the Junction Dashboard. **Step 4: Configure Delivery** Set up webhooks or ETL pipelines to receive result updates automatically. [Jump to Getting Started Guide β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/using-continuous-query) ## Query API vs. Continuous Query Both use the same Query DSL, making it easy to prototype with Query API and deploy to production with Continuous Query. [Compare in detail β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/overview#query-api-and-continuous-query) | *Feature* | *Query API* | *Continuous Query* | | :------------ | :------------------------------- | :------------------------------------ | | **Execution** | On-demand, single request | Automatic, continuous evaluation | | **Scope** | Single user, point-in-time | All team users, ongoing | | **Delivery** | Synchronous API response | Webhooks, ETL pipelines, API pull | | **Best For** | Experimentation, ad-hoc analysis | Production workflows, monitoring | | **Use When** | Testing queries, exploring data | Building features, generating reports | ## What's Next? [Manage Queries Using Junction Dashboard](/sense/managing-queries) **View Example Queries** * Copy-paste examples for sleep, activity, glucose, and workout queries * [Browse examples β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/examples) **Getting Started Guide** * Step-by-step tutorial to create your first Junction Sense query * [Get started β†’](https://docs.junction.com/api-reference/horizon-ai/continuous-query/getting-started) **Query DSL Reference** * Complete reference for building queries with available functions and constraints * [Read documentation β†’](https://docs.junction.com/api-reference/horizon-ai/aggregation/query-dsl/) **API Endpoints** * Create, manage, and retrieve results from your Continuous Queries * [View API reference β†’](https://docs.junction.com/api-reference/horizon-ai/continuous-query/create) # continuous_query.result_table.changed Source: https://docs.junction.com/event-catalog/continuous_query.result_table.changed Fired when a Continuous Query's result table changes, indicating updated derived metrics for a user. # daily.data.activity.created Source: https://docs.junction.com/event-catalog/daily.data.activity.created Webhook event fired when Vital ingests a new daily activity summary for a user in the current day's data window. # daily.data.activity.updated Source: https://docs.junction.com/event-catalog/daily.data.activity.updated Webhook event fired when Vital updates an existing daily activity summary for a user in the current day's data window. # daily.data.afib_burden.created Source: https://docs.junction.com/event-catalog/daily.data.afib_burden.created Webhook event fired when Vital ingests a new atrial fibrillation (AFib) burden for a user in the current day's data window. # daily.data.afib_burden.updated Source: https://docs.junction.com/event-catalog/daily.data.afib_burden.updated Webhook event fired when Vital updates an existing atrial fibrillation (AFib) burden for a user in the current day's data window. # daily.data.basal_body_temperature.created Source: https://docs.junction.com/event-catalog/daily.data.basal_body_temperature.created Webhook event fired when Vital ingests a new basal body temperature time-series for a user in the current day's data window. # daily.data.basal_body_temperature.updated Source: https://docs.junction.com/event-catalog/daily.data.basal_body_temperature.updated Webhook event fired when Vital updates an existing basal body temperature time-series for a user in the current day's data window. # daily.data.blood_oxygen.created Source: https://docs.junction.com/event-catalog/daily.data.blood_oxygen.created Webhook event fired when Vital ingests a new blood oxygen saturation (SpO2) time-series for a user in the current day's data window. # daily.data.blood_oxygen.updated Source: https://docs.junction.com/event-catalog/daily.data.blood_oxygen.updated Webhook event fired when Vital updates an existing blood oxygen saturation (SpO2) time-series for a user in the current day's data window. # daily.data.blood_pressure.created Source: https://docs.junction.com/event-catalog/daily.data.blood_pressure.created Webhook event fired when Vital ingests a new blood pressure time-series for a user in the current day's data window. # daily.data.blood_pressure.updated Source: https://docs.junction.com/event-catalog/daily.data.blood_pressure.updated Webhook event fired when Vital updates an existing blood pressure time-series for a user in the current day's data window. # daily.data.body.created Source: https://docs.junction.com/event-catalog/daily.data.body.created Webhook event fired when Vital ingests a new daily body summary for a user in the current day's data window. # daily.data.body.updated Source: https://docs.junction.com/event-catalog/daily.data.body.updated Webhook event fired when Vital updates an existing daily body summary for a user in the current day's data window. # daily.data.body_mass_index.created Source: https://docs.junction.com/event-catalog/daily.data.body_mass_index.created Webhook event fired when Vital ingests a new body mass index (BMI) time-series for a user in the current day's data window. # daily.data.body_mass_index.updated Source: https://docs.junction.com/event-catalog/daily.data.body_mass_index.updated Webhook event fired when Vital updates an existing body mass index (BMI) time-series for a user in the current day's data window. # daily.data.body_temperature.created Source: https://docs.junction.com/event-catalog/daily.data.body_temperature.created Webhook event fired when Vital ingests a new body temperature time-series for a user in the current day's data window. # daily.data.body_temperature.updated Source: https://docs.junction.com/event-catalog/daily.data.body_temperature.updated Webhook event fired when Vital updates an existing body temperature time-series for a user in the current day's data window. # daily.data.body_temperature_delta.created Source: https://docs.junction.com/event-catalog/daily.data.body_temperature_delta.created Webhook event fired when Vital ingests a new body temperature delta time-series for a user in the current day's data window. # daily.data.body_temperature_delta.updated Source: https://docs.junction.com/event-catalog/daily.data.body_temperature_delta.updated Webhook event fired when Vital updates an existing body temperature delta time-series for a user in the current day's data window. # daily.data.caffeine.created Source: https://docs.junction.com/event-catalog/daily.data.caffeine.created Webhook event fired when Vital ingests a new caffeine intake time-series for a user in the current day's data window. # daily.data.caffeine.updated Source: https://docs.junction.com/event-catalog/daily.data.caffeine.updated Webhook event fired when Vital updates an existing caffeine intake time-series for a user in the current day's data window. # daily.data.calories_active.created Source: https://docs.junction.com/event-catalog/daily.data.calories_active.created Webhook event fired when Vital ingests a new active calories time-series for a user in the current day's data window. # daily.data.calories_active.updated Source: https://docs.junction.com/event-catalog/daily.data.calories_active.updated Webhook event fired when Vital updates an existing active calories time-series for a user in the current day's data window. # daily.data.calories_basal.created Source: https://docs.junction.com/event-catalog/daily.data.calories_basal.created Webhook event fired when Vital ingests a new basal calories time-series for a user in the current day's data window. # daily.data.calories_basal.updated Source: https://docs.junction.com/event-catalog/daily.data.calories_basal.updated Webhook event fired when Vital updates an existing basal calories time-series for a user in the current day's data window. # daily.data.carbohydrates.created Source: https://docs.junction.com/event-catalog/daily.data.carbohydrates.created Webhook event fired when Vital ingests a new carbohydrate intake time-series for a user in the current day's data window. # daily.data.carbohydrates.updated Source: https://docs.junction.com/event-catalog/daily.data.carbohydrates.updated Webhook event fired when Vital updates an existing carbohydrate intake time-series for a user in the current day's data window. # daily.data.daylight_exposure.created Source: https://docs.junction.com/event-catalog/daily.data.daylight_exposure.created Webhook event fired when Vital ingests a new daylight exposure time-series for a user in the current day's data window. # daily.data.daylight_exposure.updated Source: https://docs.junction.com/event-catalog/daily.data.daylight_exposure.updated Webhook event fired when Vital updates an existing daylight exposure time-series for a user in the current day's data window. # daily.data.distance.created Source: https://docs.junction.com/event-catalog/daily.data.distance.created Webhook event fired when Vital ingests a new distance time-series for a user in the current day's data window. # daily.data.distance.updated Source: https://docs.junction.com/event-catalog/daily.data.distance.updated Webhook event fired when Vital updates an existing distance time-series for a user in the current day's data window. # daily.data.electrocardiogram.created Source: https://docs.junction.com/event-catalog/daily.data.electrocardiogram.created Webhook event fired when Vital ingests a new electrocardiogram (ECG) reading for a user in the current day's data window. # daily.data.electrocardiogram.updated Source: https://docs.junction.com/event-catalog/daily.data.electrocardiogram.updated Webhook event fired when Vital updates an existing electrocardiogram (ECG) reading for a user in the current day's data window. # daily.data.electrocardiogram_voltage.created Source: https://docs.junction.com/event-catalog/daily.data.electrocardiogram_voltage.created Webhook event fired when Vital ingests a new electrocardiogram (ECG) voltage time-series for a user in the current day's data window. # daily.data.electrocardiogram_voltage.updated Source: https://docs.junction.com/event-catalog/daily.data.electrocardiogram_voltage.updated Webhook event fired when Vital updates an existing electrocardiogram (ECG) voltage time-series for a user in the current day's data window. # daily.data.fall.created Source: https://docs.junction.com/event-catalog/daily.data.fall.created Webhook event fired when Vital ingests a new fall detection time-series for a user in the current day's data window. # daily.data.fall.updated Source: https://docs.junction.com/event-catalog/daily.data.fall.updated Webhook event fired when Vital updates an existing fall detection time-series for a user in the current day's data window. # daily.data.fat.created Source: https://docs.junction.com/event-catalog/daily.data.fat.created Webhook event fired when Vital ingests a new dietary fat intake time-series for a user in the current day's data window. # daily.data.fat.updated Source: https://docs.junction.com/event-catalog/daily.data.fat.updated Webhook event fired when Vital updates an existing dietary fat intake time-series for a user in the current day's data window. # daily.data.floors_climbed.created Source: https://docs.junction.com/event-catalog/daily.data.floors_climbed.created Webhook event fired when Vital ingests a new floors climbed time-series for a user in the current day's data window. # daily.data.floors_climbed.updated Source: https://docs.junction.com/event-catalog/daily.data.floors_climbed.updated Webhook event fired when Vital updates an existing floors climbed time-series for a user in the current day's data window. # daily.data.forced_expiratory_volume_1.created Source: https://docs.junction.com/event-catalog/daily.data.forced_expiratory_volume_1.created Webhook event fired when Vital ingests a new forced expiratory volume in one second (FEV1) time-series for a user in the current day's data window. # daily.data.forced_expiratory_volume_1.updated Source: https://docs.junction.com/event-catalog/daily.data.forced_expiratory_volume_1.updated Webhook event fired when Vital updates an existing forced expiratory volume in one second (FEV1) time-series for a user in the current day's data window. # daily.data.forced_vital_capacity.created Source: https://docs.junction.com/event-catalog/daily.data.forced_vital_capacity.created Webhook event fired when Vital ingests a new forced vital capacity (FVC) time-series for a user in the current day's data window. # daily.data.forced_vital_capacity.updated Source: https://docs.junction.com/event-catalog/daily.data.forced_vital_capacity.updated Webhook event fired when Vital updates an existing forced vital capacity (FVC) time-series for a user in the current day's data window. # daily.data.glucose.created Source: https://docs.junction.com/event-catalog/daily.data.glucose.created Webhook event fired when Vital ingests a new blood glucose time-series for a user in the current day's data window. # daily.data.glucose.updated Source: https://docs.junction.com/event-catalog/daily.data.glucose.updated Webhook event fired when Vital updates an existing blood glucose time-series for a user in the current day's data window. # daily.data.handwashing.created Source: https://docs.junction.com/event-catalog/daily.data.handwashing.created Webhook event fired when Vital ingests a new handwashing events time-series for a user in the current day's data window. # daily.data.handwashing.updated Source: https://docs.junction.com/event-catalog/daily.data.handwashing.updated Webhook event fired when Vital updates an existing handwashing events time-series for a user in the current day's data window. # daily.data.heart_rate_alert.created Source: https://docs.junction.com/event-catalog/daily.data.heart_rate_alert.created Webhook event fired when Vital ingests a new heart rate alert time-series for a user in the current day's data window. # daily.data.heart_rate_alert.updated Source: https://docs.junction.com/event-catalog/daily.data.heart_rate_alert.updated Webhook event fired when Vital updates an existing heart rate alert time-series for a user in the current day's data window. # daily.data.heart_rate_recovery_one_minute.created Source: https://docs.junction.com/event-catalog/daily.data.heart_rate_recovery_one_minute.created Webhook event fired when Vital ingests a new one-minute heart rate recovery time-series for a user in the current day's data window. # daily.data.heart_rate_recovery_one_minute.updated Source: https://docs.junction.com/event-catalog/daily.data.heart_rate_recovery_one_minute.updated Webhook event fired when Vital updates an existing one-minute heart rate recovery time-series for a user in the current day's data window. # daily.data.heartrate.created Source: https://docs.junction.com/event-catalog/daily.data.heartrate.created Webhook event fired when Vital ingests a new heart rate time-series for a user in the current day's data window. # daily.data.heartrate.updated Source: https://docs.junction.com/event-catalog/daily.data.heartrate.updated Webhook event fired when Vital updates an existing heart rate time-series for a user in the current day's data window. # daily.data.hrv.created Source: https://docs.junction.com/event-catalog/daily.data.hrv.created Webhook event fired when Vital ingests a new heart rate variability (HRV) time-series for a user in the current day's data window. # daily.data.hrv.updated Source: https://docs.junction.com/event-catalog/daily.data.hrv.updated Webhook event fired when Vital updates an existing heart rate variability (HRV) time-series for a user in the current day's data window. # daily.data.inhaler_usage.created Source: https://docs.junction.com/event-catalog/daily.data.inhaler_usage.created Webhook event fired when Vital ingests a new inhaler usage time-series for a user in the current day's data window. # daily.data.inhaler_usage.updated Source: https://docs.junction.com/event-catalog/daily.data.inhaler_usage.updated Webhook event fired when Vital updates an existing inhaler usage time-series for a user in the current day's data window. # daily.data.insulin_injection.created Source: https://docs.junction.com/event-catalog/daily.data.insulin_injection.created Webhook event fired when Vital ingests a new insulin injection time-series for a user in the current day's data window. # daily.data.insulin_injection.updated Source: https://docs.junction.com/event-catalog/daily.data.insulin_injection.updated Webhook event fired when Vital updates an existing insulin injection time-series for a user in the current day's data window. # daily.data.lean_body_mass.created Source: https://docs.junction.com/event-catalog/daily.data.lean_body_mass.created Webhook event fired when Vital ingests a new lean body mass time-series for a user in the current day's data window. # daily.data.lean_body_mass.updated Source: https://docs.junction.com/event-catalog/daily.data.lean_body_mass.updated Webhook event fired when Vital updates an existing lean body mass time-series for a user in the current day's data window. # daily.data.meal.created Source: https://docs.junction.com/event-catalog/daily.data.meal.created Webhook event fired when Vital ingests a new meal entry for a user in the current day's data window. # daily.data.meal.updated Source: https://docs.junction.com/event-catalog/daily.data.meal.updated Webhook event fired when Vital updates an existing meal entry for a user in the current day's data window. # daily.data.menstrual_cycle.created Source: https://docs.junction.com/event-catalog/daily.data.menstrual_cycle.created Webhook event fired when Vital ingests a new menstrual cycle entry for a user in the current day's data window. # daily.data.menstrual_cycle.updated Source: https://docs.junction.com/event-catalog/daily.data.menstrual_cycle.updated Webhook event fired when Vital updates an existing menstrual cycle entry for a user in the current day's data window. # daily.data.mindfulness_minutes.created Source: https://docs.junction.com/event-catalog/daily.data.mindfulness_minutes.created Webhook event fired when Vital ingests a new mindfulness minutes time-series for a user in the current day's data window. # daily.data.mindfulness_minutes.updated Source: https://docs.junction.com/event-catalog/daily.data.mindfulness_minutes.updated Webhook event fired when Vital updates an existing mindfulness minutes time-series for a user in the current day's data window. # daily.data.note.created Source: https://docs.junction.com/event-catalog/daily.data.note.created Webhook event fired when Vital ingests a new user-recorded note for a user in the current day's data window. # daily.data.note.updated Source: https://docs.junction.com/event-catalog/daily.data.note.updated Webhook event fired when Vital updates an existing user-recorded note for a user in the current day's data window. # daily.data.peak_expiratory_flow_rate.created Source: https://docs.junction.com/event-catalog/daily.data.peak_expiratory_flow_rate.created Webhook event fired when Vital ingests a new peak expiratory flow rate time-series for a user in the current day's data window. # daily.data.peak_expiratory_flow_rate.updated Source: https://docs.junction.com/event-catalog/daily.data.peak_expiratory_flow_rate.updated Webhook event fired when Vital updates an existing peak expiratory flow rate time-series for a user in the current day's data window. # daily.data.profile.created Source: https://docs.junction.com/event-catalog/daily.data.profile.created Webhook event fired when Vital ingests a new user profile for a user in the current day's data window. # daily.data.profile.updated Source: https://docs.junction.com/event-catalog/daily.data.profile.updated Webhook event fired when Vital updates an existing user profile for a user in the current day's data window. # daily.data.respiratory_rate.created Source: https://docs.junction.com/event-catalog/daily.data.respiratory_rate.created Webhook event fired when Vital ingests a new respiratory rate time-series for a user in the current day's data window. # daily.data.respiratory_rate.updated Source: https://docs.junction.com/event-catalog/daily.data.respiratory_rate.updated Webhook event fired when Vital updates an existing respiratory rate time-series for a user in the current day's data window. # daily.data.sleep.created Source: https://docs.junction.com/event-catalog/daily.data.sleep.created Webhook event fired when Vital ingests a new daily sleep summary for a user in the current day's data window. # daily.data.sleep.updated Source: https://docs.junction.com/event-catalog/daily.data.sleep.updated Webhook event fired when Vital updates an existing daily sleep summary for a user in the current day's data window. # daily.data.sleep_apnea_alert.created Source: https://docs.junction.com/event-catalog/daily.data.sleep_apnea_alert.created Webhook event fired when Vital ingests a new sleep apnea alert time-series for a user in the current day's data window. # daily.data.sleep_apnea_alert.updated Source: https://docs.junction.com/event-catalog/daily.data.sleep_apnea_alert.updated Webhook event fired when Vital updates an existing sleep apnea alert time-series for a user in the current day's data window. # daily.data.sleep_breathing_disturbance.created Source: https://docs.junction.com/event-catalog/daily.data.sleep_breathing_disturbance.created Webhook event fired when Vital ingests a new sleep breathing disturbance time-series for a user in the current day's data window. # daily.data.sleep_breathing_disturbance.updated Source: https://docs.junction.com/event-catalog/daily.data.sleep_breathing_disturbance.updated Webhook event fired when Vital updates an existing sleep breathing disturbance time-series for a user in the current day's data window. # daily.data.sleep_cycle.created Source: https://docs.junction.com/event-catalog/daily.data.sleep_cycle.created Webhook event fired when Vital ingests a new sleep cycle entry for a user in the current day's data window. # daily.data.sleep_cycle.updated Source: https://docs.junction.com/event-catalog/daily.data.sleep_cycle.updated Webhook event fired when Vital updates an existing sleep cycle entry for a user in the current day's data window. # daily.data.stand_duration.created Source: https://docs.junction.com/event-catalog/daily.data.stand_duration.created Webhook event fired when Vital ingests a new stand duration time-series for a user in the current day's data window. # daily.data.stand_duration.updated Source: https://docs.junction.com/event-catalog/daily.data.stand_duration.updated Webhook event fired when Vital updates an existing stand duration time-series for a user in the current day's data window. # daily.data.stand_hour.created Source: https://docs.junction.com/event-catalog/daily.data.stand_hour.created Webhook event fired when Vital ingests a new stand hour time-series for a user in the current day's data window. # daily.data.stand_hour.updated Source: https://docs.junction.com/event-catalog/daily.data.stand_hour.updated Webhook event fired when Vital updates an existing stand hour time-series for a user in the current day's data window. # daily.data.steps.created Source: https://docs.junction.com/event-catalog/daily.data.steps.created Webhook event fired when Vital ingests a new steps time-series for a user in the current day's data window. # daily.data.steps.updated Source: https://docs.junction.com/event-catalog/daily.data.steps.updated Webhook event fired when Vital updates an existing steps time-series for a user in the current day's data window. # daily.data.stress_level.created Source: https://docs.junction.com/event-catalog/daily.data.stress_level.created Webhook event fired when Vital ingests a new stress level time-series for a user in the current day's data window. # daily.data.stress_level.updated Source: https://docs.junction.com/event-catalog/daily.data.stress_level.updated Webhook event fired when Vital updates an existing stress level time-series for a user in the current day's data window. # daily.data.uv_exposure.created Source: https://docs.junction.com/event-catalog/daily.data.uv_exposure.created Webhook event fired when Vital ingests a new UV exposure time-series for a user in the current day's data window. # daily.data.uv_exposure.updated Source: https://docs.junction.com/event-catalog/daily.data.uv_exposure.updated Webhook event fired when Vital updates an existing UV exposure time-series for a user in the current day's data window. # daily.data.vo2_max.created Source: https://docs.junction.com/event-catalog/daily.data.vo2_max.created Webhook event fired when Vital ingests a new VO2 max time-series for a user in the current day's data window. # daily.data.vo2_max.updated Source: https://docs.junction.com/event-catalog/daily.data.vo2_max.updated Webhook event fired when Vital updates an existing VO2 max time-series for a user in the current day's data window. # daily.data.waist_circumference.created Source: https://docs.junction.com/event-catalog/daily.data.waist_circumference.created Webhook event fired when Vital ingests a new waist circumference time-series for a user in the current day's data window. # daily.data.waist_circumference.updated Source: https://docs.junction.com/event-catalog/daily.data.waist_circumference.updated Webhook event fired when Vital updates an existing waist circumference time-series for a user in the current day's data window. # daily.data.water.created Source: https://docs.junction.com/event-catalog/daily.data.water.created Webhook event fired when Vital ingests a new water intake time-series for a user in the current day's data window. # daily.data.water.updated Source: https://docs.junction.com/event-catalog/daily.data.water.updated Webhook event fired when Vital updates an existing water intake time-series for a user in the current day's data window. # daily.data.weight.created Source: https://docs.junction.com/event-catalog/daily.data.weight.created Webhook event fired when Vital ingests a new body weight measurement for a user in the current day's data window. # daily.data.weight.updated Source: https://docs.junction.com/event-catalog/daily.data.weight.updated Webhook event fired when Vital updates an existing body weight measurement for a user in the current day's data window. # daily.data.wheelchair_push.created Source: https://docs.junction.com/event-catalog/daily.data.wheelchair_push.created Webhook event fired when Vital ingests a new wheelchair push time-series for a user in the current day's data window. # daily.data.wheelchair_push.updated Source: https://docs.junction.com/event-catalog/daily.data.wheelchair_push.updated Webhook event fired when Vital updates an existing wheelchair push time-series for a user in the current day's data window. # daily.data.workout_distance.created Source: https://docs.junction.com/event-catalog/daily.data.workout_distance.created Webhook event fired when Vital ingests a new workout distance time-series for a user in the current day's data window. # daily.data.workout_distance.updated Source: https://docs.junction.com/event-catalog/daily.data.workout_distance.updated Webhook event fired when Vital updates an existing workout distance time-series for a user in the current day's data window. # daily.data.workout_duration.created Source: https://docs.junction.com/event-catalog/daily.data.workout_duration.created Webhook event fired when Vital ingests a new workout duration time-series for a user in the current day's data window. # daily.data.workout_duration.updated Source: https://docs.junction.com/event-catalog/daily.data.workout_duration.updated Webhook event fired when Vital updates an existing workout duration time-series for a user in the current day's data window. # daily.data.workout_stream.created Source: https://docs.junction.com/event-catalog/daily.data.workout_stream.created Webhook event fired when Vital ingests a new workout stream sample for a user in the current day's data window. # daily.data.workout_stream.updated Source: https://docs.junction.com/event-catalog/daily.data.workout_stream.updated Webhook event fired when Vital updates an existing workout stream sample for a user in the current day's data window. # daily.data.workout_swimming_stroke.created Source: https://docs.junction.com/event-catalog/daily.data.workout_swimming_stroke.created Webhook event fired when Vital ingests a new workout swimming stroke time-series for a user in the current day's data window. # daily.data.workout_swimming_stroke.updated Source: https://docs.junction.com/event-catalog/daily.data.workout_swimming_stroke.updated Webhook event fired when Vital updates an existing workout swimming stroke time-series for a user in the current day's data window. # daily.data.workouts.created Source: https://docs.junction.com/event-catalog/daily.data.workouts.created Webhook event fired when Vital ingests a new workout summary for a user in the current day's data window. # daily.data.workouts.updated Source: https://docs.junction.com/event-catalog/daily.data.workouts.updated Webhook event fired when Vital updates an existing workout summary for a user in the current day's data window. # historical.data.activity.created Source: https://docs.junction.com/event-catalog/historical.data.activity.created Webhook event fired when Vital completes the historical backfill of daily activity summary data for a newly connected user. # historical.data.afib_burden.created Source: https://docs.junction.com/event-catalog/historical.data.afib_burden.created Webhook event fired when Vital completes the historical backfill of atrial fibrillation (AFib) burden data for a newly connected user. # historical.data.basal_body_temperature.created Source: https://docs.junction.com/event-catalog/historical.data.basal_body_temperature.created Webhook event fired when Vital completes the historical backfill of basal body temperature time-series data for a newly connected user. # historical.data.blood_oxygen.created Source: https://docs.junction.com/event-catalog/historical.data.blood_oxygen.created Webhook event fired when Vital completes the historical backfill of blood oxygen saturation (SpO2) time-series data for a newly connected user. # historical.data.blood_pressure.created Source: https://docs.junction.com/event-catalog/historical.data.blood_pressure.created Webhook event fired when Vital completes the historical backfill of blood pressure time-series data for a newly connected user. # historical.data.body.created Source: https://docs.junction.com/event-catalog/historical.data.body.created Webhook event fired when Vital completes the historical backfill of daily body summary data for a newly connected user. # historical.data.body_mass_index.created Source: https://docs.junction.com/event-catalog/historical.data.body_mass_index.created Webhook event fired when Vital completes the historical backfill of body mass index (BMI) time-series data for a newly connected user. # historical.data.body_temperature.created Source: https://docs.junction.com/event-catalog/historical.data.body_temperature.created Webhook event fired when Vital completes the historical backfill of body temperature time-series data for a newly connected user. # historical.data.body_temperature_delta.created Source: https://docs.junction.com/event-catalog/historical.data.body_temperature_delta.created Webhook event fired when Vital completes the historical backfill of body temperature delta time-series data for a newly connected user. # historical.data.caffeine.created Source: https://docs.junction.com/event-catalog/historical.data.caffeine.created Webhook event fired when Vital completes the historical backfill of caffeine intake time-series data for a newly connected user. # historical.data.calories_active.created Source: https://docs.junction.com/event-catalog/historical.data.calories_active.created Webhook event fired when Vital completes the historical backfill of active calories time-series data for a newly connected user. # historical.data.calories_basal.created Source: https://docs.junction.com/event-catalog/historical.data.calories_basal.created Webhook event fired when Vital completes the historical backfill of basal calories time-series data for a newly connected user. # historical.data.carbohydrates.created Source: https://docs.junction.com/event-catalog/historical.data.carbohydrates.created Webhook event fired when Vital completes the historical backfill of carbohydrate intake time-series data for a newly connected user. # historical.data.daylight_exposure.created Source: https://docs.junction.com/event-catalog/historical.data.daylight_exposure.created Webhook event fired when Vital completes the historical backfill of daylight exposure time-series data for a newly connected user. # historical.data.distance.created Source: https://docs.junction.com/event-catalog/historical.data.distance.created Webhook event fired when Vital completes the historical backfill of distance time-series data for a newly connected user. # historical.data.electrocardiogram.created Source: https://docs.junction.com/event-catalog/historical.data.electrocardiogram.created Webhook event fired when Vital completes the historical backfill of electrocardiogram (ECG) reading data for a newly connected user. # historical.data.electrocardiogram_voltage.created Source: https://docs.junction.com/event-catalog/historical.data.electrocardiogram_voltage.created Webhook event fired when Vital completes the historical backfill of electrocardiogram (ECG) voltage time-series data for a newly connected user. # historical.data.fall.created Source: https://docs.junction.com/event-catalog/historical.data.fall.created Webhook event fired when Vital completes the historical backfill of fall detection time-series data for a newly connected user. # historical.data.fat.created Source: https://docs.junction.com/event-catalog/historical.data.fat.created Webhook event fired when Vital completes the historical backfill of dietary fat intake time-series data for a newly connected user. # historical.data.floors_climbed.created Source: https://docs.junction.com/event-catalog/historical.data.floors_climbed.created Webhook event fired when Vital completes the historical backfill of floors climbed time-series data for a newly connected user. # historical.data.forced_expiratory_volume_1.created Source: https://docs.junction.com/event-catalog/historical.data.forced_expiratory_volume_1.created Webhook event fired when Vital completes the historical backfill of forced expiratory volume in one second (FEV1) time-series data for a newly connected user. # historical.data.forced_vital_capacity.created Source: https://docs.junction.com/event-catalog/historical.data.forced_vital_capacity.created Webhook event fired when Vital completes the historical backfill of forced vital capacity (FVC) time-series data for a newly connected user. # historical.data.glucose.created Source: https://docs.junction.com/event-catalog/historical.data.glucose.created Webhook event fired when Vital completes the historical backfill of blood glucose time-series data for a newly connected user. # historical.data.handwashing.created Source: https://docs.junction.com/event-catalog/historical.data.handwashing.created Webhook event fired when Vital completes the historical backfill of handwashing events time-series data for a newly connected user. # historical.data.heart_rate_alert.created Source: https://docs.junction.com/event-catalog/historical.data.heart_rate_alert.created Webhook event fired when Vital completes the historical backfill of heart rate alert time-series data for a newly connected user. # historical.data.heart_rate_recovery_one_minute.created Source: https://docs.junction.com/event-catalog/historical.data.heart_rate_recovery_one_minute.created Webhook event fired when Vital completes the historical backfill of one-minute heart rate recovery time-series data for a newly connected user. # historical.data.heartrate.created Source: https://docs.junction.com/event-catalog/historical.data.heartrate.created Webhook event fired when Vital completes the historical backfill of heart rate time-series data for a newly connected user. # historical.data.hrv.created Source: https://docs.junction.com/event-catalog/historical.data.hrv.created Webhook event fired when Vital completes the historical backfill of heart rate variability (HRV) time-series data for a newly connected user. # historical.data.inhaler_usage.created Source: https://docs.junction.com/event-catalog/historical.data.inhaler_usage.created Webhook event fired when Vital completes the historical backfill of inhaler usage time-series data for a newly connected user. # historical.data.insulin_injection.created Source: https://docs.junction.com/event-catalog/historical.data.insulin_injection.created Webhook event fired when Vital completes the historical backfill of insulin injection time-series data for a newly connected user. # historical.data.lean_body_mass.created Source: https://docs.junction.com/event-catalog/historical.data.lean_body_mass.created Webhook event fired when Vital completes the historical backfill of lean body mass time-series data for a newly connected user. # historical.data.meal.created Source: https://docs.junction.com/event-catalog/historical.data.meal.created Webhook event fired when Vital completes the historical backfill of meal entry data for a newly connected user. # historical.data.menstrual_cycle.created Source: https://docs.junction.com/event-catalog/historical.data.menstrual_cycle.created Webhook event fired when Vital completes the historical backfill of menstrual cycle entry data for a newly connected user. # historical.data.mindfulness_minutes.created Source: https://docs.junction.com/event-catalog/historical.data.mindfulness_minutes.created Webhook event fired when Vital completes the historical backfill of mindfulness minutes time-series data for a newly connected user. # historical.data.note.created Source: https://docs.junction.com/event-catalog/historical.data.note.created Webhook event fired when Vital completes the historical backfill of user-recorded note data for a newly connected user. # historical.data.peak_expiratory_flow_rate.created Source: https://docs.junction.com/event-catalog/historical.data.peak_expiratory_flow_rate.created Webhook event fired when Vital completes the historical backfill of peak expiratory flow rate time-series data for a newly connected user. # historical.data.profile.created Source: https://docs.junction.com/event-catalog/historical.data.profile.created Webhook event fired when Vital completes the historical backfill of user profile data for a newly connected user. # historical.data.respiratory_rate.created Source: https://docs.junction.com/event-catalog/historical.data.respiratory_rate.created Webhook event fired when Vital completes the historical backfill of respiratory rate time-series data for a newly connected user. # historical.data.sleep.created Source: https://docs.junction.com/event-catalog/historical.data.sleep.created Webhook event fired when Vital completes the historical backfill of daily sleep summary data for a newly connected user. # historical.data.sleep_apnea_alert.created Source: https://docs.junction.com/event-catalog/historical.data.sleep_apnea_alert.created Webhook event fired when Vital completes the historical backfill of sleep apnea alert time-series data for a newly connected user. # historical.data.sleep_breathing_disturbance.created Source: https://docs.junction.com/event-catalog/historical.data.sleep_breathing_disturbance.created Webhook event fired when Vital completes the historical backfill of sleep breathing disturbance time-series data for a newly connected user. # historical.data.sleep_cycle.created Source: https://docs.junction.com/event-catalog/historical.data.sleep_cycle.created Webhook event fired when Vital completes the historical backfill of sleep cycle entry data for a newly connected user. # historical.data.stand_duration.created Source: https://docs.junction.com/event-catalog/historical.data.stand_duration.created Webhook event fired when Vital completes the historical backfill of stand duration time-series data for a newly connected user. # historical.data.stand_hour.created Source: https://docs.junction.com/event-catalog/historical.data.stand_hour.created Webhook event fired when Vital completes the historical backfill of stand hour time-series data for a newly connected user. # historical.data.steps.created Source: https://docs.junction.com/event-catalog/historical.data.steps.created Webhook event fired when Vital completes the historical backfill of steps time-series data for a newly connected user. # historical.data.stress_level.created Source: https://docs.junction.com/event-catalog/historical.data.stress_level.created Webhook event fired when Vital completes the historical backfill of stress level time-series data for a newly connected user. # historical.data.uv_exposure.created Source: https://docs.junction.com/event-catalog/historical.data.uv_exposure.created Webhook event fired when Vital completes the historical backfill of UV exposure time-series data for a newly connected user. # historical.data.vo2_max.created Source: https://docs.junction.com/event-catalog/historical.data.vo2_max.created Webhook event fired when Vital completes the historical backfill of VO2 max time-series data for a newly connected user. # historical.data.waist_circumference.created Source: https://docs.junction.com/event-catalog/historical.data.waist_circumference.created Webhook event fired when Vital completes the historical backfill of waist circumference time-series data for a newly connected user. # historical.data.water.created Source: https://docs.junction.com/event-catalog/historical.data.water.created Webhook event fired when Vital completes the historical backfill of water intake time-series data for a newly connected user. # historical.data.weight.created Source: https://docs.junction.com/event-catalog/historical.data.weight.created Webhook event fired when Vital completes the historical backfill of body weight measurement data for a newly connected user. # historical.data.wheelchair_push.created Source: https://docs.junction.com/event-catalog/historical.data.wheelchair_push.created Webhook event fired when Vital completes the historical backfill of wheelchair push time-series data for a newly connected user. # historical.data.workout_distance.created Source: https://docs.junction.com/event-catalog/historical.data.workout_distance.created Webhook event fired when Vital completes the historical backfill of workout distance time-series data for a newly connected user. # historical.data.workout_duration.created Source: https://docs.junction.com/event-catalog/historical.data.workout_duration.created Webhook event fired when Vital completes the historical backfill of workout duration time-series data for a newly connected user. # historical.data.workout_stream.created Source: https://docs.junction.com/event-catalog/historical.data.workout_stream.created Webhook event fired when Vital completes the historical backfill of workout stream sample data for a newly connected user. # historical.data.workout_swimming_stroke.created Source: https://docs.junction.com/event-catalog/historical.data.workout_swimming_stroke.created Webhook event fired when Vital completes the historical backfill of workout swimming stroke time-series data for a newly connected user. # historical.data.workouts.created Source: https://docs.junction.com/event-catalog/historical.data.workouts.created Webhook event fired when Vital completes the historical backfill of workout summary data for a newly connected user. # lab_report.parsing_job.created Source: https://docs.junction.com/event-catalog/lab_report.parsing_job.created Fired when a lab report parsing job starts extracting structured results from an uploaded PDF report. # lab_report.parsing_job.updated Source: https://docs.junction.com/event-catalog/lab_report.parsing_job.updated Fired when a lab report parsing job updates its status or completes structured extraction from a report. # labtest.appointment.created Source: https://docs.junction.com/event-catalog/labtest.appointment.created Fired when a lab test appointment is booked for a user, including phlebotomy and at-home visit details. # labtest.appointment.updated Source: https://docs.junction.com/event-catalog/labtest.appointment.updated Fired when a lab test appointment changes status, is rescheduled, cancelled, or has its details updated. # labtest.match_review.created Source: https://docs.junction.com/event-catalog/labtest.match_review.created Fired when a new lab result match review is created for a user, flagging results that need manual reconciliation. # labtest.match_review.updated Source: https://docs.junction.com/event-catalog/labtest.match_review.updated Fired when a lab result match review is updated after manual reconciliation of user identity or results. # labtest.order.created Source: https://docs.junction.com/event-catalog/labtest.order.created Fired when a lab test order is created for a user, including test panel and shipping or appointment details. # labtest.order.updated Source: https://docs.junction.com/event-catalog/labtest.order.updated Fired when a lab test order changes status, such as when a sample is collected, received, or results are ready. # labtest.result.critical Source: https://docs.junction.com/event-catalog/labtest.result.critical Fired when a lab test returns a critical result value that falls outside safe clinical reference ranges. # provider.connection.created Source: https://docs.junction.com/event-catalog/provider.connection.created Fired when a user successfully connects a wearable or health data provider account to your Vital application. # provider.connection.error Source: https://docs.junction.com/event-catalog/provider.connection.error Fired when a wearable or health data provider connection encounters an authentication or sync error and needs attention. # provider.device.created Source: https://docs.junction.com/event-catalog/provider.device.created Fired when a new device is registered under a user's wearable or health data provider connection. # provider.device.updated Source: https://docs.junction.com/event-catalog/provider.device.updated Fired when a registered device under a user's wearable or health data provider connection has its details updated. # Getting Support Source: https://docs.junction.com/home/getting-support Contact Junction support via email or Slack, and learn what information to include when reporting issues for faster resolution. ## Support channels When you encounter an issue which you cannot figure out, or an unexpected API error, you are welcome to get in touch with Junction support through these channels: * Email Support ([help@junction.com](mailto:help@junction.com)) * Junction Slack community * Your dedicated Slack support channel (for Scale plan customers) We appreciate as much context as possible when you raise an issue. This helps us understand your issue, enabling a quicker investigation turnaround. ## I have an issue with... ### Anything in general | Item | Remarks | | ------------------------ | ------------------------------------------ | | Your Junction Team ID | - | | Your Junction region | US or EU | | The Junction User ID | ...if the issue occurs on a specific user. | | The Junction environment | Sandbox, Production or both | ### Junction Mobile SDK | Item | Remarks | | --------------------- | --------------------------------------- | | Junction SDK Platform | Native, React Native, Flutter | | Junction SDK Version | - | | Device OS | Android or iOS | | Device OS Version | - | | Auth Scheme | Junction Sign-In Token, or Team API Key | ### A Junction API endpoint If your system has distributed tracing configured that is compliant with W3C Trace Context (e.g., OpenTelemetry tracing), you can provide us with the Trace ID of the operation **in your system**. A Trace ID looks like this: `0af7651916cd43dd8448eb211c80319c`. This helps us locate the concerned API request and related contexts. This works only if your distributed tracing setup would propagate Trace Context to your outbound HTTP requests β€” more specifically injecting the standards-based `traceparent` header into the requests. ### A wearables provider connection Before reporting an issue, we encourage you to try out the following steps: The [Get User Connections](/api-reference/user/get-users-connected-providers) endpoint reports the resource availability of all the connections. More specifically, it tells you: 1. What resources are available for a given user connection. 2. Why each individual resource is available or unavailable, in terms of provider API access scopes. If you are having issues with historical data specifically, the [Historical Pull Introspection](/api-reference/data/introspection/historical-pulls) endpoint provides a track record of historical pulls of all your user connections. If you have trouble with data availability in general, the [User Resource Introspection](/api-reference/data/introspection/user-resources) endpoint is a live data ingestion record of all your user connections. This is inclusive of all historical data covered by the Historical Pull Introspection endpoint. If you are not able to diagnose your issue using these tools, feel free to contact Junction support for further assistance. # Libraries Source: https://docs.junction.com/home/libraries Browse all Junction client libraries and SDKs, including typed API bindings for Java, Go, TypeScript, and Python, plus mobile SDKs for iOS and Android. We have created a few libraries to help you integrate with the Junction API. We'll continue to add support for more libraries as we add more devices. Email [support@junction.com](mailto:support@junction.com) for specific library support. ### Typed Bindings of Junction API These typed bindings track the Junction API OpenAPI Schema. | | | | -------------------------------------------------------------------- | ------------------------------ | | [junction-java](https://github.com/junction-api/junction-java) | Junction API Java client | | [junction-go](https://github.com/junction-api/junction-go) | Junction API Go client | | [@junction-api/sdk](https://www.npmjs.com/package/@junction-api/sdk) | Junction API TypeScript client | | [junction-api-sdk](https://pypi.org/project/junction-api-sdk) | Junction API Python client | ### Mobile SDK | | | | -------------------------------------------------------------------- | ----------------------------------- | | [vital-ios](https://github.com/tryVital/vital-ios) | Junction iOS Client | | [vital-android](https://github.com/tryVital/vital-android) | Junction Android Client | | [vital-flutter](https://github.com/tryVital/vital-flutter) | Junction Flutter Client | | [vital-react-native](https://github.com/tryVital/vital-react-native) | Junction React Native Client | | [vital-connect](https://github.com/tryVital/vital-connect-rn) | Whitelabel App using Junction's API | ### Web SDK | | | | ---------------------------------------------------------------- | ----------------------------------- | | [vital-link](https://www.npmjs.com/package/@tryvital/vital-link) | React Library for initializing Link | # Quickstart Source: https://docs.junction.com/home/quickstart Get started with the Junction API by setting up API keys, connecting a wearable device, and fetching your first health data in minutes. ## 1. API keys Let's test out running Junction locally by cloning the [Quickstart app](https://github.com/tryVital/quickstart). To create a team and get your API keys, you first need to sign up for a Junction account in the [Dashboard](https://app.junction.com). Once registered, you can create a team by hovering over your username at the bottom of the Dashboard sidebar. A team is associated with a region (either `EU` or `US`). The region dictates where data is stored. You can learn more at [regions](/api-details/regions). To create your API keys, go to the configuration section of the Dashboard. For each region, you'll have access to two environments: Sandbox and Production. We'll start in the Sandbox environment, so create a new Sandbox API key. If you get stuck at any point in the Quickstart, help is just a click away! Join our Slack channel or send us a message to [support@junction.com](mailto:support@junction.com). | Environment | | | | ------------ | ------------------------------------------- | --------------------------- | | `sandbox` | Testing, connect up to 50 live users | api.sandbox.us.junction.com | | `production` | Live environment to use with real customers | api.us.junction.com | ## 2. Running Quickstart locally Once you have your API keys, it's time to run the Junction Quickstart locally! The instructions below will guide you through the process of cloning the [Quickstart repository](https://github.com/tryVital/quickstart), customizing the `.env` file with your own Junction `API_KEY` and finally, building and running the app. ```bash 1. Clone quickstart and run locally theme={null} # Note: If on Windows, run # git clone -c core.symlinks=true https://github.com/tryVital/quickstart # instead to ensure correct symlink behavior git clone https://github.com/tryVital/quickstart.git # Create .env, then fill # out VITAL_API_KEY, VITAL_REGION (eu, us) and VITAL_ENV in .env touch .env # Note: must use python 3 # For virtualenv users: # virtualenv venv # source venv/bin/activate poetry install # Start the backend app cd backend/python source ./start.sh ``` Open a new shell and start the frontend app. Your app will be running at `http://localhost:3000`. ```bash 2. Run quickstart frontend theme={null} # Install dependencies cd quickstart/frontend npm install # Open .env.local, then fill # out NEXT_PUBLIC_VITAL_API_KEY, NEXT_PUBLIC_VITAL_ENV and NEXT_PUBLIC_VITAL_REGION # Start the frontend app npm run dev # Go to http://localhost:3000 ``` ## 3. Creating your first User When retrieving data or connecting devices, Junction will require a `user_id` as input. A `user_id` is a unique representation that we hold for a user. It allows you to fetch data for that user. To create a user, you need to pass a unique id (`client_user_id`). This represents the user in your system. Our recommendation is to store the Junction `user_id` in your db against the user row. Personally identifiable information (PII), such as an email address or phone number, should not be used as input for the `client_user_id` parameter. Enter a new `client_user_id` and tap Create: quickstart This can also be achieved via the API as follows. ```bash Creating a Junction user (bash) theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/ \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-api-key: ' \ --data '{"client_user_id":""}' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.create({ clientUserId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.create(client_user_id="") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.UserCreateBody; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().create( UserCreateBody.builder() .clientUserId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Create(context.TODO(), &junction.UserCreateBody{ ClientUserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```swift Swift theme={null} let user = try await VitalClient.shared.user.create(clientUserId) ``` ## 4. Connecting a source A source, at Junction, is a medical device, wearable, or lab. It is a source of information for health data. To connect a source, tap the connect button. This will launch the Junction Link Widget for that user. Once you have entered your credentials and moved to the next screen, you have connected your first source! You can now make API calls to retrieve data for that Source. ### How it works As you might have noticed, you use both a server and a client-side component to access the Junction APIs. A more detailed explanation of how linking works can be found in [link flow](/wearables/connecting-providers/link_flow). The first step is to create a new `link_token` by making a `/link/token` request and passing in the required configuration. This `link_token` is a short-lived, one-time use token that authenticates your app with Junction Link, our frontend module. ```python Generating a Link Token theme={null} # TEST BACKEND IMPLEMENTATION from junction import Junction from junction.environment import JunctionEnvironment from fastapi import FastAPI from starlette.middleware.cors import CORSMiddleware client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, timeout=30, ) app = FastAPI() app.add_middleware( # type: ignore CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/token/{user_key}") def get_token(user_key: str): return client.link.token(user_id=user_key) ``` Once you have a `link_token`, you can use it to initialize `Link`. `Link` is a drop-in client-side module available for web, iOS, and Android that handles the authentication process. The Quickstart uses `Link` on the web, which is a pure JavaScript integration that you trigger via your own client-side code. ```javascript Generating a Link Token theme={null} import { Button } from "@chakra-ui/react"; import { useState, useCallback } from "react"; import { useVitalLink } from "@tryvital/vital-link"; export const LinkButton: React.FC<{ userID: string | null }> = ({ userID }) => { const [isLoading, setLoading] = useState(false); const onSuccess = useCallback((metadata) => { // Device is now connected. console.log("onSuccess", metadata); }, []); const onExit = useCallback((metadata) => { // User has quit the link flow. console.log("onExit", metadata); }, []); const onError = useCallback((metadata) => { // Error encountered in connecting device. console.log("onError", metadata); }, []); const config = { onSuccess, onExit, onError, env: "sandbox", region: "us", }; const { open, ready, error } = useVitalLink(config); const handleVitalOpen = async () => { setLoading(true); const token = await getTokenFromBackend(userID); open(token.link_token); setLoading(false); }; return ( ); }; ``` This is what your users see to connect their medical devices or wearables: Link specific ## 5. Making your first API request We can now explore what happens when you press the analyze button in the Quickstart to make an API call. As an example, we'll look at the Quickstart's call to `/summary/sleep`, which retrieves sleep summary data for a user. The request is simple and requires the Junction `user_id`, `start_date` and `end_date`. **Getting user sleep data** ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.sleep.get( "", start_date="2021-01-01", end_date="2021-01-02", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.sleep.get({ userId: "", startDate: "2021-01-01", endDate: "2021-01-02", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.sleep.requests.GetSleepRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.sleep().get( "", GetSleepRequest.builder() .startDate("2021-01-01") .endDate("2021-01-02") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) endDate := "2021-01-02" response, err := c.Sleep.Get(context.TODO(), &junction.GetSleepRequest{ UserId: "", StartDate: "2021-01-01", EndDate: &endDate, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```swift Swift theme={null} let sleepData = try await VitalClient.shared.summary.sleep(userId, startDate, endDate) ``` ## 6. SDKs and Libraries We offer different SDKs so you can start building your app right away: | | | | -------------------------------------------------------------------- | ------------------------------------------------------- | | [junction-api-sdk](https://pypi.org/project/junction-api-sdk) | Python library for calling Junction API on your backend | | [vital-link](https://www.npmjs.com/package/@tryvital/vital-link) | React Library for initializing Link | | [@junction-api/sdk](https://www.npmjs.com/package/@junction-api/sdk) | Junction TypeScript Client | | [vital-ios](https://github.com/tryVital/vital-ios) | Junction iOS Client | | [junction-java](https://github.com/junction-api/junction-java) | Junction Java Client | | [junction-go](https://github.com/junction-api/junction-go) | Junction Go Client | You can also download our [API collection](https://www.postman.com/collections/35339909-b0d080b7-3870-4aa8-a68b-a675f93a0533), or install Postman first and click the button below. [![Run in Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/35339909-b0d080b7-3870-4aa8-a68b-a675f93a0533?action=collection%2Ffork\&source=rip_markdown\&collection-url=entityId%3D35339909-b0d080b7-3870-4aa8-a68b-a675f93a0533%26entityType%3Dcollection%26workspaceId%3Ddd82502b-0c9d-4fe4-9760-73a54bc2b8bf) ## Next Steps Congratulations, you have completed the Junction Quickstart! There are a few directions you can go in now: A client-side component your users will interact with in order to link their accounts with Junction. It allows you to access their accounts via the Junction API. Native toolkits to integrate Junction into iOS, Android, and Flutter Webhooks are a way to receive data from Junction. We frequently poll to receive data from the various providers. # Junction Source: https://docs.junction.com/home/welcome Integrate 300+ wearables, streamline lab operations, and build your own lab testing experience spanning all 50 states – with a single API. Access a nationwide lab network. In-person, at-home, or hybrid methods to maximize completion rates. Automatically transforms raw activity and biometric data from 300+ connected devices into structured, aggregated datasets that update as new data arrives. Connect to 300+ devices, and receive data in Junction standardized schemas. User management, Device connection and data access, Lab Testing orders and results, Junction Sense Query and Data. Programmatically manage all Junction regional and global resources in your organization, including Junction Sense Continuous Queries. ## Popular Topics The Quickstart walk-through gives you an overview of how to integrate with Junction. By the end of this guide, you'll have a working app with both backend and frontend. Learn how to integrate with Apple HealthKit through Junction Mobile SDKs, available in Native iOS, React Native and Flutter. Learn how to integrate with Android Health Connect through Junction Mobile SDKs, available in Native Android, React Native and Flutter. Junction Link enables your users to connect their account with their wearable data providers. Learn how to integrate the Link Widget for a no-fuss starter integration. Learn how to use the Junction Link API to build your own Link Widget. Learn about timestamp and time zone handling of wearable device data. Junction can push wearable device data as webhook events to you as soon as they are discovered. Learn about the delivery stages, event structure as well as the advanced ETL Pipeline options for high volume needs. Learn how to use Demo Connections β€” which emit synthetic data mimicking selected providers β€” as an alternative way to test your Junction integration. # Communications Source: https://docs.junction.com/lab/at-home-phlebotomy/communications Configure SMS and email notifications sent to patients during each status change in the at-home phlebotomy order lifecycle. Communication for patients is done via email or SMS for At-Home Phlebotomy orders. Customers have the following options when setting this up: * `Default` - Email and SMS communications are enabled. * `SMS Only` - Only SMS communication is enabled. * `Disable` - All communications from Junction are disabled. Each option has a different set of content and status changes, depending on what triggered them. You can enable or disable SMS and Email communications individually through the [**Junction Dashboard**](https://app.junction.com/), under the Team Settings section. ## Default Communications ### SMS Messages A table of the **Order Status** and **default SMS** is provided below: | Order Status | Default Message | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `requisition_created` | *"Hey **patient\_first\_name**, it's time to book your at-home phlebotomy draw. You can book a slot using the following link **booking\_link**."* | | `appointment_scheduled` | *"Your appointment with the phlebotomist has been booked at **date**! You can reschedule or cancel using the following link **booking\_link**."* | | `appointment_cancelled` | *"Hey, your at-home-phlebotomy appointment at **date** for the **team\_name** has been cancelled. You can rebook using the following link **booking\_link**."* | | `draw_completed` | *"Your at-home phlebotomy draw is complete! We're delivering your sample to the lab for processing."* | | `completed` | *"The lab has finished processing your blood sample, your results should be ready soon :)"* | | `cancelled` | *"Hey, your order for the **team\_name** at-home-phlebotomy appointment has been cancelled. If this is by accident, please contact support."* | SMS Texts are customizable, and can be enabled or disabled individually. ### Emails For emails, the following table describes what information each email contains for each Order Status: | Order Status | Email Content Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `requisition_created` | An email with the booking link for **Junction Booking Widget** will be sent to the patient. | | `appointment_scheduled` | An email confirming the appointment date and time will be sent to the patient, with the possibility of rescheduling or cancelling the appointment. | | `appointment_cancelled` | An email confirming the cancellation of the appointment is sent, providing the possibility of scheduling a new appointment. | Emails can be white-labeled and sent from your own domain. ## Scheduling Appointments Before A Requisition Has Been Created This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. If the ability to [`schedule appointments before a requisition has been created`](/lab/at-home-phlebotomy/order-appointment-lifecycle#scheduling-appointments-before-a-requisition-has-been-created) is enabled for your team, all appointment-related messages will be triggered by the **appointment** status, not the **order** status. All non-appointment-related messages will be triggered by the **order** status, e.g., `requisition_created`, `draw_completed`, etc. (see above section). ### SMS Messages A table of the **Appointment Status** and **default SMS** is provided below: | Appointment Status | Default Message | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `confirmed` | *"Your appointment with the phlebotomist has been booked at **date**! You can reschedule or cancel using the following link **booking\_link**."* | | `cancelled` | *"Hey, your at-home-phlebotomy appointment at **date** for the **team\_name** has been cancelled. You can rebook using the following link **booking\_link**."* | ### Emails For emails, the following table describes what information each email contains for each Appointment Status: | Appointment Status | Email Content Description | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `confirmed` | An email confirming the appointment date and time will be sent to the patient, with the possibility of rescheduling or cancelling the appointment. | | `cancelled` | An email confirming the cancellation of the appointment is sent, providing the possibility of scheduling a new appointment. | ## Disable Communications In this case, no communications will be sent from Junction. You have the ability to produce completely customized communications using the [`Webhook events`](/lab/at-home-phlebotomy/webhooks) described previously. # Order and Appointment Lifecycle Source: https://docs.junction.com/lab/at-home-phlebotomy/order-appointment-lifecycle Reference for all order and appointment lifecycle statuses in the at-home phlebotomy flow, from order creation through results delivery. The **At-Home Phlebotomy** orders are composed of two different lifecycles, the **Order** lifecycle and the **Appointment** lifecycle, detailed in the following sections. ## Order Lifecycle As discussed in [`Lab Test Lifecycle - Statuses`](/lab/workflow/lab-test-lifecycle#statuses), each lab testing modality has the following format: `[HIGH-LEVEL STATUS].[TEST MODALITY].[LOW-LEVEL STATUS]` For each modality, there can be multiple **low-level statuses**, for **At-Home Phlebotomy** the possible low-level statuses are: * `ordered`: Junction received the order, stored it into our system, and started processing it asynchronously. * `requisition_created`: An order requisition form was validated and created with the partner laboratory, making the order available to be carried out. * `requisition_bypassed`: An order requisition form wasn't created when the order was placed with us because it already existed. * `appointment_pending`: An appointment was placed in Junction's system for the order, but doesn't have a scheduled date. * `appointment_scheduled`: An appointment was scheduled or rescheduled for the order. * `draw_completed`: The phlebotomy appointment was completed and the blood was drawn successfully. * `appointment_cancelled`: The appointment was cancelled by either the patient, Junction, or you. * `partial_results`: The laboratory has started making partial results available. * `completed`: The laboratory processed the blood sample and final results are available. * `sample_error`: The collected sample was unprocessable by the lab. * `cancelled`: The order was cancelled by either the patient, Junction, or you. The Finite State Machine that defines the possible transitions for the low-level statuses described above is illustrated in the following diagram.
In **sandbox**, there is no async transition from the `ordered` state to the `requisition_created` state. This must be **manually triggered** via the **Junction Dashboard**. ## Appointment Lifecycle The appointment lifecycle is separate from the order lifecycle, and it corresponds to a single appointment. The possible statuses are defined as follows: * `pending`: An appointment was placed in the system, and is pending updates from the phlebotomy service. * `reserved`: The time slot has been reserved for the appointment, but the scheduling confirmation is waiting on the creation of the order requisition. * `scheduled`: The appointment has been scheduled or rescheduled. * `in-progress`: The phlebotomist is on their way to the patient's address. * `cancelled`: The appointment was cancelled by either the patient, Junction, or you. * `completed`: The phlebotomy appointment was completed and the blood was drawn successfully. The Finite State Machine that defines the possible transitions for the appointment statuses described above is illustrated in the following diagram. The events are related to a single appointment. An order can have multiple existing appointments in Junction's system, although only one appointment will be considered active and returned when using the [GET Appointment endpoint](/api-reference/lab-testing-at-home-phlebotomy/get-appointment). ## Scheduling Appointments Before A Requisition Has Been Created This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. When this feature is enabled on your Team, you can create an At-Home Phlebotomy appointment even before the requisition has been created for the corresponding Order (i.e., reaching the `requisition_created` status). This allows you to build an experience that can order the lab test *and* book an appointment consecutively, without having to wait on the asynchronous requisition creation process that may take an indeterminate amount of time. ### API Journey You create an Appointment for an Order which does not yet have a requisition. For an [Appointment Ready Tier](/lab/at-home-phlebotomy/service-tiers) service, the Appointment starts with the `pending` status and immediately moves to the `reserved` status. For an [Appointment Request Tier](/lab/at-home-phlebotomy/service-tiers) service, the Appointment starts with the `pending` status. Once the service has penciled in the time slot, the Appointment moves to the `reserved` status β€” if the order requisition still has not yet been created by then. If the order requisition has been created on or before the time slot confirmation, the Appointment moves directly to the `confirmed` status. The `reserved` status would be skipped. The requisition is being created asynchronously. The requisition has now been created. For all types of Appointments: 1. The Order will move through the `requisition_created` and `appointment_pending` Order statuses in quick succession. You will receive two `labtest.order.updated` events, one each for the two status transitions. For all [Appointment Ready Tier](/lab/at-home-phlebotomy/service-tiers) Appointments and all the penciled [Appointment Request Tier](/lab/at-home-phlebotomy/service-tiers) Appointments: 1. The Order will move further to the `appointment_scheduled` Order status in quick succession. 2. The Appointment will move to the `confirmed` status automatically, which corresponds to the `scheduled` appointment event. You will additionally receive a `labtest.order.updated` event and a `labtest.appointment.updated` event for the status transition. ## Cancelling An Appointment If an Appointment is cancelled **before** a requisition has been created: * The Appointment will move to the `cancelled` status; and * There is no change to the Order, which will remain in the `ordered` status. If an Appointment is cancelled **after** a requisition has been created: 1. The Appointment will move to the `cancelled` status; and 2. The Order will move from the `appointment_pending` or `appointment_scheduled` status to the `appointment_cancelled` status. ### Auto-cancellation of appointments without requisition In cases where appointments can be scheduled before a requisition has been created, the appointment will be automatically cancelled by Junction if the following happens: 1. More than 8 hours have passed since the order was created, and no requisition has been received. 2. There are fewer than 2 hours until the appointment start time, and no requisition has been received. The 8-hour auto-cancellation rule does not apply to [scheduled orders](/lab/workflow/scheduled-orders#scheduled-orders). Scheduled orders are fulfilled on their `activate_by` date, so Junction does not cancel their appointments based solely on the fact that more than 8 hours have passed since order creation without a requisition. When booking an appointment with Getlabs, we strongly recommend that the appointment is booked at least 48 hours in advance to allow sufficient time for the requisition to be received and sent to the phlebotomist. Getlabs automatically reschedules appointments that do not have a requisition form around 24 hours before the appointment start time. They also inform the patient about the rescheduling, directly via SMS. Restricting the scheduling of appointments to at least 48 hours in advance allows Junction to handle the auto-cancellation of the appointment, which triggers an appointment cancelled webhook. You can then use this for patient communications, rather than relying on Getlabs to do so. # Overview Source: https://docs.junction.com/lab/at-home-phlebotomy/overview Overview of the at-home phlebotomy modality where a phlebotomist visits a patient at home to draw blood for lab testing. At-home phlebotomy tests are one of our offered modalities. This modality is focused on patients that don't want to go to a Laboratory, but instead want a phlebotomist to come to their home or office to carry out the phlebotomy draw. The phlebotomist is responsible for bringing the required equipment and tubes and then delivering those to our partner Laboratories. ## Ordering Flow overview To achieve this, a high-level overview of the process is defined as: * An order is placed in Junction's system through our Dashboard or API. * The order is added to a background queue and additional checks are made before a test requisition is created with the chosen Laboratory. * After the requisition is created, some form of communication is carried out with the patient so they can book an appointment with our phlebotomy partners. * On the day of the appointment, our partner phlebotomist will contact the patient directly to confirm that everything is correct for carrying out the appointment. * The phlebotomist goes to the appointment, draws the patient's blood and then delivers it to the Laboratory. * The Laboratory processes the patient's blood sample and generates the required results. * Junction exposes the results as soon as they are available, both as PDF and structured data via API. ## Access Notes and Appointment Notes There are two ways to provide instructions for the phlebotomist: ### Access Notes Set `access_notes` on the patient address when creating an order. These describe how to physically reach the patient's location β€” gate codes, parking instructions, entrance details, etc. Access notes are automatically forwarded to the phlebotomy provider on every booking and reschedule. ### Appointment Notes Set `appointment_notes` in the booking, request, or reschedule request body. These are per-appointment special instructions β€” for example, "Please bring photo ID" or "Patient prefers left arm". Appointment notes can be changed on each reschedule and are stored on the appointment itself. ## Constraints * Phlebotomy appointments are not supported for patients under 18 years of age. * The same patient can't have more than one active appointment with a specific **Phlebotomy provider**. * The addresses provided when fetching the appointment availability slots must be reachable by the phlebotomist and must contain a street number and unit (if applicable). To find out more details, see [`Order and Appointment Lifecycle`](/lab/at-home-phlebotomy/order-appointment-lifecycle), [`Communications`](/lab/at-home-phlebotomy/communications) and [`Webhooks`](/lab/at-home-phlebotomy/webhooks). # Phlebotomy Service Tiers Source: https://docs.junction.com/lab/at-home-phlebotomy/service-tiers Compare the two phlebotomy service tiers: Appointment Ready for synchronous scheduling and Appointment Request for asynchronous assignment. Junction offers multiple Tiers of phlebotomy services, with different coverage capabilities: * **Appointment Ready:** An appointment is booked in Junction using the patient's address and the appointment's date and time. The scheduling is completely synchronous and fully controlled by Junction's customers through our API. * **Appointment Request:** An appointment is requested through the Junction system using the patient's address. A phlebotomist will eventually assign themselves to the appointment and define the appointment's date and time with the patient. The following Providers are available for each Tier: | | Getlabs | Phlebfinders (Beta) | | :------------------ | :-----: | :-----------------: | | Appointment Ready | X | | | Appointment Request | | X | `appointment-request` appointments will start in the `pending` status, and won't have any time or date information. ## High Level flow for Appointment Scheduling
The recommended high-level flow for selecting an appointment at Junction is: * Place an At-Home Phlebotomy order with the [`POST /v3/order`](/api-reference/lab-testing/create-order) endpoint. * Wait for the `Requisition Ready` status updates through our Webhooks. * Fetch Provider data via the [`GET /v3/order/area/info`](/api-reference/lab-testing/area-info) endpoint, the response payload should look like this: ```json theme={null} { "zip_code": "85004", "phlebotomy": { "is_served": true, "providers": [ { "name": "getlabs", "tier": ["appointment-ready"] }, { "name": "phlebfinders", "tier": ["appointment-request"] } ] } } ``` * Select the Provider that best fits your needs. * If you use the [`POST /v3/order/{order_id}/phlebotomy/appointment/book`](/api-reference/lab-testing-at-home-phlebotomy/appointment-booking) endpoint, an `appointment-ready` provider is chosen on your behalf. * If you use the [`POST /v3/order/{order_id}/phlebotomy/appointment/request`](/api-reference/lab-testing-at-home-phlebotomy/appointment-request) endpoint, you must select a provider that offers an `appointment-request` tier. * Wait for the `Appointment Webhooks` and `Order Webhooks` described in the [Webhooks](/lab/at-home-phlebotomy/webhooks) section. # Webhooks Source: https://docs.junction.com/lab/at-home-phlebotomy/webhooks Reference for webhook events triggered during at-home phlebotomy order and appointment lifecycle changes, with example payloads. The following webhook events are of interest when placing an At-Home Phlebotomy order. These are described in detail in the following sections. ## Order webhook events Based on the status present in [`Order and Appointment Lifecycle - Order Lifecycle`](/lab/at-home-phlebotomy/order-appointment-lifecycle#order-lifecycle), Junction will trigger two kinds of webhook events, [`labtest.order.created`](/event-catalog/labtest.order.created) and [`labtest.order.updated`](/event-catalog/labtest.order.updated). The `labtest.order.created` event is triggered when an order is created in the system, having the `ordered` status, and all subsequent status changes will trigger a `labtest.order.updated` event in the system. The `partial_results` status does not trigger a Webhook unless specifically requested from Junction. The webhook payload body will have the following information if the Order is in the `appointment_scheduled` status: ```json Phlebotomy Order Updated theme={null} { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "team_id": "6353bcab-3526-4838-8c92-063fa760fb6b", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "at_home_phlebotomy", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "appointment_id": "d55210cc-3d9f-4115-8262-5013f700c7be", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.at_home_phlebotomy.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.at_home_phlebotomy.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.at_home_phlebotomy.appointment_scheduled" } ], "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "active", "orders": [ { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "low_level_status": "appointment_scheduled", "low_level_status_created_at": "2022-01-03T00:00:00Z", "origin": "initial" } ] } } ``` ## Appointment webhook events Based on the status present in [`Order and Appointment Lifecycle - Appointment Lifecycle`](/lab/at-home-phlebotomy/order-appointment-lifecycle#appointment-lifecycle), Junction will trigger the [`labtest.appointment.updated`](/event-catalog/labtest.appointment.updated) webhook event. The `labtest.appointment.updated` event is triggered for all possible appointment statuses, and is the **recommended** way of integrating to fetch all **At-Home Phlebotomy** status updates, together with the [Order Webhooks](#order-webhook-events). If the ability to [schedule appointments before a requisition has been created](/lab/at-home-phlebotomy/order-appointment-lifecycle#scheduling-appointments-before-a-requisition-has-been-created) is enabled for your team, and you intend to send patient communications for appointment updates, use the `labtest.appointment.updated` event. See more on communications for this feature [here](/lab/at-home-phlebotomy/communications#scheduling-appointments-before-a-requisition-has-been-created). The webhook payload body may have the following information if the appointment is in the `scheduled` status, after a **reschedule** has happened: ```json Phlebotomy Appointment Updated theme={null} { "event_type": "labtest.appointment.updated", "data": { "id": "06c2c65b-74a0-4f25-a4a9-44f796296355", "user_id": "acf79a82-0c2c-4ca0-998b-378931793905", "order_id": "1ed9c8d7-e1b4-4d61-8123-0f99de5ae99a", "order_transaction_id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "address": { "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip_code": "91189", "country": "United States" }, "location": { "lng": -122.4194155, "lat": 37.7749295 }, "start_at": "2022-01-01T00:00:00", "end_at": "2022-01-01T00:00:00", "iana_timezone": "America/New_York", "type": "phlebotomy", "provider": "getlabs", "status": "pending", "event_status": "scheduled", "provider_id": "123", "can_reschedule": true, "event_data": { "origin": "patient", "is_reschedule": true }, "events": [ { "created_at": "2022-01-01T00:00:00Z", "data": null, "status": "scheduled" }, { "created_at": "2022-01-01T00:00:00Z", "data": { "origin": "patient", "is_reschedule": true }, "status": "scheduled" } ] } } ```
The `event_data` field contains relevant information regarding the current appointment status, and may be specific for each `provider`. # Communications Source: https://docs.junction.com/lab/on-site-collection/communications Configure SMS and email notifications sent to patients during each status change in the on-site collection order lifecycle. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. Communication for patients is done via email or SMS for On-site collection orders. Customers have the following options when setting this up: * `Default` - Email and SMS communications are enabled. * `SMS Only or Email Only` - Only SMS or Email communication is enabled. * `Disable` - All communications from Junction are disabled. Each option has a different set of content and status changes, depending on what triggered them. You can enable or disable SMS and Email communications individually through the [**Junction Dashboard**](https://app.junction.com/), under the Team Settings section. ## Default Communications ### SMS Messages A table of the **Order Status** and **default SMS** is provided below: | Order Status | Default Message | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `ordered` | *"Hi, , your order for the on-site collection has been placed! We'll provide you with updates on the status of your order via text messages :)"* | | `requisition_created` | *"Hey , it's time to visit your local collection center. Please check the email you just received for instructions."* | | `draw_completed` | *"Your on-site collection is complete! We're delivering your sample to the lab for processing."* | | `completed` | *"Your results have finished processing and should be ready soon."* | | `cancelled` | *"Hey, your order for the on-site collection has been cancelled. If this is by accident, please contact support."* | SMS Texts are customizable, and can be enabled or disabled individually. ### Emails For emails, the following table describes what information each email contains for each Order Status: | Order Status | Email Content Description | | --------------------- | ------------------------------------------------------------------------------------------------------ | | `requisition_created` | An email with confirmation of the partner Lab and additional instructions will be sent to the patient. | Emails can be customized and sent from your own domain. ## Disable Communications In this case, no communications will be sent from Junction. You have the ability to produce completely customized communications using the [`Webhook events`](/lab/on-site-collection/webhooks) described previously. # Order Lifecycle Source: https://docs.junction.com/lab/on-site-collection/order-lifecycle Reference for all order lifecycle statuses in the on-site collection flow, from order placement through draw completion and results. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. The **On-site Collection** orders are composed of one lifecycle, the **Order** lifecycle, detailed in the following section. ## Order Lifecycle As discussed in [`Lab Test Lifecycle - Statuses`](/lab/workflow/lab-test-lifecycle#statuses), each lab testing modality has the following format: `[HIGH-LEVEL STATUS].[TEST MODALITY].[LOW-LEVEL STATUS]` For on-site collections, this will look like: `[HIGH-LEVEL STATUS].on_site_collection.[LOW-LEVEL STATUS]` For each modality, there can be multiple **low-level statuses**, for **On-site Collection** the possible low-level statuses are: * `ordered`: Junction received the order, stored it into our system, and started processing it asynchronously. * `requisition_created`: An order requisition form was validated and created with the partner laboratory, making the order available to be carried out. * `requisition_bypassed`: An order requisition form wasn't created when the order was placed with us because it already existed. * `draw_completed`: The phlebotomy was completed and the blood was drawn successfully. * `partial_results`: The laboratory has started making partial results available. * `completed`: The laboratory processed the blood sample and final results are available. * `cancelled`: The order was cancelled by either the patient, Junction, or you. This closely models that of walk-in tests. Refer to that [order lifecycle](/lab/walk-in/order-lifecycle#order-lifecycle) for a diagrammatic explanation. # Overview Source: https://docs.junction.com/lab/on-site-collection/overview Overview of the on-site collection modality for blood draws at customer-managed locations like clinics and wellness events. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. On-site collections are one of our offered modalities. Their locations are customer-managed settings where blood draws occur outside of traditional lab-owned patient service centers β€” such as primary care clinics, employer health centers, or event-based wellness pop-ups. ## Ordering Flow overview To achieve this, a high-level overview of the process is defined as: * An order is placed in Junction's system through our Dashboard or API. * The order is added to a background queue and additional checks are made before a test requisition is created with the chosen Laboratory. * After the requisition is created, some form of communication is carried out with the patient. * After that, the patient can go at any time they want to the draw location to have their blood drawn. * The Laboratory processes the patient's blood sample and generates the required results. * Junction exposes the results as soon as they are available, both as PDF and structured data via API. To find out more details, see [`Order Lifecycle`](/lab/on-site-collection/order-lifecycle), [`Communications`](/lab/on-site-collection/communications) and [`Webhooks`](/lab/on-site-collection/webhooks). # Webhooks Source: https://docs.junction.com/lab/on-site-collection/webhooks Reference for webhook events triggered during on-site collection order lifecycle changes, with example payload structures. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. The following webhook events are of interest when placing an On-site collection order. These are described in detail in the following sections. ## Order webhook events Based on the status present in [`Order Lifecycle`](/lab/on-site-collection/order-lifecycle), Junction will trigger two kinds of webhook events, [`labtest.order.created`](/event-catalog/labtest.order.created) and [`labtest.order.updated`](/event-catalog/labtest.order.updated). The `labtest.order.created` event is triggered when an order is created in the system, having the `ordered` status, and all subsequent status changes will trigger a `labtest.order.updated` event in the system. The `partial_results` status does not trigger a Webhook unless specifically requested from Junction. The webhook payload body will have the following information if the Order is in the `completed` status: ```json On-site Collection Order Updated theme={null} { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "team_id": "6353bcab-3526-4838-8c92-063fa760fb6b", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "on_site_collection", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "completed", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.on_site_collection.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.on_site_collection.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.on_site_collection.draw_completed" }, { "id": 4, "created_at": "2022-01-04T00:00:00Z", "status": "sample_with_lab.on_site_collection.partial_results" }, { "id": 5, "created_at": "2022-01-05T00:00:00Z", "status": "completed.on_site_collection.completed" } ], "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "completed", "orders": [ { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "created_at": "2022-01-01T00:00:00Z", "updated_at": "2022-01-05T00:00:00Z", "low_level_status": "completed", "low_level_status_created_at": "2022-01-05T00:00:00Z", "origin": "initial" } ] } } ``` # Compendium Search Source: https://docs.junction.com/lab/overview/compendium-search Search the lab test compendium to find canonical tests and crosswalk them to available lab-specific test candidates. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. `POST /v3/compendium/search` searches the compendium in two modes: * `canonical`: find and rank canonical tests only. * `crosswalk`: select one canonical test, then map it into per-lab candidates. ## Request body ```json theme={null} { "mode": "canonical | crosswalk", "query": "string (optional in crosswalk, required in canonical)", "loinc_set_hash": "string (crosswalk only)", "labs": ["labcorp", "quest", "bioreference", "sonora_quest"], "include_related": true, "limit": 3 } ``` ### Validation rules #### Canonical mode * `query` is required and must be non-empty. * `loinc_set_hash` is not allowed. * `limit` must be `1..10`. #### Crosswalk mode * Exactly one of `query` or `loinc_set_hash` is required. * `limit` must be `1..20`. * `include_related` controls whether related canonical candidates are returned. If validation fails, the API returns HTTP `422`. ## Search modes ### 1) `canonical` Purpose: return ranked canonical tests only. Behavior: * Returns: * `selected_canonical`: top candidate (or `null`). * `canonical_candidates`: ranked list (up to `limit`). * `per_lab` and `related` are empty in this mode. ### 2) `crosswalk` Purpose: choose one canonical test and expand it across labs. Entry points: * By text query: pick best canonical from query. * By `loinc_set_hash`: load canonical directly by hash. Behavior: * If no canonical is found, response has: * `selected_canonical = null` * `canonical_candidates = []` * no per-lab candidates. * If canonical is found, returns: * one `selected_canonical` and same item in `canonical_candidates` * `per_lab`: candidates grouped by lab slug * `related`: related canonical tests (if `include_related=true`) ## Canonical tests "Canonical tests" are normalized, cross-lab test concepts. They are used to: * normalize query intent (`display_name`, `aliases`, `loinc_codes`, etc.) * create one canonical anchor (`selected_canonical`) * crosswalk into concrete provider/lab tests (`per_lab`) Canonical ranking combines match quality and popularity score. The selected labs filter which per-lab candidates are returned in crosswalk mode. ## Output schema ```json theme={null} { "mode": "canonical | crosswalk", "selected_canonical": { "loinc_set_hash": "string", "display_name": "string", "aliases": ["string"], "loinc_codes": ["string"], "provider_ids": ["string"], "loinc_components": ["string"], "loinc_groups": ["string"], "popularity_score": 0.0, "confidence": 0.0 }, "canonical_candidates": [ { "loinc_set_hash": "string", "display_name": "string", "aliases": ["string"], "loinc_codes": ["string"], "provider_ids": ["string"], "loinc_components": ["string"], "loinc_groups": ["string"], "popularity_score": 0.0, "confidence": 0.0 } ], "per_lab": { "quest": [ { "marker_id": 0, "lab_id": 7, "lab_slug": "quest", "name": "string", "result_names": ["string"], "provider_id": "string", "loinc_set_hash": "string", "loinc_codes": ["string"], "loinc_components": ["string"], "loinc_groups": ["string"], "relation": "exact | subset | superset | overlap | suggested", "confidence": 0.0, "reason_codes": ["EXACT_LOINC_SET | SUBSET | SUPERSET | OVERLAP | NAME_MATCH | SYNONYM_MATCH"], "marker_popularity_score": 0.0 } ] }, "related": [ { "canonical": { "loinc_set_hash": "string", "display_name": "string", "aliases": ["string"], "loinc_codes": ["string"], "provider_ids": ["string"], "loinc_components": ["string"], "loinc_groups": ["string"], "popularity_score": 0.0, "confidence": 0.0 }, "relation": "exact | subset | superset | overlap | suggested", "confidence": 0.0, "reason_codes": ["EXACT_LOINC_SET | SUBSET | SUPERSET | OVERLAP | NAME_MATCH | SYNONYM_MATCH"] } ] } ``` Notes: * `confidence` is model/service-generated and relative to result quality. * Omitting `labs` defaults to all supported labs (`labcorp`, `quest`, `bioreference`, `sonora_quest`). ## Example requests ### Canonical mode ```bash theme={null} curl -X POST "$BASE_URL/v3/compendium/search" \ -H "Content-Type: application/json" \ -H "x-vital-api-key: $API_KEY" \ -d '{ "mode": "canonical", "query": "hemoglobin a1c", "labs": ["quest", "labcorp"], "limit": 5 }' ``` ### Crosswalk mode by query ```bash theme={null} curl -X POST "$BASE_URL/v3/compendium/search" \ -H "Content-Type: application/json" \ -H "x-vital-api-key: $API_KEY" \ -d '{ "mode": "crosswalk", "query": "comprehensive metabolic panel", "labs": ["quest", "bioreference"], "include_related": true, "limit": 3 }' ``` ### Crosswalk mode by canonical hash ```bash theme={null} curl -X POST "$BASE_URL/v3/compendium/search" \ -H "Content-Type: application/json" \ -H "x-vital-api-key: $API_KEY" \ -d '{ "mode": "crosswalk", "loinc_set_hash": "f0a1b2c3d4", "labs": ["labcorp", "quest"], "include_related": false, "limit": 3 }' ``` For endpoint schema and try-it behavior, see the API reference page: [Compendium Search](/api-reference/lab-testing/compendium/search). # Ordering Idempotency Source: https://docs.junction.com/lab/overview/idempotency Use the X-Idempotency-Key header when creating lab orders to safely retry requests without duplicating orders on connection failures. The API supports idempotency for safely retrying requests without accidentally performing the same operation twice. When creating an order via the [POST /v3/order](/api-reference/lab-testing/create-order), you can supply an `X-Idempotency-Key` header. Then, if a connection error occurs, you can safely repeat the request without risk of creating a second order. This works by saving the resulting status code and body of the first request made for any given idempotency key, regardless of whether it succeeds or fails. Subsequent requests with the same key return the same result. A client generates an idempotency key, which is a unique key that the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions. You can remove keys from the system automatically after they're at least 24 hours old. We generate a new request if a key is reused after the original is pruned. We save results only after the execution of an endpoint begins. If incoming parameters fail validation, or the request conflicts with another request that's executing concurrently, we don't save the idempotent result because the API endpoint does not initiate the execution. You can retry these requests. # Insurance Ordering Source: https://docs.junction.com/lab/overview/insurance Set up and place lab test orders with commercial insurance billing, including Medicare and Medicaid inference support. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. Junction supports ordering with commercial insurance billing. To set this up, there are a set of steps required. This document explains the complete flow for ordering via commercial insurance. ## Setting Insurance Data **Medicare and Medicaid location inference closed beta** If the patient is covered by Medicare or Medicaid, we have closed beta support for inferring the plan to use based on the patient's address. This endpoint supports `payor_code` values of `MEDFED` (Medicare) and `MAIDFED` (Medicaid) to do this. For example, supplying a `payor_code` of `MEDFED` for a patient that lives in Arizona will create insurance data using Arizona's Medicare plan payor code. Medicare and Medicaid location inference is in closed beta. Get in touch with your Customer Success Manager for more information or check out the [API docs](/api-reference/user/create-insurance) on the beta channel. To place an order for a `user` in Junction with commercial insurance, you must first provide Junction with insurance data. This can be done via the [`POST /{user_id}/insurance`](/api-reference/user/create-insurance) endpoint, with the following payload: Note that you can only set insurance data for users that already have patient information set, either via an order or via the [`PATCH /v2/user/{user_id}/info`](/api-reference/user/upsert-info). It is expected that insurance data will become outdated or change with time. It is the customer's responsibility to update this data with Junction in order to minimize the risk of a denied claim. ```json theme={null} "insurance": { "payor_code": "string", "member_id": "string", "group_id": "string", // optional "relationship": "Self, Spouse, Other", "insured": { "first_name": "string", "last_name": "string", "dob": "YYYY-MM-DD", "gender": "string", "address": { "first_line": "string", "second_line": "string", // optional "zip_code": "string", "state": "string", "city": "string", }, "phone_number": "string", "email": "string" }, "guarantor": { "first_name": "string", "last_name": "string", "dob": "YYYY-MM-DD", "gender": "string", "address": { "first_line": "string", "second_line": "string", // optional "zip_code": "string", "state": "string", "city": "string", }, "phone_number": "string", "email": "string", } // optional if relationship is Self } ``` ### Insured, Guarantor and Relationship First, let's understand the `relationship`, `insured` and `guarantor` fields. `insured` refers to the insured person, and must always be provided. The `relationship` field is the relationship between the patient and the holder of the insurance. For example, if the insured person and the insurance holder are the same, then the relationship is `Self`. The `guarantor` is an optional field, that must be provided when the relationship is **NOT** `Self`. The guarantor is the financially responsible party. If provided when the relationship is `Self`, we will store it, but it may not be propagated to all lab partners, as not all partners accept a guarantor in this situation. ### Payor Code The `payor_code` is a lab-specific identifier for an insurance company. Junction has abstracted this away into our own Junction payor codes, allowing customers to supply one lab-agnostic payor code for all labs. To obtain this code, use the [Search Payor Code](/api-reference/lab-testing/insurance/search-payor-get) endpoint, using the insurance company name, and select the `code` from your insurance company. It is also possible to use this endpoint to search using external providers' payor codes (e.g., Change Healthcare or Availity). ```json theme={null} [ { "code": "AARPA", "name": "AARP", "aliases": [ "AARP" ], "org_address": { "first_line": "PO BOX 740819", "second_line": null, "country": "US", "zip": "30374", "city": "ATLANTA", "state": "GA" } }, ] ``` ## Ordering Once the above steps are complete, you can place an order as usual, with two differences. In order to trigger the commercial insurance flow, you must supply the following extra fields in the [POST /order](/api-reference/lab-testing/create-order) payload: ```json theme={null} { "icd_codes": ["ICD.10"], "billing_type": "commercial_insurance" } ``` ### Billing type By default, Junction orders are Client Bill. In order to trigger the insurance flow, you must supply the `billing_type` field, with `commercial_insurance`. ### Diagnosis Codes Insurance orders require diagnosis codes to be supplied. You can search for diagnosis codes in our [Search ICD Code](/api-reference/lab-testing/insurance/search-diagnosis) endpoint. ## Insurance Availability Not all labs and not all states are cleared for insurance ordering. You can verify if a zip code is served for insurance via the [`GET /v3/order/area/info`](/api-reference/lab-testing/area-info) endpoint. If a particular lab supports insurance, then you should see `commercial_insurance` in the supported bill types. ```json theme={null} { "zip_code": "85007", "central_labs": { "labcorp": { "patient_service_centers": { "within_radius": 15, "radius": "25" }, "supported_bill_types": [ "commercial_insurance" ] }, ... } } ``` ## Error Cases 1. Order with `commercial_insurance` billing for a lab that does not support it. 2. Order with `commercial_insurance` billing for a state that does not support it. 3. Order with `commercial_insurance` billing and no ICD codes or invalid ICD codes provided. 4. Order with `commercial_insurance` billing and the user has no insurance data. # Introduction Source: https://docs.junction.com/lab/overview/introduction Introduction to the Junction Lab Testing API for ordering lab tests, managing results, and integrating with physician networks and partner labs. Junction's lab test API allows digital health companies to carry out at-home lab testing. Companies can use the API to order a variety of tests, using multiple sampling methods. We partner with CLIA and CAP certified labs across the United States that cover a range of different diagnostic tests. For example, lipid panels, metabolic profiles, hormone tests, and more. We collect these test samples via at-home kits, or phlebotomy. ### Features Our lab test API gives you an end-to-end experience, from ordering a test all the way to receiving results, all with one API call! What we offer: * Multiple [test modalities](/lab/overview/testing-modalities) through one unified API. * 50-state physician network - you can use your own physician if you have one, or we will automatically assign one from our network. * Updates throughout the test lifecycle - we automatically send you webhook updates and SMS updates to your patients so that you both never miss an update. * Test results: we will update you once the test results are ready. In case of abnormal results, we also provide follow-ups through our physician network. * 1:1 support: after production launch, you will have direct access to Slack and our engineers. ### Start integrating You can sign up today for our sandbox environment. The [quickstart](/lab/overview/quickstart) guide will help you get from zero to ordering tests in less than 30 minutes! Once the integration is ready, switching to production will just be a matter of switching API keys. ### Production launch As a first step, we need to define what type of testing you want to offer to your users. We will have an introduction call to go over the test, projected volumes, customizations for kits and other questions you might have. Once we have all this information, we will begin setting up the test kits for distribution. Once the integration is complete, you will have access to the dashboard to start ordering tests via our API. On [this page](https://tryvital.io/labs), you can check out some examples of the test panels we offer, and book an introductory call with us. ### Support We will assist you throughout the whole integration with Junction. After launch, you will have a dedicated account manager with access to Slack, and 1:1 support with our engineers. ### Coverage Our lab test API is available throughout the US. This is our current coverage by test modality: * [At-home test kits](/lab/overview/testing-modalities#at-home-test-kits): 49 states (all excluding NY). * [Walk-in tests](/lab/overview/testing-modalities#walk-in-tests): 49 states (all excluding NY). * [At-home phlebotomy](/lab/overview/testing-modalities#at-home-phlebotomy): 35 states at the moment. Full coverage coming soon. * [On-site collection](/lab/overview/testing-modalities#on-site-collection): In beta testing. To find out more about our coverage, you can use the [area info endpoint](/api-reference/lab-testing/area-info) - this endpoint takes a zip code and tells you whether that area is covered by our service or not. Or you can contact us at [support@junction.com](mailto:support@junction.com) for more info. # Lab Accounts Source: https://docs.junction.com/lab/overview/lab-accounts Manage lab accounts that link your team to partner laboratories for order routing and result delivery configuration. Lab accounts encapsulate the information needed to place orders and receive results for a particular lab. They are tied to Orgs and can be dynamically linked to as many Teams within the Org as desired. When an active lab account is linked to a Team, that Team can place orders using that lab account. A Team can have multiple lab accounts linked, even for a single lab, but an individual order must be placed with a single lab account. The [Create Order](/api-reference/lab-testing/create-order) endpoint accepts a `lab_account_id` to specify the lab account. If `lab_account_id` is not provided when placing an order, we will try to determine an appropriate lab account based on available information, but if we cannot unambiguously find one lab account that should be used, we might not be able to place the order. We recommend including the `lab_account_id` when possible. Lab accounts for an Org can be viewed using the [Get Lab Accounts (Org-level)](/api-reference/org-management/lab-accounts/get-lab-accounts) endpoint. Teams can fetch their available lab accounts using [Get Lab Accounts (Team-level)](/api-reference/lab-testing/lab_accounts). Team linkage is managed only through the [Update Lab Account Teams (Org-level)](/api-reference/org-management/lab-accounts/update-lab-account-teams) endpoint. ## Which endpoint should I use? Use both endpoints for different jobs. They are complementary, not interchangeable. | Topic | Org-level Get Lab Accounts | Team-level Get Lab Accounts | | ------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------- | | Scope | Returns lab accounts for the Org, across teams | Returns lab accounts available to one team context | | Typical user | Org admin or platform integrator | Team-scoped integration | | Best use case | Org-wide visibility and management | Team-specific runtime operations | | Filtering behavior | Can be used to review accounts at the Org level and understand team linkage | Returns only accounts available in the current team context | Recommendation: * Use the team-level endpoint when operating within one team context. * Use the org-level endpoint when you need cross-team, org-level management views. * There is no team-level endpoint for updating lab account team linkage. Practical examples: * **Org-level endpoint:** An operations admin audits all lab accounts in the Org and confirms which teams are linked to each account. * **Team-level endpoint:** A team-specific ordering workflow fetches only the lab accounts that team can use before creating an order. You can also view lab accounts tied to your Org on the [Lab Interface Requests page of your Org Config](https://app.junction.com/org/lab-interface-requests) in the Junction dashboard. # Patient Service Centers and Appointments Source: https://docs.junction.com/lab/overview/locations Find and verify nearby Patient Service Centers (PSCs) for walk-in lab tests using the Area Info and PSC Info API endpoints. # Finding the Nearest Serviceable Patient Service Centers Verifying if a particular zip code is serviceable is an important step, as not all labs have patient service centers within a state or within a reasonable distance. The recommended high-level flow for verifying PSC availability at Junction is: 1. Fetch PSC location data via the `GET` [Area Info](/api-reference/lab-testing/area-info) endpoint, the response payload should look like this: ```python theme={null} { "zip_code": "85004", "central_labs": { "labcorp": { "within_radius": 5, # the number of PSCs within radius of provided zip code "radius": "25", # miles "capabilities": ["stat", "appointment_scheduling_with_lab"] # aggregate list of capabilities provided by PSCs within the radius } } ... } ``` 2. Then you can query the `GET` [PSC Info](/api-reference/lab-testing/psc-info) endpoint for specific information on the PSCs within the radius of the provided zip code, which will look like this: ```json theme={null} { "lab_id": 27, "slug": "labcorp", "patient_service_centers": [ { "metadata": { "name": "LABCORP", "state": "AZ", "city": "Phoenix", "zip_code": "85006", "first_line": "1300 N 12th St", "second_line": "Ste 300", "phone_number": "480-878-3988", "fax_number": "844-346-5903", "hours": null }, "distance": "25", "site_code": "ABC", "capabilities": ["stat", "appointment_scheduling_with_lab"] }, ] } ``` A **capability** is a specific service that a PSC provides, for example, STAT testing or appointment scheduling. # Booking appointments at Patient Service Centers Currently only available for Quest lab locations. ## Appointment scheduling capability The ability to schedule appointments is designated with the `capabilities` field in the response from the `GET` [Area Info](/api-reference/lab-testing/area-info) or `GET` [PSC Info](/api-reference/lab-testing/psc-info) endpoints as: * `appointment_scheduling_via_junction`: Indicates that the PSC allows scheduling appointments via Junction's API. * `appointment_scheduling_with_lab`: Indicates that the PSC allows scheduling appointments directly with the lab, either online or via phone. This capability also indicates that scheduling appointments with this location is **not** available through Junction's API. If neither scheduling capability is present, that means the PSC either does not offer appointment scheduling, or its scheduling availability is unknown. At this time, Arizona Quest lab locations cannot be scheduled through Junction's API. These labs are operated by Sonora Quest, and their scheduling service does not currently support third-party API scheduling. ## Appointment Availability Use the `POST` [PSC Appointment Availability](/api-reference/lab-testing/psc-scheduling/appointment-psc-availability) endpoint to obtain the available slots. You can provide the `site_code` you obtain from the `GET` [PSC Info](/api-reference/lab-testing/psc-info) endpoint, or supply a zip code directly. * If you provide a zip code, a maximum of 3 PSC locations will be displayed. Note that since this endpoint can return availability for multiple PSCs, there may be multiple time zones associated with the returned data. * ⚠️ The individual start and end times are in UTC, and each location has its own `iana_timezone` key, which should be used to convert these start and end dates to the correct time zone. * The overarching `timezone` key will always be `null` in this endpoint. ## Booking Patient Service Centers have access to the booked appointment, which can be cancelled or updated outside of our system. When this occurs, the lab does not expose this to us, and so we do not have visibility, and it will not be reflected in our system or API. In order to book these appointments, you can use the `POST` [PSC Appointment Availability](/api-reference/lab-testing/psc-scheduling/appointment-psc-availability) endpoint to find available appointment slots. You can then [book](/api-reference/lab-testing/psc-scheduling/appointment-psc-booking), [reschedule](/api-reference/lab-testing/psc-scheduling/appointment-psc-rescheduling), or [cancel](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) with Junction as many times as you want. To allow the patient to track their appointment individually, we expose the `external_id` parameter in the appointment endpoints and webhooks. * This code is the unique identifier for the appointment at the provider and should be made available to the patient. * We provide it to the patient via [SMS communications](/lab/walk-in/communications) for the appointment. ### External ID Format The `external_id` field contains the provider's unique appointment identifier: | Provider | Format | Example | Description | | -------- | ------------- | -------- | ------------------------------------------------------ | | Quest | 6-letter code | `ABCDEF` | Used by Quest to identify appointments in their system | # Order and Follow-up Physician Source: https://docs.junction.com/lab/overview/physicians Choose between using Junction's physician network, your own physicians, or a hybrid approach for lab test ordering and result review. For an order to be valid/complete, both the request and the results need to be validated by a physician. As such, Junction provides three flows: ## 1. Order and Results through Junction Physician Network The validation of both the order and the results is done by Junction's physician network. For each order, Junction's physician network validates the requisition and, when the results are available, they are uploaded to Junction's physician network to be evaluated for abnormal/critical results. On the physician's judgment, the patient may receive a phone call regarding their results. ## 2. Order and Results with Customer Physician Network In this flow, the Customer must specify a `physician` when making an order request. Both the order and the results are the responsibility of the Customer's chosen physician. ## 3. Order with Junction Physician Network and Results with Customer Physician Network In this flow, the Customer does not specify a `physician` when making an order request - they use Junction's physician network. However, the results aren't uploaded to Junction's physician network, and it's the Customer's physician's responsibility to validate the results and do the follow-ups. When there are critical results, Junction's physician network will always be notified. # Quickstart Source: https://docs.junction.com/lab/overview/quickstart Step-by-step guide to placing your first lab test order through the Junction API, from user creation to order submission. We have carefully designed Junction's API to ensure a seamless and hassle-free experience for developers. You can get up and running with just a few lines of code. In this guide, we will walk you through the essential steps to order your first lab test. ### What you need * If you haven't done so yet, you can get API keys by signing up for a Junction account in the [Dashboard](https://app.junction.com). Detailed instructions are available [here](/home/quickstart#1-api-keys). * One of our [client libraries](/home/libraries). The lab testing API is available for the [Python](https://pypi.org/project/junction-api-sdk/) and [TypeScript](https://www.npmjs.com/package/@junction-api/sdk) SDKs. If none of those fit your use case, you can always directly call the API. Email [support@junction.com](mailto:support@junction.com) for specific library support. In the following, replace `{{BASE_URL}}` with your team's [environment URL](/api-details/junction-api#environments). ### (1) Creating a user In the context of our API, a user refers to the patient who will be undergoing the lab test. All you need to provide is a string identifying the user on your side (`client_user_id`). The response to this call returns the userId on our side, which you'll be able to use for future requests. You can find more details in our [API quickstart guide](/home/quickstart#3-creating-your-first-user). ```bash Creating a Junction user (bash) theme={null} curl --request POST \ --url {{BASE_URL}}/v2/user/ \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --header 'x-vital-api-key: ' \ --data '{"client_user_id":""}' ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.user.create({ clientUserId: "" }); ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.user.create(client_user_id="") ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.user.requests.UserCreateBody; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.user().create( UserCreateBody.builder() .clientUserId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.User.Create(context.TODO(), &junction.UserCreateBody{ ClientUserId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ### (2) Listing available tests To retrieve the set of lab tests you have access to, use the `/v3/lab_tests` API endpoint. In Sandbox, you will already have access to a default set of tests. Once you're ready to head to production, we can [set up a call](/lab/overview/introduction#production-launch) and get you ready for launch! ```bash Listing available tests (bash) theme={null} curl --request GET \ --url {{BASE_URL}}/v3/lab_tests/ \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.get() ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.get(); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().get(); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.Get(context.TODO(), nil) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` This will return a list of all the available tests to you. They include a description, turnaround time and price: ```json Response theme={null} { "lab_tests": [ { "id": "e2eaa385-a311-4f17-b33f-2165e3d24dd9", "name": "Lipids Panel", "description": "Cholesterol tests", "sample_type": "dried blood spot", "method": "testkit", "price": 10.0, "is_active": true, "lab": { "slug": "USSL", "name": "US Specialty Lab", "first_line_address": "123 Main St", "city": "New York", "zipcode": "10001", }, "markers": [ { "name": "Thyroid Stimulating Hormone", "slug": "tsh", "description": "", "min_value": 100, "max_value": 200, "unit": "fg/L" } ], } ] } ``` You can then use the test `id` when creating an order. ### (3) Placing an order Ordering a test for your user is as simple as making an API call. Ensure all patient name fields (`first_name`, `last_name`, `receiver_name`) follow our [name validation requirements](/lab/workflow/order-requirements#patient-name-validation): ```bash Ordering a test (bash) theme={null} curl --request POST \ --url {{BASE_URL}}/v3/order/ \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' \ --data ' { "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2022-07-06T22:20:26.796Z", "gender": "male | female", "email": "test@test.com" }, "patient_address": { "receiver_name": "John Doe", "street": "Hazel Road", "street_number": "102", "city": "San Francisco", "state": "CA", "zip": "91789", "country": "U.S.", "phone_number": "+14158180852" }, "lab_test_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "physician": { "first_name": "John", "last_name": "Doe", "email": "john@doe.com", "npi": "123456789", "licensed_states": ["CA", "NY"], "created_at": "2022-07-06T22:20:26.796Z", "updated_at": "2022-07-06T22:20:26.796Z" } } ' ``` ```python Python theme={null} from junction import Gender, Junction, PatientAddressWithValidation, PatientDetailsWithValidation from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.create_order( user_id="", lab_test_id="", patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="2020-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddressWithValidation( first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", phone_number="+1123456789", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.createOrder({ userId: "", labTestId: "", patientDetails: { firstName: "John", lastName: "Doe", dob: "2020-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", phoneNumber: "+1123456789", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.CreateOrderRequestCompatible; import com.junction.api.types.Gender; import com.junction.api.types.PatientAddressWithValidation; import com.junction.api.types.PatientDetailsWithValidation; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().createOrder( CreateOrderRequestCompatible.builder() .userId("") .patientDetails(PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("2020-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build()) .patientAddress(PatientAddressWithValidation.builder() .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .build()) .labTestId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) labTestId := "" response, err := c.LabTests.CreateOrder(context.TODO(), &junction.CreateOrderRequestCompatible{ UserId: "", LabTestId: &labTestId, PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "2020-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddressWithValidation{ FirstLine: "123 Main St.", City: "San Francisco", State: "CA", Zip: "91189", Country: "US", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ```json Response theme={null} { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": {"dob": "2020-01-01", "gender": "male"}, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789", }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z", }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", }, }, "diagnostic_lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit", }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "collecting_sample", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered", } ], } ``` As demonstrated in this Quickstart Guide, integrating with our API is straightforward, allowing you to access a wide range of lab tests with minimal effort. Placing an order for a lab test is as simple as making a request to the appropriate endpoint. With our user-friendly design and clear documentation, you can harness the power of our clinical test API to enhance your application and deliver a seamless experience to your users. # Testing in Sandbox Source: https://docs.junction.com/lab/overview/sandbox Test lab test ordering in the Junction sandbox environment with lifecycle simulation, pre-configured tests, and collection method restrictions. To enable customers to simulate the ordering process in the sandbox environment, Junction provides simulated results and a way to transition an order through its [lifecycle](/lab/workflow/lab-test-lifecycle). ## Creating Lab Tests Every created team comes with 4 standard `Lab Tests` to allow the customer to test all 4 collection modalities: * **Test Kit**: At-home collection using shipped test kits * **Walk-in Test**: Patient visits a Patient Service Center (PSC) location * **At-Home Phlebotomy**: A mobile phlebotomist visits the patient's location * **On-Site Collection**: Collection at the customer's facility However, since most customers choose to have their own custom lab tests, you should create your own tests using the [API](/lab/workflow/create-test). This is encouraged, as Junction generates results based on the associated markers. More on this in the [results section](/lab/overview/sandbox#results). ## Lifecycle When an order is placed in the sandbox environment, it is "stuck" in the `ordered` state and will not progress unless triggered to do so. This can be done through the dashboard or through the [API](/api-reference/lab-testing/simulate-order). Initiating the simulation process will progress the order through the expected success states defined in the [lifecycle section](/lab/workflow/lab-test-lifecycle), triggering all expected webhooks, emails, and SMS messages. ## Collection Method Restrictions ### At-Home Phlebotomy When testing At-Home Phlebotomy appointments, there are only two specific zip codes allowed: * **85004** (Phoenix, AZ) - Uses Getlabs provider * And only one specific address: `West Lincoln Street, Phoenix, AZ 85004, USA` * **54650** - Uses PhlebFinders provider ### Quest PSC Appointments In the sandbox, Quest appointment slots are generated automatically with these patterns: **Availability:** * Same day: Next hour until 5 PM EST (if before 4 PM) * Future days: 7 AM - 12 PM EST * 20-minute intervals for all slots **Timezone:** All sandbox appointments use `America/New_York` timezone regardless of location (production uses actual PSC timezones). We have a feature request in our backlog to support more representative sandbox appointment slots, including handling time zones specific to locations. We don't have a timeline for this right now, but if you'd like to be notified when it is implemented, please contact our support team. ## Results To allow customers to test, Junction generates fake results for each lab test based on the [expected markers](/lab/results/result-formats#expected-results). The generated JSON results will cycle through all possible [result types](/lab/results/result-formats#resulttype): * `numeric`: Numerical values with reference ranges * `comment`: Textual commentary results * `range`: Range-based results (e.g., "\<50") **Important Notes:** * Generated values might not match the expected unit * **PDF results are not dynamically generated** - Junction returns an example PDF that does not reflect the ordered test * Account numbers for shipping labels return a hardcoded value `1234567890` in sandbox ## Customizing the Response You can customize the end response of the results via the body of the [Simulate Order](/api-reference/lab-testing/simulate-order) endpoint. There are three avenues of customization currently: ### 1. Interpretation Supplying the `interpretation` field will set the result's status to the supplied value. If you set it to critical, then the critical result workflow will be triggered. ```json theme={null} { "interpretation": "critical" } ``` Available interpretations: * `normal`: Standard normal results (default) * `abnormal`: Results outside normal ranges * `critical`: Triggers critical result notifications and workflows ### 2. Result Types This field controls what result types will be generated. Omitting it will cycle through all available types. ```json theme={null} { "result_types": ["numeric", "comment"] } ``` Available result types: * `numeric`: Numerical results with reference ranges * `comment`: Text-based results and observations * `range`: Range-based results ### 3. Missing Results Supplying this field will generate missing biomarkers in the result to simulate incomplete lab processing. ```json theme={null} { "has_missing_results": true } ``` This simulates scenarios where some biomarkers fail processing or are unavailable, which is common in real-world lab operations. ## Environment-Specific Behavior ### Sandbox vs Production Differences | Feature | Sandbox | Production | | -------------------- | -------------------------------------------- | ----------------------------------------- | | Order Progression | Manual trigger required | Automatic, based on lab processing times. | | PDF Results | Static example PDF | Dynamic lab-generated PDFs | | Account Numbers | Hardcoded `1234567890` | Real lab account numbers | | Phlebotomy Locations | Restricted to specific zip codes | Full coverage area | | Quest PSC Slots | Mock slots, `America/New_York` timezone only | Real Quest API integration | | Appointment Times | Restricted availability (see above) | Based on actual PSC availability | ## Testing Recommendations 1. **Use Custom Lab Tests**: Create tests with your specific biomarkers for realistic result simulation 2. **Test All Collection Methods**: Verify each modality works with your integration 3. **Test Error Scenarios**: Use missing results and different interpretations 4. **Test Appointment Workflows**: Book, reschedule, and cancel appointments to verify full flow # Testing Modalities Source: https://docs.junction.com/lab/overview/testing-modalities Compare the four lab testing modalities: at-home test kits, at-home phlebotomy, walk-in tests, and on-site collection. By integrating with our API, you will have access to the following testing modalities: * At-home test kit. * At-home phlebotomy visit. * Walk-in test visit. * On-site collection visit (in closed beta). ## At-home test kits This involves sending a kit to a patient's home. They will then be able to collect their specimen and send it back to our lab networks via mail. At-home testing kits are comprised of a number of components such as:
* Mailer Box * Blade Lancets * Plasters * Gauze * ADX Card * Blood collection card * Saliva Tubes * Collection Supplies * Instruction Booklet Additional components can be included in the test kit box. To fully customize the kit, just contact us at [support@junction.com](mailto:support@junction.com).
## At-home phlebotomy At-home phlebotomy requires a phlebotomist to visit a patient's home and carry out the phlebotomy draw. The sample is then delivered to the lab by the phlebotomist. The flow for at-home phlebotomy orders is as follows: * [Place an order](/lab/overview/quickstart) via the API. * The order is processed in the background. For at-home phlebotomy, this means generating the requisition form for the lab test. * Once the requisition form is ready, a webhook update and an email to the patient are sent. The email will let them know they can now book an appointment. * The patient goes through Junction's appointment booking dashboard, where they can select a location and time from the available slots. * Once the appointment takes place and the sample is drawn, it will be taken to the lab. * Once the lab analyzes the results, the order is complete and the results can be [fetched](/lab/results/result-formats). ## Walk-in tests Walk-in tests require the patient to visit a lab location (often referred to as a Patient Service Center or PSC)β€”such as Quest, Labcorp, or BioReferenceβ€”to have their sample collected. A requisition form is needed to perform the test, which Junction's API generates if the patient meets the required conditions. This workflow closely mirrors the at-home phlebotomy flow, except that appointment scheduling is not required. With a "walk-in" test, a patient can simply *walk in* to a PSC or they can schedule an appointment (Quest only). ## On-site collection On-site collection closely mirrors the walk-in test flow. Scheduling an appointment is not necessary. On-site collections are currently in beta testing. Expanded support for on-site or in-clinic draws coming soon! # Turnaround Times Source: https://docs.junction.com/lab/overview/turnaround-times Review turnaround time estimates for lab test results at the marker, panel, and order levels with 95th and 99th percentile metrics. For a comprehensive Dashboard-focused overview of turnaround times, check out [the product guide](https://support.junction.com/articles/9137043704-turnaround-time). This page focuses on the API aspects. We have two different turnaround time metrics: 1. Common turnaround time which 95% of orders should fall within. 2. Worst-case turnaround time which 99% of orders should fall within. Furthermore, each operates on three distinct levels: 1. Markers 2. Panels 3. Orders Turnaround times are calculated from historical data. For some tests, we may not yet have enough data to make a determination on its turnaround time. We won't include turnaround times for these tests in our API responses. We recalculate expected turnaround times regularly using the latest live data. Values might change dramatically from time to time to reflect real-world logistical circumstances. ## Marker turnaround times Marker turnaround times are based on historical orders of each marker. If a marker has been ordered enough such that we can make a statistically viable determination on its average turnaround time, we will include these in payloads containing marker data. For example, the response body for [retrieving markers for a lab test](/api-reference/lab-testing/lab-test-markers) includes the common and worst-case number of days to receive results for that marker after collection time. If we don't have enough data for that marker, those values will be null. ## Panel turnaround times Panels comprise one or more markers, and the turnaround time for the panel is the largest turnaround time among its constituent markers. Just like in marker response bodies, lab test response bodies return the common and worst-case turnaround times (in days) for the panel. You can see this when [getting all available tests](/api-reference/lab-testing/tests-paginated), for example. If any of the markers in the panel have null turnaround times, then the panel also has a null turnaround time. ## Order turnaround times An order's turnaround time is the same as its panel, so we don't repeat that information in the top-level order response body. You can still find that information in the `lab_test` object within the response body if you need it. Instead, the top-level body includes two related fields: 1. Expected result by date 2. Worst-case result by date These will be null unless the order's lab test has a non-null turnaround time *and* the sample collection has already been performed. The time of sample collection is what we add to the panel turnaround times to determine the expected and worst-case result by dates. [Retrieving an order](/api-reference/lab-testing/get-order) is an example of where this is included. # Lab Report Parsing Source: https://docs.junction.com/lab/report-parsing/overview Extract structured biomarker data from PDF and image lab reports using the Lab Report Parsing API with automatic LOINC code matching. Junction's Lab Report Parsing API converts lab report files into structured JSON. You can upload PDF, JPEG, and PNG reports from external laboratories, patient-uploaded records, or historical chart archives, then retrieve extracted metadata, results, reference ranges, interpretations, and LOINC matches. Lab Report Parsing is separate from Junction's ordered lab test workflow. It does not place an order, collect a sample, or request a result from a lab. It reads an existing report document and returns the data Junction can extract from that document. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. ## When to Use It Use Lab Report Parsing when you already have a completed lab report file and need to make it usable in your application. Common use cases include: * Patient uploads of lab reports from outside providers * Historical data imports from PDFs or scanned records * Multi-lab result aggregation using LOINC as a normalization layer * Backfilling structured results before a user starts ordering through Junction If the result came from a Junction lab order, use the order [result format documentation](/lab/results/result-formats) and [results endpoints](/api-reference/lab-testing/results/get-results) instead. ## Workflow The parsing workflow is asynchronous: 1. Upload one or more report files to create a parsing job. 2. Junction validates and stages the uploaded file, then queues the parsing job. 3. Junction extracts report metadata and lab results, then attempts to match extracted results to LOINC codes. 4. Your application receives a webhook or polls the job endpoint. 5. When the job is `completed`, the `data` object contains parsed metadata and results. ```mermaid theme={null} sequenceDiagram participant App as Your App participant API as Junction API participant Parser as Parser Service App->>API: POST /lab_report/v1/parser/job API->>API: Validate and stage file API->>Parser: Queue parsing job API-->>App: { id, status: "upload_pending" } Parser->>Parser: Extract results and match LOINCs API-->>App: Webhook: lab_report.parsing_job.updated App->>API: GET /lab_report/v1/parser/job/{job_id} API-->>App: { status: "completed", data: {...} } ``` ## Uploading Reports Create a parsing job with the [Create Lab Report Parser Job](/api-reference/lab-testing/lab-report-parsing/post-lab-report-parser-job) endpoint. The request is `multipart/form-data` and requires: | Field | Required | Description | | -------------------- | -------- | ---------------------------------------------------------------------------------------- | | `file` | Yes | One lab report file, or multiple image files for one report. | | `user_id` | Yes | Junction user ID to associate with the parsed report. | | `needs_human_review` | No | Set to `true` to request manual review where enabled for your team. Defaults to `false`. | Supported file formats and upload limits: | Upload | Supported formats | Limit | | -------------- | ----------------- | ---------------------------------------------- | | Single file | PDF, JPEG, or PNG | 10 MB | | Multiple files | JPEG and PNG only | Up to 8 files, 10 MB per file, 20 MiB combined | | PDF pages | PDF upload | Up to 20 pages | When you upload multiple image files, Junction merges them into a single PDF before sending the report to the parser. Multi-file uploads cannot include PDFs. Junction validates both the declared `Content-Type` and the file's magic bytes, so spoofed or corrupted files are rejected before parsing starts. ```bash cURL theme={null} curl --request POST \ --url {{BASE_URL}}/lab_report/v1/parser/job \ --header 'accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: multipart/form-data' \ --form 'file=@/path/to/lab_report.pdf' \ --form 'user_id=' \ --form 'needs_human_review=false' ``` The create response returns the job immediately. At this point, `data` is `null` because parsing has not completed. ```json Response theme={null} { "id": "8eb0217f-4683-4a3c-adca-faf95ac65739", "status": "upload_pending", "failure_reason": null, "data": null, "needs_human_review": false, "is_reviewed": false } ``` ## Job Statuses The `status` field describes the state of the parsing job. | Status | Description | | ---------------- | ----------------------------------------------------------------------------------------------------------- | | `upload_pending` | Job was created and the file upload is being finalized. This is the status returned by the create endpoint. | | `started` | The file was uploaded and parsing is in progress. | | `completed` | Parsing completed and results are available in `data`. | | `failed` | Parsing failed. Check `failure_reason` for more information. | For parser jobs, `failure_reason` commonly includes: | Failure reason | Meaning | | ------------------ | -------------------------------------------------------------------------------------------- | | `invalid_input` | The parser determined that the document is not a lab report containing medical test results. | | `not_english` | The report language is not supported. | | `processing_error` | Junction could not process the report because of an internal parser or provider failure. | Parser status and failure reason enums are non-exhaustive. Store unknown values safely and avoid hard-failing if Junction adds a new value or returns `failure_reason: null`. ### Upload Validation Errors Some invalid uploads are rejected synchronously by the create endpoint instead of becoming failed parser jobs. These errors return an HTTP error response and do not produce a completed async parsing result. | Upload issue | Response behavior | | ------------------------------------------------- | ---------------------------------- | | Unsupported file type | `400` error before parsing starts. | | Empty file | `400` error before parsing starts. | | Declared `Content-Type` does not match file bytes | `400` error before parsing starts. | | File is larger than the upload limit | `413` error before parsing starts. | | PDF is corrupted, truncated, or unreadable | `400` error before parsing starts. | | PDF exceeds the page limit | `400` error before parsing starts. | ## Human Review Set `needs_human_review` to `true` to mark the job as requiring manual review where enabled for your team. Human review is useful for high-impact workflows, low-quality scans, complex multi-page reports, or reports where your application needs a higher-confidence extraction path. Human review is not enabled for every team by default. Contact your account manager before depending on it in production. If your team is not enabled for human review, creating a job with `needs_human_review=true` returns a `400` response: ```json Error theme={null} { "detail": "Human review is not supported yet for your team please contact support" } ``` The response includes two review fields: | Field | Meaning | | -------------------- | ------------------------------------------------------------------------------------ | | `needs_human_review` | Whether the job was submitted with a manual-review request. | | `is_reviewed` | Whether manual review has been completed, where a manual-review workflow is enabled. | ## Parsed Output When `status` is `completed`, `data` contains: | Field | Description | | ---------- | ---------------------------------------------------------------------------------------- | | `metadata` | Patient and report-level metadata extracted from the document. | | `results` | Array of extracted lab results. Each item represents one reported marker or observation. | Example completed response: ```json Response theme={null} { "id": "8eb0217f-4683-4a3c-adca-faf95ac65739", "status": "completed", "failure_reason": null, "data": { "metadata": { "patient_first_name": "Jane", "patient_last_name": "Doe", "dob": "1990-01-01", "gender": "female", "lab_name": "Acme Labs", "date_reported": "2025-01-01", "date_collected": "2024-12-30", "specimen_number": "ABC123" }, "results": [ { "test_name": "Glucose", "value": "90", "type": "numeric", "units": "mg/dL", "min_reference_range": 70, "max_reference_range": 99, "source_panel_name": "CMP", "sample_type": "serum_plasma_blood", "measurement_kind": "direct", "sensitivity": "unknown", "loinc_match_status": "auto_match", "loinc_matches": [ { "loinc_code": "2345-7", "loinc_name": "Glucose [Mass/volume] in Serum or Plasma", "display_name": "Glucose", "aliases": [], "confidence_score": 0.99 } ], "interpretation": "normal", "is_above_max_range": false, "is_below_min_range": false } ] }, "needs_human_review": false, "is_reviewed": false } ``` ### Metadata `metadata` is extracted from the document header and surrounding report content when present. | Field | Description | | -------------------- | -------------------------------------------------------------------- | | `patient_first_name` | Patient first name from the report. | | `patient_last_name` | Patient last name from the report. | | `dob` | Patient date of birth as printed or normalized from the report. | | `gender` | Extracted patient gender normalized to `male`, `female`, or `other`. | | `lab_name` | Name of the lab or reporting organization. | | `date_reported` | Date the report was issued. | | `date_collected` | Date the specimen was collected. | | `specimen_number` | Lab specimen, accession, or sample identifier. | Not every report contains every metadata field. Treat patient names, date of birth, lab name, report dates, and specimen number as nullable. Treat unknown or unsupported gender values as `other`. ### Result Fields Each `data.results[]` item contains the extracted value and associated context. | Field | Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------ | | `test_name` | Normalized marker or observation name derived from the report. | | `value` | Result value as a string. See [Value and Type](#value-and-type). | | `type` | Result shape, such as `numeric`, `range`, or `comment`. | | `units` | Units extracted from the report, when available. | | `min_reference_range` | Numeric lower bound extracted from the reference range, when available. | | `max_reference_range` | Numeric upper bound extracted from the reference range, when available. | | `source_panel_name` | Panel name associated with the result, when available. | | `sample_type` | Specimen type, such as `serum_plasma_blood`, `urine`, `saliva`, `stool`, `capillary_blood`, `other`, or `unknown`. | | `measurement_kind` | Whether the result appears to be `direct`, `calculated`, `ratio`, or `unknown`. | | `sensitivity` | Sensitivity classification when the report indicates it. | | `interpretation` | Parsed or inferred interpretation. Possible values are `normal`, `abnormal`, `critical`, or `unknown`. | | `is_above_max_range` | Whether the result is above `max_reference_range`, when this can be determined. | | `is_below_min_range` | Whether the result is below `min_reference_range`, when this can be determined. | | `loinc_match_status` | LOINC matching state: `auto_match`, `needs_review`, or `no_match`. | | `loinc_matches` | Candidate LOINC matches with confidence scores. | ## Value and Type `data.results[].value` is always returned as a string. Do not assume it can always be parsed as a number. For `type: "numeric"`, `value` should be a number encoded as a string, such as `"5"` or `"5.0"`. For other result types, `value` can contain comparators, text, boolean-like values, durations, percentages, or ratios. Use `type` before deciding how to parse or display the value. | Type | Example `value` | Notes | | ------------ | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `numeric` | `"90"`, `"1e-3"` | Numeric result encoded as a string. Use `units` for measurement units. | | `range` | `"<5"`, `">=10"`, `"≀1e-3"`, `"3-7"` | May include comparators, approximate values, scientific notation, or lower-to-upper range notation. Do not parse as a plain float. | | `comment` | `"Positive"`, `"See note"` | Textual result or observation. | | `boolean` | `"true"`, `"false"`, `"yes"`, `"no"`, `"positive"`, `"negative"` | Boolean or presence-style findings can vary by report wording. | | `duration` | `"3h"`, `"12 min"`, `"10:00"` | Duration-like values are preserved as strings because reports can use different formats. | | `percentage` | `"5.4%"` | Inferred when the value includes `%`. If the value is `"5.4"` and `units` is `%`, the result may be returned as `numeric`; read `value`, `type`, and `units` together. | | `ratio` | `"97/100"` | Slash-form ratios are inferred when `type` is not already supplied. Other ratio-like formats, such as colon-form titers, may be returned as `comment`. | The parser output is optimized to preserve what was reported. Store the raw `value` string and derive typed values in your application only after checking `type`, `units`, and reference range fields. The parser-specific `type` values are related to, but not identical to, the order result `ResultType` values documented in [Result Formats](/lab/results/result-formats#resulttype). Parser results currently include `numeric`, `range`, `comment`, `boolean`, `duration`, `percentage`, and `ratio`. When `type` is not supplied by extraction, Junction infers it from `value`. For example, `"<50"`, `"β‰₯2000"`, and `"10-20"` are inferred as `range`; `"20%"` is inferred as `percentage`; `"97/100"` is inferred as `ratio`; and unrecognized text is inferred as `comment`. ## Reference Ranges and Interpretation The parser may extract `min_reference_range` and `max_reference_range` as numeric bounds when the report includes a parseable reference range. It may also return: * `interpretation`: possible values are `normal`, `abnormal`, `critical`, or `unknown`. * `is_above_max_range`: whether the result is above the extracted maximum * `is_below_min_range`: whether the result is below the extracted minimum These fields depend on the quality and structure of the source report. Some reports include clear numeric bounds; others include textual ranges, age-specific ranges, sex-specific ranges, comments, or formatting that cannot be normalized into numeric bounds. For numeric values, Junction can infer whether the result is above or below the extracted numeric reference bounds. For comparator range values, Junction only sets range flags when the comparator is conclusive. For example, `">2000"` with a max reference range of `1100` is above range, but `">500"` with the same max is inconclusive. If a value is conclusively outside the extracted bounds, `interpretation` is `abnormal`. Numeric values without an out-of-range flag are interpreted as `normal`. Non-numeric and inconclusive range values are interpreted as `unknown` unless the parser extracted a more specific interpretation. If you need custom boundary logic, read the result `value`, `type`, `units`, and reference range fields together. For general order-result reference range guidance, see [Reference Range](/lab/results/reference-range-parsing). ## LOINC Matching Junction attempts to match extracted results to LOINC codes so you can compare markers across different labs and report formats. Each `loinc_matches[]` item includes: | Field | Description | | ------------------ | ------------------------------------------ | | `loinc_code` | LOINC code, such as `2345-7`. | | `loinc_name` | Official or normalized LOINC name. | | `display_name` | Display label for the match. | | `aliases` | Alternate names associated with the match. | | `confidence_score` | Relative score for this LOINC candidate. | `confidence_score` is a matching score for the candidate LOINC code. It is not an accuracy score for the extracted lab result, patient metadata, units, reference ranges, or interpretation. A high score means Junction's LOINC matcher found a stronger candidate for that result row than lower-scored candidates; it does not prove that the source document was parsed correctly. In most integrations, use `loinc_match_status` for workflow decisions instead of building your own thresholds on `confidence_score`. Store the score for debugging, audit, or support workflows, but avoid using it as a clinical-confidence or result-accuracy signal. Use `loinc_match_status` to decide how much review your workflow needs: | Status | Meaning | | -------------- | ----------------------------------------------------------- | | `auto_match` | Junction found a likely LOINC match. | | `needs_review` | Junction found possible matches, but review is recommended. | | `no_match` | Junction could not identify a match. | LOINC matches are not guaranteed for every extracted result. Your integration should handle `loinc_matches: null`, an empty match list, low confidence scores, `needs_review`, `no_match`, and future match statuses. ## Webhooks Subscribe to parser events to avoid polling. | Event | Trigger | | -------------------------------- | -------------------------------------------------------------- | | `lab_report.parsing_job.created` | A new parsing job was created. | | `lab_report.parsing_job.updated` | A parsing job changed status, including completion or failure. | Webhook payloads include the user, team, and parsing job: ```json Webhook payload theme={null} { "event_type": "lab_report.parsing_job.updated", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "client_user_id": "7cbd6f62-0d22-4e5f-b7fd-bc4ee5c3fd8d", "team_id": "6353bcab-3526-4838-8c92-063fa760fb6b", "data": { "id": "8eb0217f-4683-4a3c-adca-faf95ac65739", "status": "completed", "failure_reason": null, "data": { "metadata": { "patient_first_name": "Jane", "patient_last_name": "Doe", "dob": "1990-01-01", "gender": "female", "lab_name": "Acme Labs", "date_reported": "2025-01-01", "date_collected": "2024-12-30", "specimen_number": "ABC123" }, "results": [ { "test_name": "Glucose", "value": "90", "type": "numeric", "units": "mg/dL", "min_reference_range": 70, "max_reference_range": 99, "loinc_match_status": "auto_match", "loinc_matches": [ { "loinc_code": "2345-7", "loinc_name": "Glucose [Mass/volume] in Serum or Plasma", "display_name": "Glucose", "aliases": [], "confidence_score": 0.99 } ], "interpretation": "normal", "is_above_max_range": false, "is_below_min_range": false } ] }, "needs_human_review": false, "is_reviewed": false } } ``` For webhook delivery behavior, retries, and event structure, see [Webhooks](/webhooks/introduction). ## Sandbox Limits Sandbox lab report parsing has a team-level report limit. The error response includes the configured limit for your team. For example, a team limited to 150 reports receives: ```json Error theme={null} { "detail": "Sandbox lab report parsing is limited to 150 reports. Please upgrade your contract to continue." } ``` This is a sandbox usage limit, not a file-level validation error. Retrying the same request, creating more users, or changing the report file does not reset the limit. Contact your account manager or [support@junction.com](mailto:support@junction.com) if you need the limit increased for higher-volume testing or production access. ## Integration Guidance Build your parser integration defensively: * Keep the original report file or a pointer to it in your system for audit and reprocessing workflows. * Store `data.results[].value` as a string, even when `type` is `numeric`. * Treat parser enums as non-exhaustive and log unknown `status`, `type`, `failure_reason`, `sample_type`, `measurement_kind`, and `loinc_match_status` values. * Do not require LOINC matches to be present before displaying the extracted result to users. * Review low-confidence or `needs_review` LOINC matches before using them for clinical decisioning, cohort logic, or automated recommendations. * Expect null metadata and null reference range fields when the source report does not include parseable values. * Use webhooks for normal processing and keep polling as a fallback for missed events or manual support flows. ## API Reference * [Create Lab Report Parser Job](/api-reference/lab-testing/lab-report-parsing/post-lab-report-parser-job) * [Get Lab Report Parser Job](/api-reference/lab-testing/lab-report-parsing/get-lab-report-parser-job) * [Lab Report Parsing Job Created](/event-catalog/lab_report.parsing_job.created) * [Lab Report Parsing Job Updated](/event-catalog/lab_report.parsing_job.updated) # Critical Results Source: https://docs.junction.com/lab/results/critical-results Understand how Junction categorizes lab result markers as normal, abnormal, or critical, and receive webhook alerts for critical findings. When our Lab partners return results to Junction, they may return specific interpretations for each Marker: * `normal`, the marker value is inside the lab reference range. * `abnormal`, the marker value is outside the lab reference range. * `critical`, the marker value falls in the critical range for that marker, which can be life-threatening. These values are returned in an `interpretation` field for results, both in each individual marker and the overall results object: ```json Results Object theme={null} { "metadata": { "age": 19, "dob": "18/08/1993", "clia_number": "12331231", "patient": "Bob Smith", "provider": "Dr. Jack Smith", "laboratory": "LabCorp", "date_reported": "2020-01-01", "date_collected": "2022-02-02", "specimen_number": "123131", "date_received": "2022-01-01", "status": "final", "interpretation": "critical" }, "results": [ { "name": "Hemoglobin", "slug": "hemoglobin", "unit": "g/dL", "notes": null, "value": 100.2, "timestamp": null, "max_range_value": 17.7, "min_range_value": 13.0, "is_above_max_range": true, "is_below_min_range": false, "interpretation": "critical" }, { "name": "Sodium", "slug": "unknown", "unit": "mmol/L", "notes": null, "value": 136, "timestamp": null, "max_range_value": 144, "min_range_value": 134, "is_above_max_range": false, "is_below_min_range": false, "interpretation": "normal" } ] } ``` Besides the `interpretation` field, there is also the `status` field, which can assume the values of `final` or `partial`, as critical results are reported as soon as they're available; not all tests are guaranteed to have been processed by the lab. For critical results, the laboratory will contact a physician, so they can provide further information to the patient. The physician called is the Junction-assigned physician. They act as the ordering physician when placing the order. After the call is made, and Junction has received the results from the laboratory, a `labtest.result.critical` event is sent. The webhook payload contains the following information: ```json Critical Results Webhook Payload theme={null} { "data": { "created_at": "2023-09-04T19:02:33.042533+00:00", "updated_at": "2023-09-04T19:02:47.106778+00:00", "order_id": "93ae03a7-626f-4cf4-802b-1fb6b3c339c7", "sample_id": "W4123LKB3VTL", "status": "final", "interpretation": "critical", "team_id": "482gh249-cd9d-4049-bb42-db5682cdf1d2", "user_id": "db5d34d5-bf7b-4e25-b119-9asd53694f45" }, "event_type": "labtest.result.critical" } ``` After you receive the webhook, you can use the [`GET /order/{order_id}/result`](/api-reference/lab-testing/results/get-results) endpoint to fetch the raw results. You can test the webhook event by using the [Junction Dashboard](https://app.junction.com) Webhooks section, where you can register an endpoint and subscribe to the `labtest.result.critical` event. The following image shows what the screen should look like after you have an endpoint registered and have selected the `Testing` section inside the endpoint configurations. You can then click the `Send Example` button and should receive an HTTP call in the registered URL. # Follow-ups Source: https://docs.junction.com/lab/results/follow-up Learn how Junction's physician network handles follow-up communications with patients who receive abnormal lab test results. When the test results are ready, you will receive a `labtest.order.updated` webhook where the order has a `completed` status. That means the results are ready and can be [fetched](/lab/results/result-formats). In case of abnormal results, our physician will determine if a call with the patient is required, and if so, they will follow up to figure out the next steps. Please keep in mind that the follow-up call with the patient only happens for orders processed by our physician network. If you provided your own physician when you placed the order, you will be responsible for following up with your patients. # Galleri Multi-Cancer Early Detection Results (GRAIL) Source: https://docs.junction.com/lab/results/galleri-results Understand the unique result structure for the Galleri multi-cancer early detection test, which returns coded enum values instead of numeric biomarkers. ## Overview The Galleri test (by GRAIL) is a multi-cancer early detection blood test available exclusively through the Quest lab provider. Unlike standard lab biomarkers that return numeric values with reference ranges, Galleri results use coded values (enums) to indicate cancer detection status, predicted cancer signal origin, and anatomical subcategories. ## Result Structure Comparison ### Standard Numeric Biomarker Result Typical lab results for biomarkers like cholesterol follow this structure: ```json theme={null} { "name": "Total Cholesterol", "slug": "total-cholesterol", "type": "numeric", "result": "195", "value": 195, "unit": "mg/dL", "reference_range": "< 200", "min_range_value": null, "max_range_value": 200, "is_above_max_range": false, "is_below_min_range": false, "interpretation": "normal", "timestamp": "2024-01-15T10:30:00Z", "loinc": "2093-3", "loinc_slug": "cholesterol-total-serum-plasma", "provider_id": "001347", "notes": null, "source_sample_id": "12345678" } ``` Notice the `type` is `"numeric"`, the `result` contains a numeric string, `value` contains the actual number, and `unit` specifies the measurement unit. ### Galleri Result - No Cancer Signal Detected When no cancer signal is detected, you receive a single result: ```json theme={null} { "name": "Galleri Multi-Cancer Early Detection", "slug": "galleri-cancer-signal", "type": "coded_value", "result": "NOT_DETECTED", "value": -1, "unit": null, "reference_range": null, "min_range_value": null, "max_range_value": null, "is_above_max_range": null, "is_below_min_range": null, "interpretation": "normal", "timestamp": "2024-01-15T10:30:00Z", "loinc": null, "loinc_slug": null, "provider_id": "86038987", "notes": null, "source_sample_id": "12345678" } ``` ### Galleri Results - Cancer Signal Detected When a cancer signal is detected, you receive **multiple related biomarker results** that provide detailed information about the detection: #### 1. Cancer Signal Detection ```json theme={null} { "name": "Galleri Cancer Signal", "slug": "galleri-cancer-signal", "type": "coded_value", "result": "DETECTED", "value": -1, "unit": null, "reference_range": null, "min_range_value": null, "max_range_value": null, "is_above_max_range": null, "is_below_min_range": null, "interpretation": "critical", "timestamp": "2024-01-15T10:30:00Z", "loinc": null, "loinc_slug": null, "provider_id": "86038987", "notes": null, "source_sample_id": "12345678" } ``` #### 2. Cancer Signal Origin ```json theme={null} { "name": "Galleri Cancer Signal Origin", "slug": "galleri-cancer-origin", "type": "coded_value", "result": "HEAD_AND_NECK", "value": -1, "unit": null, "reference_range": null, "min_range_value": null, "max_range_value": null, "is_above_max_range": null, "is_below_min_range": null, "interpretation": "critical", "timestamp": "2024-01-15T10:30:00Z", "loinc": null, "loinc_slug": null, "provider_id": "86038987_1", "notes": null, "source_sample_id": "12345678" } ``` #### 3. Cancer Signal Subcategory ```json theme={null} { "name": "Galleri Cancer Signal Subcategory", "slug": "galleri-cancer-subcategory", "type": "coded_value", "result": "OROPHARYNX_HYPOPHARYNX_NASOPHARYNX_LARYNX_LIP_AND_ORAL_CAVITY_INCLUDING_ORAL_TONGUE_NASAL_CAVITY_PARANASAL_SINUSES_MAJOR_SALIVARY_GLANDS", "value": -1, "unit": null, "reference_range": null, "min_range_value": null, "max_range_value": null, "is_above_max_range": null, "is_below_min_range": null, "interpretation": "critical", "timestamp": "2024-01-15T10:30:00Z", "loinc": null, "loinc_slug": null, "provider_id": "86038987_2", "notes": null, "source_sample_id": "12345678" } ``` #### 4. Additional Information (Comment) ```json theme={null} { "name": "Galleri Additional Information", "slug": "galleri-comment-1", "type": "comment", "result": "Squamous Cell Signal of Head and Neck, Lung, and Esophagus", "value": -1, "unit": null, "reference_range": null, "min_range_value": null, "max_range_value": null, "is_above_max_range": null, "is_below_min_range": null, "interpretation": "critical", "timestamp": "2024-01-15T10:30:00Z", "loinc": null, "loinc_slug": null, "provider_id": "86038987_3", "notes": "Squamous Cell Signal of Head and Neck, Lung, and Esophagus", "source_sample_id": "12345678" } ``` ## Key Differences from Standard Biomarkers Understanding these differences is crucial for proper integration: ### Result Type * **Standard biomarkers**: `type` is `"numeric"` or `"range"` * **Galleri results**: `type` is `"coded_value"` or `"comment"` ### Result Field * **Standard biomarkers**: Contains numeric values as strings (e.g., `"195"`, `"<1.2"`) * **Galleri results**: Contains enum constant names in uppercase with underscores (e.g., `"DETECTED"`, `"HEAD_AND_NECK"`) ### Value Field * **Standard biomarkers**: Contains actual numeric value (e.g., `195`) * **Galleri results**: Always `-1` (placeholder value; actual information is in the `result` field) The `value` field is deprecated and will eventually be removed. For Galleri results, always use the `result` field to extract meaningful information. ### Unit Field * **Standard biomarkers**: Contains measurement units (e.g., `"mg/dL"`, `"mmol/L"`) * **Galleri results**: Always `null` ### Interpretation Field * **Standard biomarkers**: Can be `"normal"`, `"abnormal"`, or `"critical"` based on reference ranges * **Galleri results**: `"normal"` when not detected, `"critical"` when cancer signal detected ### Result Multiplicity * **Standard biomarkers**: Typically one result per biomarker tested * **Galleri positive results**: Multiple related results (signal + origin + subcategory + comments) ### Provider ID Pattern Galleri results use a consistent `provider_id` pattern to distinguish between the different related results: * `"86038987"` - Base cancer signal detection result * `"86038987_1"` - Cancer signal origin * `"86038987_2"` - Cancer signal subcategory * `"86038987_3"` - Additional information/comments ## Enum Value Reference ### Galleri Cancer Signal **Description**: Indicates whether a cancer signal was detected in the Galleri test. **Field**: `BiomarkerResult.result` when `type` is `"coded_value"` and `provider_id` is `"86038987"` **Possible Values**: ``` DETECTED NOT_DETECTED ``` ### Galleri Cancer Origin **Description**: When a cancer signal is detected, indicates the predicted tissue of origin for the cancer signal. This represents the general anatomical location or cell lineage where the cancer may have originated. **Field**: `BiomarkerResult.result` when `type` is `"coded_value"` and `provider_id` is `"86038987_1"` **Possible Values** (21 total): ``` ANUS BLADDER_UROTHELIAL_TRACT BREAST CERVIX COLON_RECTUM HEAD_AND_NECK KIDNEY LIVER_BILE_DUCT LUNG NEUROENDOCRINE_CELLS_OF_LUNG_OR_OTHER_ORGANS LYMPHOID_LINEAGE MELANOCYTIC_LINEAGE MYELOID_LINEAGE OVARY PANCREAS_GALLBLADDER PLASMA_CELL_LINEAGE PROSTATE BONE_AND_SOFT_TISSUE THYROID_GLAND STOMACH_ESOPHAGUS UTERUS ``` ### Galleri Cancer Subcategory **Description**: Provides a more specific anatomical classification of the predicted cancer signal origin, with additional detail about the specific organs or tissue types involved. **Field**: `BiomarkerResult.result` when `type` is `"coded_value"` and `provider_id` is `"86038987_2"` **Possible Values** (21 total): ``` ANUS BLADDER_RENAL_PELVIS_URETER_URETHRA BREAST CERVIX COLON_RECTUM_APPENDIX OROPHARYNX_HYPOPHARYNX_NASOPHARYNX_LARYNX_LIP_AND_ORAL_CAVITY_INCLUDING_ORAL_TONGUE_NASAL_CAVITY_PARANASAL_SINUSES_MAJOR_SALIVARY_GLANDS KIDNEY LIVER_INTRAHEPATIC_BILE_DUCT LUNG_BRONCHUS NEUROENDOCRINE_CELLS_OF_LUNG_OR_OTHER_ORGANS LYMPHOID_LINEAGE MELANOCYTIC_LINEAGE MYELOID_LINEAGE OVARY_FALLOPIAN_TUBE_PRIMARY_PERITONEUM PANCREAS_EXTRAHEPATIC_BILE_DUCT_GALLBLADDER PLASMA_CELL_LINEAGE PROSTATE SKELETAL_MUSCLE_AND_OTHER_CONNECTIVE_TISSUE_VASCULAR_TISSUE_BONE_AND_CARTILAGE THYROID_GLAND STOMACH_ESOPHAGUS UTERUS ``` ## Integration Tips ### Identifying Galleri Results Galleri results can be identified in the API response by: 1. The `type` field will be `"coded_value"` or `"comment"` 2. The `provider_id` will start with `"86038987"` 3. The slug values will be: `"galleri-cancer-signal"`, `"galleri-cancer-origin"`, or `"galleri-cancer-subcategory"` ### Handling Multiple Related Results When a cancer signal is detected, you will receive multiple related biomarker results that should be grouped and displayed together. The `provider_id` field distinguishes between them: * `"86038987"` - The main cancer signal detection result * `"86038987_1"` - The predicted origin of the cancer signal * `"86038987_2"` - The specific subcategory with detailed anatomical information * `"86038987_3"`, `"86038987_4"`, etc. - Additional information and comments # Reference Range Source: https://docs.junction.com/lab/results/reference-range-parsing Parse the reference_range string field in lab results to determine boundary inclusivity and build custom result interpretation logic. The Junction API already returns the `interpretation` field (e.g., "normal", "abnormal", "critical") in the [`BiomarkerResult`](/lab/results/result-formats#biomarkerresult) object. This documentation is intended for teams that want to build their own interpretation logic and need to parse the `reference_range` field along with `min_range_value` and `max_range_value` to determine whether results are within normal limits. The `reference_range` field in Order results contains a string representation of the normal range for a lab test result. This field is critical for determining whether a result is within normal limits, but it requires parsing to understand the inclusivity/exclusivity of boundary values. ## Why Parsing is Needed The `min_range_value` and `max_range_value` fields contain the boundary numbers from the lab, but they **do not indicate whether those boundaries are inclusive or exclusive**. This information is only available in the `reference_range` string, which requires parsing to determine the correct comparison operator. ### Example For a result with: * `reference_range`: `"<5.7"` * `max_range_value`: `5.7` * `min_range_value`: None * `result`: `"5.7"` Without knowing the inclusivity, you cannot determine if `5.7` is normal or abnormal. The boundary value `5.7` is the same whether the range is `<=5.7` (inclusive, normal) or `<5.7` (exclusive, abnormal). You must parse the `reference_range` string to know which operator to use. ## Reference Range Formats The `reference_range` field can appear in several formats: ### 1. Comparison Operators Single-bound comparisons using standard operators: * `<5` - Less than 5 (exclusive upper bound) * `<=10.5` - Less than or equal to 10.5 (inclusive upper bound) * `>3` - Greater than 3 (exclusive lower bound) * `>=7.25` - Greater than or equal to 7.25 (inclusive lower bound) ### 2. Range Notation Two-bound ranges using hyphen notation: * `1-10` - Between 1 and 10 (both inclusive) * `3.5-7.8` - Between 3.5 and 7.8 (both inclusive) **Note:** Range notation (with hyphen) typically indicates both bounds are inclusive. ### 3. Alternative Comparison Syntax Some labs use alternative syntax: * `< OR = 9.9` - Less than or equal to 9.9 (inclusive upper bound) * `> OR = 2` - Greater than or equal to 2 (inclusive lower bound) These are case-insensitive (`< or = 9.9` is equivalent). ## Parsing Strategy Parse the `reference_range` string to extract: * Lower bound value (if present) * Upper bound value (if present) * Whether each bound is inclusive or exclusive The parsed information, combined with `min_range_value` and `max_range_value`, determines the correct comparison operators for evaluating whether results are within the normal range. ## Example Implementation Here's an example implementation showing how to parse the `reference_range` field: This example uses Python's `re` module for regular expression matching. ```python theme={null} import re def parse_reference_range(reference_range_string): # Pattern 1: Handle comparison operators: <5, <=10.5, >3, >=7.25 comparison_match = re.match(r"([<>]=?)(\d+(\.\d+)?)", reference_range_string) if comparison_match: comparison_operator, boundary_value, _ = comparison_match.groups() boundary_value_float = float(boundary_value) if comparison_operator in ["<", "<="]: # Upper bound: < or <= return { "lower_bound": None, "upper_bound": boundary_value_float, "lower_included": False, "upper_included": comparison_operator == "<=", # <= is inclusive, < is exclusive } else: # > or >= # Lower bound: > or >= return { "lower_bound": boundary_value_float, "upper_bound": None, "lower_included": comparison_operator == ">=", # >= is inclusive, > is exclusive "upper_included": False, } # Pattern 2: Handle range notation: 1-10, 3.5-7.8 range_match = re.match(r"(\d+(\.\d+)?)-(\d+(\.\d+)?)", reference_range_string) if range_match: lower_bound_str, _, upper_bound_str, _ = range_match.groups() return { "lower_bound": float(lower_bound_str), "upper_bound": float(upper_bound_str), "lower_included": True, # Range notation is always inclusive on both sides "upper_included": True, } # Pattern 3: Handle alternative comparison syntax: < OR = 9.9, > OR = 2 alternative_match = re.match(r"([<>]) OR = (\d+(\.\d+)?)", reference_range_string, re.IGNORECASE) if alternative_match: comparison_operator, boundary_value, _ = alternative_match.groups() boundary_value_float = float(boundary_value) if comparison_operator == "<": # < OR = means <= (inclusive upper bound) return { "lower_bound": None, "upper_bound": boundary_value_float, "lower_included": False, "upper_included": True, } else: # > # > OR = means >= (inclusive lower bound) return { "lower_bound": boundary_value_float, "upper_bound": None, "lower_included": True, "upper_included": False, } # If no pattern matches, return empty bounds return { "lower_bound": None, "upper_bound": None, "lower_included": False, "upper_included": False, } ``` This code should be used as a starting point and not directly used in production. It demonstrates parsing logic for the formats shown in this documentation, but may not handle all edge cases or variations that labs might use. For example, it does not cover signed ranges (e.g., `-5.0 - +2.0`) or other format variations. You should thoroughly test and extend this implementation based on your specific needs. ## Parsing Examples Here are examples of what the above parsing function returns for different `reference_range` formats: ### Example 1: Exclusive Upper Bound ```python theme={null} reference_range_string = "<5.7" parsed = parse_reference_range(reference_range_string) # Returns: { # "lower_bound": None, # "upper_bound": 5.7, # "lower_included": False, # "upper_included": False # < means exclusive # } ``` ### Example 2: Inclusive Upper Bound ```python theme={null} reference_range_string = "<=5.7" parsed = parse_reference_range(reference_range_string) # Returns: { # "lower_bound": None, # "upper_bound": 5.7, # "lower_included": False, # "upper_included": True # <= means inclusive # } ``` ### Example 3: Range with Both Bounds ```python theme={null} reference_range_string = "2.6-24.9" parsed = parse_reference_range(reference_range_string) # Returns: { # "lower_bound": 2.6, # "upper_bound": 24.9, # "lower_included": True, # Range notation is inclusive # "upper_included": True # } ``` ### Example 4: Lower Bound Only ```python theme={null} reference_range_string = ">3.0" parsed = parse_reference_range(reference_range_string) # Returns: { # "lower_bound": 3.0, # "upper_bound": None, # "lower_included": False, # > means exclusive # "upper_included": False # } ``` ### Example 5: Alternative Syntax ```python theme={null} reference_range_string = "< OR = 9.9" parsed = parse_reference_range(reference_range_string) # Returns: { # "lower_bound": None, # "upper_bound": 9.9, # "lower_included": False, # "upper_included": True # < OR = means <= (inclusive) # } ``` # Result Formats Source: https://docs.junction.com/lab/results/result-formats Retrieve lab test results in two formats: raw PDF reports from partner labs and structured JSON data through the Junction API. Junction's API returns results in two different formats. * `PDF` * `JSON` ## PDF Results We return the raw results in PDF form that we receive directly from our partner labs. This can be retrieved as follows: ```bash Get order results PDF theme={null} curl --request GET \ --url {{BASE_URL}}/v3/order/{order_id}/result/pdf \ --header 'Accept: application/json' \ --header 'Content-Type: application/pdf' \ --header 'x-vital-api-key: ' ``` Some laboratories do not issue PDFs for partial results, and only provide PDF reports once all results are finalized. An example result: ## JSON Results We also return the parsed results in JSON format, so you can use them to generate your own forms. These results are returned in a structured format, which you can find [here](/api-reference/lab-testing/results/get-results). The `results` field, according to the spec, can return either a `list[BiomarkerResult]` or an untyped `dict`. This is due to backwards compatibility, and you can disregard the untyped `dict`. ### Result Status The `status` field can be one of the following: 1. `ResultStatus.PARTIAL` - The results are partial. Labs can return results before all biomarkers are available. Junction makes these results available to you as soon as we receive them, but does not send a webhook notification for `partial` results. This means that if you probe the API for results, you might get a `partial` result, even if there was no webhook for a `labtest.order.updated` event. This is done due to the possibility of [critical values](/lab/results/critical-results) in the results. 2. `ResultStatus.FINAL` - The results are complete. This means that all biomarkers are available, and the results are final. You will receive a `labtest.order.updated` webhook notification for this event. ### BiomarkerResult A `BiomarkerResult` has the following definition: ```python theme={null} name: str slug: str value: float # deprecated result: str type: ResultType unit: str | None timestamp: datetime | None notes: str | None reference_range: str | None min_range_value: float | None max_range_value: float | None is_above_max_range: bool | None is_below_min_range: bool | None interpretation: str = Interpretation.NORMAL loinc: str | None loinc_slug: str | None provider_id: str | None source_markers: List[ParentBiomarkerData] | None ``` #### ResultType Results can fall into one of the following categories: 1. `ResultType.NUMERIC` - A numeric result, e.g., `1.2` In this case, the `result` field will be a string representation of the number, and the `value` field will be a float representation of the number. 2. `ResultType.RANGE` - A range result, e.g., `<1.2` In this case, the `result` field will be a string representation of the range value, and the `value` field will be `-1`. Note that you will also find the `<1.2` value in the `notes` field. A range result will always be a value following the pattern `^([<>]=?\d*(\.\d+)?|(\d*(\.\d+)?-\d*(\.\d+)?))$`. 3. `ResultType.COMMENT` - A text result, e.g., `Positive` In this case, the `result` field will be a string representation of the text, and the `value` field will be `-1`. Note that you will also find the `Positive` value in the `notes` field. 4. `ResultType.CODED_VALUE` - A coded value result using enum constants, e.g., `DETECTED`, `HEAD_AND_NECK` In this case, the `result` field will be an enum constant name, and the `value` field will be `-1`. This type is used for specialized tests like the Galleri multi-cancer early detection test. See the [Galleri Results](/lab/results/galleri-results) documentation for detailed information. The `value` field is deprecated and will eventually be removed. #### Interpretation Interpretation is a string value that can be one of the following: 1. `Interpretation.NORMAL` - The result is within normal parameters. 2. `Interpretation.ABNORMAL` - The result is outside of normal parameters. 3. `Interpretation.CRITICAL` - The result is outside of critical parameters. In this case, refer to the [critical values](/lab/results/critical-results) section. #### Standardization - LOINC It's possible to test the same biomarkers across different laboratories. For these to match, we use the [LOINC](https://loinc.org/) standard. In the `BiomarkerResult` object, you can see two fields `loinc_slug` and `loinc`. These fields refer to the LOINC standard. Customers should use this standard, so it's possible to match results across different laboratories. You can expect that the `slug` field is what the laboratory returns to us - and the `loinc_slug` is the standardized version. An example: | Lab | Slug | LOINC | LOINC Slug | | ------- | --------------- | ------ | --------------------------- | | Labcorp | hdl-cholesterol | 2085-9 | cholesterol-in-hdl-mass-vol | | USSL | hdl | 2085-9 | cholesterol-in-hdl-mass-vol | As you can see, the same biomarker `HDL Cholesterol` can have different slugs across different laboratories. However, it's represented by the same LOINC value. LOINC codes may be missing in some results due to our LOINC compendium still being expanded and updated, labs providing data in formats our system does not recognize, or labs not including LOINC codes in their data at all. We are actively improving both the completeness of our compendium and our ability to interpret data variations, but missing LOINCs can still occur. Integrations should be built to handle cases where LOINC codes are not guaranteed. #### Expected Results When ordering a `lab_test`, you can see which `markers` each test orders. These can either be `panels` composed of multiple `biomarkers` or just individual `biomarkers`. This means that a `lab_test` with only one associated `marker`, such as `Lipid Panel`, can return multiple `result markers`. We call these expected results. Each `marker` can thus be composed of multiple `expected results` which match to a `loinc`. As an example, here's the expected results for the `Lipid Panel` marker: ```json theme={null} "expected_results":[ { "id":1108, "name":"VLDL Cholesterol Cal", "slug":"vldl-cholesterol-cal", "lab_id":6, "provider_id":"011919", "loinc":{ "id":5062, "name":"Cholesterol in VLDL Calc [Mass/Vol]", "slug":"cholesterol-in-vldl-calc-mass-vol", "code":"13458-5", "unit":"mg/dL" } }, { "id":1109, "name":"Cholesterol, Total", "slug":"cholesterol-total", "lab_id":6, "provider_id":"001065", "loinc":{ "id":11940, "name":"Cholesterol [Mass/Vol]", "slug":"cholesterol-mass-vol", "code":"2093-3", "unit":"mg/dL" } }, { "id":1110, "name":"HDL Cholesterol", "slug":"hdl-cholesterol", "lab_id":6, "provider_id":"011817", "loinc":{ "id":11858, "name":"Cholesterol in HDL [Mass/Vol]", "slug":"cholesterol-in-hdl-mass-vol", "code":"2085-9", "unit":"mg/dL" } }, { "id":1112, "name":"Triglycerides", "slug":"triglycerides", "lab_id":6, "provider_id":"001172", "loinc":{ "id":16384, "name":"Triglyceride [Mass/Vol]", "slug":"triglyceride-mass-vol", "code":"2571-8", "unit":"mg/dL" } }, { "id":1113, "name":"LDL Chol Calc (NIH)", "slug":"ldl-chol-calc-nih", "lab_id":6, "provider_id":"012059", "loinc":{ "id":5060, "name":"Cholesterol in LDL Calc [Mass/Vol]", "slug":"cholesterol-in-ldl-calc-mass-vol", "code":"13457-7", "unit":"mg/dL" } } ] ``` You can use this information to verify if the final results are composed of all expected results. In order to obtain this data, you can use the following endpoints: 1. [GET /v3/lab\_tests/markers](/api-reference/lab-testing/biomarkers) This allows you to search markers based on laboratory or name. 2. [GET /v3/lab\_tests/\{id}/markers](/api-reference/lab-testing/lab-test-markers) This allows you to see all markers associated with a lab test and its expected results. #### Source Markers As mentioned above, a marker can be composed of one or more results. This means that if you order a `Lipid Panel`, there will be no `Lipid Panel` result returned, but instead a series of markers that originate from the `Lipid Panel`. Junction identifies the source marker via the `source_markers` field. ```json theme={null} { "name": "Sex Horm Binding Glob, Serum", "slug": "sex-horm-binding-glob-serum", "value": 30.4, "result": "30.4", "type": "numeric", "unit": "nmol/L", "timestamp": "2024-10-31T09:08:00+00:00", "notes": "Final", "min_range_value": 24.6, "max_range_value": 122, "is_above_max_range": false, "is_below_min_range": false, "interpretation": "normal", "loinc": "13967-5", "loinc_slug": "sex-hormone-binding-globulin-moles-vol", "provider_id": "082016", "source_markers": [ { "marker_id": 229, "name": "Testosterone Free, Profile I", "slug": "testosterone-free-profile-i", "provider_id": "140226" } ] }, ``` When Junction cannot identify the source, then this field will be `null`, indicating that this is an unsolicited result. There may also be more than one `source` marker, if there are two or more ordered markers that contain the same underlying result, using the same testing method. #### Missing Results At times, labs will make mistakes, and expected results will be missing. Junction identifies these and parses them into a separate structure, named `missing_results`. This data has the following format: ```python theme={null} name: str slug: str inferred_failure_type: FailureType note: str | None = None loinc: str | None = None loinc_slug: str | None = None provider_id: str | None = None source_markers: List[ParentBiomarkerData] | None = None ``` `inferred_failure_type` is the Junction-assigned error type. The error type is inferred from the comments received from the lab. They are to help assess possible root causes of missing results, and aid the customer in identifying issues in aggregate. The way that we infer these error types is subject to change as we continue to refine and achieve a more granular understanding of failure modes. 1. `quantity_not_sufficient_failure` The lab could not process this result due to an insufficient quantity of collected sample. This could be due to the patient refusing to collect more, the phlebotomist being unable to collect the proper volume of blood from the patient, or the phlebotomist not collecting all of the sample they were meant to collect. 2. `collection_process_failure` This is indicative of potential failures to follow the entire phlebotomy process, often immediately following the collection. For example, improper centrifugation of the collected sample or improper refrigeration. While these are the most likely causes, there are other reasons why sample quality may have been degraded. 3. `drop_off_failure` This speaks to a specific form of collection process failures. Specifically, the sample was not received by the lab in proper condition. Possible issues correspond to improper freezing, refrigeration, or exposure to excessive transport delay. 4. `internal_lab_failure` This speaks to failures that are most likely to have happened internally at the lab. This includes issues such as misplacing a collected sample, or errors that could not best be attributed to any external cause. 5. `order_entry_failure` The test was not performed because it was not properly ordered at the lab. 6. `non_failure` This speaks to a failure that should not impact the patient. For example, it may indicate that a duplicate test was ordered. 7. `unknown_failure` This is a failure that could not be properly attributed to any specific failure mode. Potentially the results were simply left out and Junction was not provided any additional information. 8. `patient_condition_failure` This speaks to a failure to result due to specifics of the patient's physical condition. For example, the patient may have had some food very high in fats immediately prior to a collection. It is possible that improper storage and handling can cause samples to fail in ways that appear to be a patient condition failure. 9. `missing_result_calc_failure` This failure indicates that a calculated field is missing because the underlying tests required to perform the calculation were either unable to be processed, or yielded a result outside of the allowable parameters to perform the calculation. 10. `missing_demo_aoe_calc_failure` Some results may require additional information β€” such as age β€” reported in AOE (ask on order entry) in order to be properly calculated. # Communications Source: https://docs.junction.com/lab/testkits/communications Configure SMS notifications sent to patients during each status change in the at-home testkit order lifecycle. Communication for patients is done via SMS for At-home Testkit orders. Customers have the following options when setting this up: * `Default` - SMS communications are enabled. * `Disable` - All communications from Junction are disabled. Each option has a different set of content and status changes, depending on what triggered them. You can enable or disable SMS individually through the [**Junction Dashboard**](https://app.junction.com/), under the Team Settings section. ## Default Communications ### SMS Messages A table of the **Order Status** and **default SMS** is provided below: | Order Status | Default Message | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `ordered` | Hey **receiver\_name**, your order for the **team\_name** health kit has been placed! We'll update you with where it is in the process via messages :) | | `transit_customer` | Your order for the **team\_name** test kit is in transit, and should be arriving by **eta**. | | `out_for_delivery` | Your order for the **team\_name** test kit is out for delivery, and should be arriving by today. | | `delivered_to_lab` | Your test kit has arrived at our labs. We're processing your sample now! | | `completed` | The lab has finished processing your test kit, your results should be ready soon :) | | `cancelled` | Hey, your order for the **team\_name** test kit has been cancelled. If this is by accident, please contact support. | SMS Texts are customizable, and can be enabled or disabled individually. ### Emails We do not send emails for At-home Testkits. ## Disable Communications In this case, no communications will be sent from Junction. You have the ability to produce completely customized communications using the [`Webhook events`](/lab/testkits/webhooks) described previously. # Order Lifecycle Source: https://docs.junction.com/lab/testkits/order-lifecycle Reference for all order lifecycle statuses in the at-home testkit flow, including shipping, sample collection, and lab processing stages. The **At-Home Testkit** can be composed of two distinct **Order** lifecycles, which we detail below. ## Order Lifecycle As discussed in [`Lab Test Lifecycle - Statuses`](/lab/workflow/lab-test-lifecycle#statuses), each lab testing modality has the following format: `[HIGH-LEVEL STATUS].[TEST MODALITY].[LOW-LEVEL STATUS]` For each modality, there can be multiple **low-level statuses**, for **At-Home Testkit** the possible low-level statuses are: ### Registered Testkits * `ordered`: Junction received the order, stored it into our system, and started processing it asynchronously. * `requisition_created`: An order requisition form was validated and created with the partner laboratory, making the order available to be carried out. * `requisition_bypassed`: An order requisition form wasn't created when the order was placed with us because it already existed. * `transit_customer`: The testkit is shipped and in transit to the customer. * `out_for_delivery`: The testkit is out for delivery. * `with_customer`: The testkit is delivered to the customer. * `transit_lab`: The customer has sent the testkit back to the lab. * `delivered_to_lab`: The lab has received the testkit. * `failure_to_deliver_to_customer`: The shipping company was unable to deliver the testkit to the customer. * `failure_to_deliver_to_lab`: The shipping company was unable to deliver the testkit to the lab. * `problem_in_transit_customer`: The shipping company encountered a problem while delivering the testkit to the customer. * `problem_in_transit_lab`: The shipping company encountered a problem while delivering the testkit to the lab. * `lab_processing_blocked`: The lab encountered an issue while processing the sample. * `sample_error`: The collected sample was unprocessable by the lab. * `completed`: The laboratory processed the blood sample and final results are available. * `cancelled`: The order was cancelled by either the patient, Junction, or you. The Finite State Machine that defines the possible transitions for the low-level statuses described above is illustrated in the following diagram. ### Registrable Testkits * `ordered`: Junction received the order, stored it into our system, and started processing it asynchronously. * `awaiting_registration`: Order is created but no user has been registered yet. * `transit_customer`: The testkit is shipped and in transit to the customer. * `out_for_delivery`: The testkit is out for delivery. * `with_customer`: The testkit is delivered to the customer. * `registered`: Order has been registered, and a requisition will be created. * `requisition_created`: An order requisition form was validated and created with the partner laboratory, making the order available to be carried out. * `transit_lab`: The customer has sent the testkit back to the lab. * `delivered_to_lab`: The lab has received the testkit. * `failure_to_deliver_to_customer`: The shipping company was unable to deliver the testkit to the customer. * `failure_to_deliver_to_lab`: The shipping company was unable to deliver the testkit to the lab. * `problem_in_transit_customer`: The shipping company encountered a problem while delivering the testkit to the customer. * `problem_in_transit_lab`: The shipping company encountered a problem while delivering the testkit to the lab. * `lab_processing_blocked`: The lab encountered an issue while processing the sample. * `sample_error`: The collected sample was unprocessable by the lab. * `completed`: The laboratory processed the blood sample and final results are available. * `cancelled`: The order was cancelled by either the patient, Junction, or you. The Finite State Machine that defines the possible transitions for the low-level statuses described above is illustrated in the following diagram.
In **sandbox**, there is no async transition from the `ordered` state to the `requisition_created` state. This must be **manually triggered** via the **Junction Dashboard**. # Overview Source: https://docs.junction.com/lab/testkits/overview Overview of the at-home testkit modality where patients receive a kit by mail, collect their own sample, and return it to the lab. At-home Testkits are one of our offered modalities. This modality involves sending a kit to a patient's home, where the patient will collect their own sample and send the kit to our Lab network through mail. Within this modality, we provide two types of testkits, those which are pre-registered to a user, and those which need to be [registered by the patient upon receiving the kit](/lab/workflow/order-registrable-testkit). ## Ordering Flow overview To achieve this, a high-level overview of the process is defined as: * An order is placed in Junction's system through our Dashboard or API. * The order is added to a background queue and additional checks are made before the kit is shipped to the provided address. * Once the order shipment is created, a requisition is generated. * After the requisition is created, some form of communication is carried out with the patient. * If the kit is not registered, then the user must register the kit before results can be provided. * The patient receives the kit, collects their sample, and sends the kit back through mail. * The Laboratory processes the patient's blood sample and generates the required results. * Junction exposes the results as soon as they are available, both as PDF and structured data via API. ## Constraints * If the testkit is unregistered, then the user must register it in order for the results to be processed. To find out more details, see [`Order Lifecycle`](/lab/testkits/order-lifecycle), [`Communications`](/lab/testkits/communications) and [`Webhooks`](/lab/testkits/webhooks). # Testkit Status Details Source: https://docs.junction.com/lab/testkits/status-details Reference for testkit order status details, including lab processing blocks and sample errors returned by the API. ## Overview When a testkit order enters a problem or blocked state, the API surfaces additional detail beyond the order event status. This page describes the named status details and what they mean. **Please note**: To ensure future compatibility, avoid exhaustive matching on status detail values. New values may be introduced over time. Handle unknown values gracefully using a default case. *** ## Lab Processing These status details apply after the lab has received the sample but cannot proceed with processing. Most are recoverable if the missing information is provided before the specimen expires. | Status Detail | Description | Permanence | Detection | | ----------------------------------- | ----------------------------------------------------------------------------------------------- | ---------- | ------------------------------- | | **Missing date of collection** | Lab received the sample but the collection date is absent. | Temporary | Programmatic (lab notification) | | **Missing documentation / ID form** | Lab received the sample but required paperwork is missing. | Temporary | Programmatic (lab notification) | | **Demographic mismatch** | Name or date of birth on the specimen does not match the order. Requires patient confirmation. | Temporary | Programmatic (lab notification) | | **NIS (Not In System)** | Lab cannot match the specimen to a known order. Requires ops investigation. May be recoverable. | Temporary | Programmatic (lab notification) | ### API field values β€” Lab Processing | Problem | `status` | `status_detail` | | ------------------------------- | ------------------------ | ------------------------------------- | | Missing date of collection | `lab_processing_blocked` | `date_of_collection_unspecified` | | Missing documentation / ID form | `lab_processing_blocked` | `demographic_information_unspecified` | | Demographic mismatch | `lab_processing_blocked` | `demographic_information_mismatch` | | NIS (Not In System) | `lab_processing_blocked` | β€” | *** ## Sample Errors These status details indicate the collected sample could not be processed by the lab. All are final β€” a new kit and recollection are required. | Status Detail | Description | Detection | | ----------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------- | | **QNS (Quantity Not Sufficient)** | Insufficient blood volume was collected. | Programmatic (lab notification) | | **Contaminated specimen** | Sample was contaminated during collection or transit. | Programmatic (lab notification) | | **Specimen too old / stability exceeded** | Too much time elapsed between collection and processing β€” sample has degraded. | Programmatic (lab notification) | | **Specimen mislabeled** | Identification discrepancy between the specimen and the requisition. Results are discarded. | Programmatic (lab notification) | | **Specimen lost by lab** | Lab reports the specimen was lost after receipt. | Programmatic (lab notification) | | **Partial results** | Lab could only process a subset of ordered tests. Remaining tests may require recollection. | Programmatic (lab notification) | ### API field values β€” Sample Errors | Problem | `status` | `status_detail` | | ------------------------------------- | -------------- | -------------------------------- | | QNS (Quantity Not Sufficient) | `sample_error` | `sample_quantity_not_sufficient` | | Contaminated specimen | `sample_error` | `sample_contaminated` | | Improper collection | `sample_error` | `sample_improper_collection` | | Specimen hemolyzed | `sample_error` | `sample_hemolyzed` | | Specimen too old / stability exceeded | `sample_error` | `sample_stability_exceeded` | | Specimen mislabeled | `sample_error` | β€” | # Webhooks Source: https://docs.junction.com/lab/testkits/webhooks Reference for webhook events triggered during at-home testkit order lifecycle changes, with example payload structures. The following webhook events are of interest when placing an At-Home Testkit order. These are described in detail in the following sections. ## Order webhook events Based on the status present in [`Order Lifecycle`](/lab/testkits/order-lifecycle), Junction will trigger two kinds of webhook events, [`labtest.order.created`](/event-catalog/labtest.order.created) and [`labtest.order.updated`](/event-catalog/labtest.order.updated). The `labtest.order.created` event is triggered when an order is created in the system, having the `ordered` status, and all subsequent status changes will trigger a `labtest.order.updated` event in the system. The webhook payload body will have the following information if the Order is in the `requisition_created` status: ```json Testkit Order Updated theme={null} { "data":{ "created_at":"2023-09-01T18:02:41.210495+00:00", "details":{ "data":{ "created_at":"2023-09-01T18:02:41.247443+00:00", "id":"3c046d74-347e-4e28-9e0d-c5b720a8e219", "shipment":{ "id":"ae0323d4-2c18-4aea-a0e7-d73b377315b1", "inbound_courier":null, "inbound_tracking_number":null, "inbound_tracking_url":null, "notes":null, "outbound_courier":null, "outbound_tracking_number":null, "outbound_tracking_url":null }, "updated_at":"2023-09-01T18:02:42.186312+00:00" }, "type":"testkit" }, "events":[ { "created_at":"2023-09-01T18:02:41.271401+00:00", "id":4056, "status":"received.testkit.ordered" }, { "created_at":"2023-09-01T18:05:12.618156+00:00", "id":4057, "status":"received.testkit.requisition_created" } ], "health_insurance_id":null, "id":"e1c380c1-7df4-487f-869e-f1be0193ca25", "lab_test":{ "fasting":false, "id":"0cb9f34f-c3df-4a13-8ca1-19429a82611b", "is_active":true, "is_delegated":false, "lab":null, "markers":null, "method":"testkit", "name":"Female General Wellness", "price":45, "sample_type":"dried_blood_spot", "slug":"general_wellness_female_002" }, "notes":null, "patient_address":{ ... }, "patient_details":{ ... }, "physician":{ ... }, "priority":false, "requisition_form_url":null, "sample_id": "some_id", "shipping_details":null, "status":"received", "team_id":"f07f59d2-2903-4bcd-a2ac-3e87fa47c4bc", "updated_at":"2023-09-01T18:02:41.210495+00:00", "user_id":"f6cdf185-6815-4b2b-9482-798b75168689", "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "active", "orders": [ { "id": "e1c380c1-7df4-487f-869e-f1be0193ca25", "created_at": "2023-09-01T18:02:41.210495+00:00", "updated_at": "2023-09-01T18:02:41.210495+00:00", "low_level_status": "requisition_created", "low_level_status_created_at": "2023-09-01T18:05:12.618156+00:00", "origin": "initial" } ] } }, "event_type":"labtest.order.updated" } ``` # Communications Source: https://docs.junction.com/lab/walk-in/communications Configure SMS and email notifications sent to patients during each status change in the walk-in lab test order lifecycle. Communication for patients is done via email or SMS for Walk-in orders. Customers have the following options when setting this up: * `Default` - Email and SMS communications are enabled. * `SMS Only or Email Only` - Only SMS or Email communication is enabled. * `Disable` - All communications from Junction are disabled. Each option has a different set of content and status changes, depending on what triggered them. You can enable or disable SMS and Email communications individually through the [**Junction Dashboard**](https://app.junction.com/), under the Team Settings section. ## Default Communications ### SMS Messages A table of the **Order Status** and **default SMS** is provided below: | Order Status | Default Message | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ordered` | *`"Hi, {patient_first_name}, your order for the {team_name} walk-in-test has been placed! We'll provide you with updates on the status of your order via text messages :)."`* | | `requisition_created` | *`"Hey {patient_first_name}, it's time to visit your local {lab_name} center. Please check the email you just received for instructions."`* | | `appointment_scheduled` | *`"Your appointment with the lab has been booked at {date} over at {address}! Here's your appointment key: {appointment_key}"`* This message is sent only for Quest orders and Quest appointments placed through Junction API. | | `appointment_cancelled` | *`"Hey, your lab appointment at {date} for {team_name} has been cancelled."`* This message is sent only for Quest orders and Quest appointments placed through Junction API. | | `redraw_available` | *`"Hi {patient_first_name}, your {team_name} results have come back with at least one missing biomarker. We recommend a redraw to complete your lab testing. We will send you an email shortly with more information."`* | | `completed` | *`"Your results have finished processing, your results should be ready soon."`* | | `cancelled` | *`"Hey, your order for the {team_name} walk-in-test has been cancelled. If this is by accident, please contact support."`* | SMS Texts are customizable, and can be enabled or disabled individually. ### Emails For emails, the following table describes what information each email contains for each Order Status: | Order Status | Email Content Description | | --------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `requisition_created` | An email with confirmation of the partner Lab and additional instructions will be sent to the patient. | | `redraw_available` | An email with confirmation of the partner Lab, missing biomarker(s) and redraw instructions will be sent to the patient. | Emails can be customized and sent from your own domain. ## Scheduling Appointments Before A Requisition Has Been Created This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. If the ability to [`schedule appointments before a requisition has been created`](/lab/walk-in/order-lifecycle#scheduling-appointments-before-a-requisition-has-been-created) is enabled for your team, all appointment-related messages will be triggered by the **appointment** status, not the **order** status. All non-appointment-related messages will be triggered by the **order** status, e.g., `requisition_created`, `completed`, etc. (see above section). ### SMS Messages A table of the **Appointment Status** and **default SMS** is provided below: | Appointment Status | Default Message | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `confirmed` | *`"Your appointment with the lab has been booked at {date} over at {address}! Here's your appointment key: {appointment_key}"`* This message is sent only for Quest orders and Quest appointments placed through Junction API. | | `cancelled` | *`"Hey, your lab appointment at {date} for {team_name} has been cancelled."`* This message is sent only for Quest orders and Quest appointments placed through Junction API. | ### Emails No emails are sent for this feature. ## Disable Communications In this case, no communications will be sent from Junction. You have the ability to produce completely customized communications using the [`Webhook events`](/lab/walk-in/webhooks) described previously. # Order and Appointment Lifecycle Source: https://docs.junction.com/lab/walk-in/order-lifecycle Learn the order and appointment statuses, state transitions, and scheduling flows for Walk-In Phlebotomy lab tests. The **Walk-In Test** orders are composed of two different lifecycles, the **Order** lifecycle and the **Appointment** lifecycle, detailed in the following sections. ## Order Lifecycle As discussed in [`Lab Test Lifecycle - Statuses`](/lab/workflow/lab-test-lifecycle#statuses), each lab testing modality has the following format: `[HIGH-LEVEL STATUS].[TEST MODALITY].[LOW-LEVEL STATUS]` For each modality, there can be multiple **low-level statuses**, for **Walk-In Phlebotomy** the possible low-level statuses are: * `ordered`: Vital received the order, stored it into our system, and started processing it asynchronously. * `requisition_created`: An order requisition form was validated and created with the partner laboratory, making the order available to be carried out. * `requisition_bypassed`: An order requisition form wasn't created when the order was placed with us because it already existed. * `appointment_pending`: An appointment was placed in Vital's system for the order, but doesn't have a scheduled date. * `appointment_scheduled`: An appointment was scheduled or rescheduled for the order. * `appointment_cancelled`: The appointment was cancelled, by either the patient, Vital or you. * `partial_results`: The laboratory has started making partial results available. * `redraw_available`: The result has been marked as final but is missing biomarker results due to lab error. * `completed`: The laboratory processed the blood sample and final results are available. * `sample_error`: The collected sample was unprocessable by the lab. * `cancelled`: The order was cancelled by either the patient, Vital or you. The Finite State Machine that defines the possible transitions for the low-level statuses described above is illustrated in the following diagram.
In **sandbox**, there is no async transition from the `ordered` state to the `requisition_created` state. This must be **manually triggered** via the **Junction Dashboard**. ## Appointment Lifecycle The appointment lifecycle is separate from the order lifecycle, and it corresponds to a single appointment. The possible statuses are defined as follows: * `pending`: An appointment was placed in the system, and is pending updates from the phlebotomy service. * `scheduled`: An appointment was scheduled or rescheduled. The Finite State Machine that defines the possible transitions for the appointment statuses described above is illustrated in the following diagram. The events are related to a single appointment. An order can have multiple existing appointments in Vital's system, although only one appointment will be considered active and returned when using the [GET Appointment endpoint](/api-reference/lab-testing/psc-scheduling/get-psc-appointment). ## Scheduling Appointments Before A Requisition Has Been Created This feature is available upon request. To enable, please get in touch with your Customer Success Manager. When this feature is enabled on your Team, you can create a Patient Service Center (PSC) appointment even before the requisition has been created for the corresponding Order (i.e., reaching the `requisition_created` status). This allows you to build an experience that can order the lab test *and* book an appointment consecutively, without having to wait on the asynchronous requisition creation process that may take an indeterminate amount of time. ### API Journey You create an Appointment for an Order which does not yet have a requisition. The Appointment starts with the `reserved` status. If the order requisition has been created on or before the time slot confirmation, the Appointment moves directly to the `confirmed` status. The `reserved` status will be skipped. The requisition is being created asynchronously. The requisition has now been created. 1. The Order will move through the `requisition_created`, `appointment_pending` and `appointment_scheduled` Order statuses in quick succession. 2. The Appointment will move to the `confirmed` status automatically, which corresponds to the `scheduled` appointment event. You will receive three `labtest.order.updated` events, one each for the three Order status transitions. You will also receive a `labtest.appointment.updated` event for the Appointment status transition. ## Cancelling An Appointment If an Appointment is cancelled **before** a requisition has been created: * The Appointment will move to the `cancelled` status; and * There is no change to the Order, which will remain in the `ordered` status. If an Appointment is cancelled **after** a requisition has been created: 1. The Appointment will move to the `cancelled` status; and 2. The Order will move from the `appointment_pending` or `appointment_scheduled` status to the `appointment_cancelled` status. ### Auto-cancellation of appointments without requisition In cases where appointments can be scheduled before a requisition has been created, the appointment will be automatically cancelled by Junction if the following happens: 1. More than 8 hours have passed since the order was created, and no requisition has been received. 2. There are fewer than 2 hours until the appointment start time, and no requisition has been received. The 8-hour auto-cancellation rule does not apply to [scheduled orders](/lab/workflow/scheduled-orders#scheduled-orders). Scheduled orders are fulfilled on their `activate_by` date, so Junction does not cancel their appointments based solely on the fact that more than 8 hours have passed since order creation without a requisition. ## Arizona Scheduling This feature is available upon request. To enable, please get in touch with your Customer Success Manager. When this feature is enabled on your Team, you can book appointments with Quest in Arizona (Sonora Quest). ### API Journey You create an Appointment for an Order to an Arizona PSC. The Appointment starts with the `reserved` status. The appointment is being created asynchronously. The appointment has now been created. 1. The Order will move through the `appointment_pending` and `appointment_scheduled` Order statuses in quick succession. 2. The Appointment will move to the `confirmed` status automatically, which corresponds to the `scheduled` appointment event. You will receive a `labtest.appointment.updated` event for the Appointment status transition. You will also receive two `labtest.order.updated` events, one each for the two Order status transitions. Arizona Scheduling uses separate Order and Appointment lifecycles. Appointment status changes are delivered through [`labtest.appointment.updated`](/event-catalog/labtest.appointment.updated). The Order status updates for `appointment_pending` and `appointment_scheduled` are emitted only after Sonora Quest confirms the appointment. If you use this feature, make sure your webhook endpoint is subscribed to appointment-level events. ### Appointment Booking Failure If we are unable to book the Appointment asynchronously, then: * The Appointment will move to the `cancelled` status. * Junction will send a `labtest.appointment.updated` event for the cancelled Appointment. * There is no change to the Order, which will remain in its last status. ### Cancellation and Rescheduling Cancellation and rescheduling for Arizona should be done directly by the patient, via the email they receive from Sonora Quest. It is not possible to cancel/reschedule via Junction. # Overview Source: https://docs.junction.com/lab/walk-in/overview Overview of the walk-in test modality where patients visit a laboratory Patient Service Center to have their blood drawn. Walk-in tests are one of our offered modalities. This modality is focused on patients that are able to go to a Laboratory to have their blood drawn. ## Ordering Flow overview To achieve this, a high-level overview of the process is defined as: * An order is placed in Junction's system through our Dashboard or API. * The order is added to a background queue and additional checks are made before a test requisition is created with the chosen Laboratory. * After the requisition is created, some form of communication is carried out with the patient so they can go to the assigned partner Laboratory. * After that, the patient can go at any time they want to the laboratory to have their blood drawn. * The Laboratory processes the patient's blood sample and generates the required results. * Junction exposes the results as soon as they are available, both as PDF and structured data via API. To find out more details, see [`Order Lifecycle`](/lab/walk-in/order-lifecycle), [`Communications`](/lab/walk-in/communications) and [`Webhooks`](/lab/walk-in/webhooks). # API Endpoints and Errors Source: https://docs.junction.com/lab/walk-in/psc-appointment-scheduling Error handling and optional features for scheduling appointments at Patient Service Centers (PSCs). ## API Endpoints All endpoints require authentication and are prefixed with `/v3/order`: * [`POST /v3/order/psc/appointment/availability`](/api-reference/lab-testing/psc-scheduling/appointment-psc-availability) - Get available time slots * [`POST /v3/order/{order_id}/psc/appointment/book`](/api-reference/lab-testing/psc-scheduling/appointment-psc-booking) - Book an appointment * [`PATCH /v3/order/{order_id}/psc/appointment/reschedule`](/api-reference/lab-testing/psc-scheduling/appointment-psc-rescheduling) - Reschedule an appointment * [`PATCH /v3/order/{order_id}/psc/appointment/cancel`](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) - Cancel an appointment * [`GET /v3/order/{order_id}/psc/appointment`](/api-reference/lab-testing/psc-scheduling/get-psc-appointment) - Get appointment details * [`GET /v3/order/psc/appointment/cancellation-reasons`](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancellation-reasons) - Get cancellation reasons *** ## Error Handling ### Environment Differences ⚠️ **Important**: Currently, error behavior differs between sandbox and production environments: | Environment | Quest Integration | Slot Conflict Behavior | | -------------- | ----------------- | --------------------------------------------- | | **Sandbox** | Mock client | Returns 400 (mock doesn't simulate conflicts) | | **Production** | Real Quest API | Returns 404 (actual Quest response) | **Recommendation**: For now, handle both 400 and 404 responses as potential slot-unavailability scenarios. ### Frequently Asked Questions #### Q: Do I need to parse error messages to distinguish between different 400 errors? **Yes.** Since multiple error types return 400 status codes, you must examine the error message content to determine the appropriate handling: * **Time in the past**: `"This appointment slot is no longer available. Please select a new time."` β†’ Select new slot * **Invalid booking key**: `"Invalid booking key format"` β†’ Fix request * **Missing parameters**: `"radius must be provided when using zip_code"` β†’ Fix request * **Order state issues**: `"Order is not in a state that allows booking..."` β†’ Contact support HTTP status codes alone are insufficient because our API uses 400 for multiple distinct error categories that require different user experiences. ### Error Categories #### Slot Unavailability Errors *The user should select a different time slot* | Status | Error Message | When It Occurs | User Action | | ---------- | --------------------------------------------------------------------------- | ---------------------------------------- | -------------------------------------- | | 400 | `"This appointment slot is no longer available. Please select a new time."` | Requested time is in the past | Select a future time slot | | 400 or 404 | Quest-specific error messages | Slot already taken or no longer exists | Select a different time slot | | 404 | `"No slots found for zip code"` | No locations/slots in the area | Try a different location or date range | | 404 | `"No slots found. Not all PSCs support scheduling..."` | All locations lack scheduling capability | Use different locations | #### Input Validation Errors *Fix the request parameters* | Status | Error Message | When It Occurs | User Action | | ------ | ------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------- | | 400 | `"Invalid booking key format"` | Malformed or corrupted booking key | Refresh availability and get a new booking key | | 400 | `"Location with site code {code} not found"` | Invalid PSC location code | Use a valid site code from the availability API | | 400 | `"Location with site code {code} is no longer active"` | PSC location disabled | Select a different location | | 400 | `"start_date must be greater or equal than the current date"` | Past date in the availability request | Use current or future date | | 400 | `"site_codes or zip_code must be provided"` | Missing search parameters | Provide either site codes or zip code | | 400 | `"radius must be provided when using zip_code"` | Missing radius with zip code search | Include radius parameter | | 400 | `"site_codes must be less than or equal to 3"` | Too many site codes | Limit to 3 site codes maximum | | 404 | `"This order doesn't exist."` | Invalid order ID | Verify order ID is correct | | 404 | `"This order is not a walk-in phlebotomy order."` | Wrong order type | Use the correct order type | #### Order State Errors *Order workflow or business logic issues* | Status | Error Message | When It Occurs | User Action | | ------ | ------------------------------------------------------- | ------------------------------------ | --------------------------------------- | | 400 | `"Order is not a walkin phlebotomy order"` | Wrong order type for PSC booking | Contact support | | 400 | `"Order does not have a sample ID..."` | Order missing requisition | Wait for requisition or contact support | | 400 | `"Order is not in a state that allows booking..."` | Order workflow prevents booking | Contact support | | 400 | `"Order is not in a state that allows cancelling..."` | Order workflow prevents cancellation | Contact support | | 400 | `"Order is not in a state that allows rescheduling..."` | Order workflow prevents rescheduling | Contact support | | 400 | `"This order does not have a requisition..."` | Missing requisition for appointment | Wait or contact support | | 400 | `"This lab is not supported."` | Order not for Quest lab | Use a supported lab | #### Appointment Management Errors *Appointment-specific business rules* | Status | Error Message | When It Occurs | User Action | | ------ | ----------------------------------------------------- | ------------------------------------------- | --------------------------------- | | 400 | `"This order doesn't have an appointment yet."` | Trying to modify a non-existent appointment | Book an appointment first | | 400 | `"This appointment cannot be rescheduled."` | Appointment marked non-reschedulable | Cancel and book a new appointment | | 400 | `"This appointment has been cancelled or completed."` | Operating on finalized appointment | No further action is possible | | 400 | `"This appointment has already been cancelled."` | Cancelling already cancelled appointment | No action needed | | 404 | `"Appointment not found."` | Appointment doesn't exist | Verify appointment exists | #### Authorization Errors *Access control issues* | Status | Error Message | When It Occurs | User Action | | ------ | -------------------- | ----------------------------------- | --------------- | | 401 | Authentication error | Invalid or expired token | Re-authenticate | | 403 | `"Action forbidden"` | User lacks permission for the order | Contact support | #### Service Availability Errors *System configuration or availability* | Status | Error Message | When It Occurs | User Action | | ------ | ----------------------- | ----------------------- | ---------------------------- | | 503 | `"Feature not enabled"` | PSC scheduling disabled | Contact support or try later | ### Testing Error Scenarios #### Sandbox Testing * Most validation errors can be tested in sandbox * Slot conflicts cannot be reliably tested (mock client always succeeds) * Use invalid parameters to test input validation #### Production Testing * Test with caution using real appointments * Slot conflicts will return actual 404 errors from Quest * Time-based errors can be tested with past dates ### Quest API Limitations * **Timeout**: 15 seconds read timeout, 5 seconds connection timeout * **Slot availability**: Real-time, can change between availability check and booking * **Mock client**: Doesn't simulate all real-world scenarios * **Rate limiting**: Standard Quest API rate limits apply # Opt-In Features Source: https://docs.junction.com/lab/walk-in/psc-appointment-scheduling-opt-ins Error handling and optional features for scheduling appointments at Patient Service Centers (PSCs). ## Availability Cache Junction maintains a fast Availability Cache containing the next 21 days of availability for all locations. Each location is refreshed every 5 minutes on average. When you set the `allow_stale` parameter on the [PSC Appointment Availability](/api-reference/lab-testing/psc-scheduling/appointment-psc-availability) endpoint, your request is fulfilled directly from the Availability Cache, provided that: 1. All requested locations have a cache hit; and 2. The cached information is reasonably fresh (less than 15 minutes old). When a request cannot be fulfilled by the Availability Cache, it is routed directly to the PSC Appointment Provider. #### When to use Use `allow_stale` when you need fast response times and can tolerate slightly stale availability dataβ€”for example, when displaying initial availability options to a user before they select a specific slot. ## Idempotency Key Consider specifying an Idempotency Key (`X-Idempotency-Key` header) when submitting a booking request to the [Book PSC Appointment](/api-reference/lab-testing/psc-scheduling/appointment-psc-booking) endpoint. Requests with the same idempotency key within a 14-day retention window will return the original request's response. Note that the response is frozen at the time it is first emitted. For example, if a pending appointment later transitions to confirmed via Async Confirmation, requests with that idempotency key will still return the appointment in its original pending status. #### When to use When a booking request fails on your side (API consumer side), it could be a transient connection issue or a Junction request queueing issue. Your request might have still reached the Junction API server and might have been processed. Using an Idempotency Key allows your system to safely retry booking requests, without the risk of double booking appointments. ## Async Confirmation When calling the [Book PSC Appointment](/api-reference/lab-testing/psc-scheduling/appointment-psc-booking) endpoint, Junction by default returns a 500 Internal Server Error if the PSC Appointment Provider fails to acknowledge the booking request. With Async Confirmation enabled, Junction waits synchronously for the provider to acknowledge the booking request, up to `sync_confirmation_timeout_millisecond` (default: 2.5s, range: 1–10s). * If an acknowledgment is received before the timeout, Junction creates a *reserved* or *confirmed* appointment immediately and returns it in the response. * If no acknowledgment is received before the timeout, Junction creates a placeholder **pending** appointment and returns it in the response. #### Background retries If a pending appointment is created, Junction continues to retry the booking request with the PSC Appointment Provider in the background, up to `async_confirmation_timeout_millisecond` (default: 15min, range: 1min–48hr). * If an acknowledgment is received before the timeout, the appointment transitions to *reserved* or *confirmed* status. * If the provider still fails to acknowledge after the timeout, the pending appointment transitions to *cancelled* status. #### Webhooks You will receive the `labtest.appointment.updated` event for the initial appointment creation, as well as for all state transitions described above. #### When to use Use Async Confirmation when you want to provide a consistently responsive booking experience. When the PSC Appointment Provider is under stress, Async Confirmation allows you to show a pending appointment to the end patient, and manages all the logistics of retrying the booking requests with the provider. # Webhooks Source: https://docs.junction.com/lab/walk-in/webhooks Reference for webhook events triggered during walk-in order lifecycle changes, with example payload structures. The following webhook events are of interest when placing a Walk-in order. These are described in detail in the following sections. ## Order webhook events Based on the status present in [`Order Lifecycle`](/lab/walk-in/order-lifecycle), Junction will trigger two kinds of webhook events, [`labtest.order.created`](/event-catalog/labtest.order.created) and [`labtest.order.updated`](/event-catalog/labtest.order.updated). The `labtest.order.created` event is triggered when an order is created in the system, having the `ordered` status, and all subsequent status changes will trigger a `labtest.order.updated` event in the system. The `partial_results` status does not trigger a Webhook unless specifically requested from Junction. The webhook payload body will have the following information if the Order is in the `completed` status: ```json Walk-in Order Updated theme={null} { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "team_id": "6353bcab-3526-4838-8c92-063fa760fb6b", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "walk_in_test", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "completed", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.walk_in_test.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.walk_in_test.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.walk_in_test.appointment_pending" }, { "id": 4, "created_at": "2022-01-03T00:00:00Z", "status": "collecting_sample.walk_in_test.appointment_scheduled" }, { "id": 5, "created_at": "2022-01-04T00:00:00Z", "status": "sample_with_lab.walk_in_test.partial_results" }, { "id": 6, "created_at": "2022-01-04T00:00:00Z", "status": "completed.walk_in_test.completed" } ], "origin": "initial", "order_transaction": { "id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "status": "completed", "orders": [ { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2022-01-04T00:00:00Z", "low_level_status": "completed", "low_level_status_created_at": "2022-01-04T00:00:00Z", "origin": "initial" } ] } } ``` ## Appointment webhook events Based on the status present in [`Order and Appointment Lifecycle - Appointment Lifecycle`](/lab/walk-in/order-lifecycle#appointment-lifecycle), Junction will trigger the [`labtest.appointment.updated`](/event-catalog/labtest.appointment.updated) webhook event. If the ability to [schedule appointments before a requisition has been created](/lab/walk-in/order-lifecycle#scheduling-appointments-before-a-requisition-has-been-created) is enabled for your team, and you intend to send patient communications for appointment updates, use the `labtest.appointment.updated` event. See more on communications for this feature [here](/lab/walk-in/communications#scheduling-appointments-before-a-requisition-has-been-created). If [Arizona Scheduling](/lab/walk-in/order-lifecycle#arizona-scheduling) is enabled for your team, subscribe to `labtest.appointment.updated` for Sonora Quest appointment status changes. The Order and Appointment lifecycles are managed separately for this flow, and the Order status updates for `appointment_pending` and `appointment_scheduled` are emitted only after Sonora Quest confirms the appointment. An endpoint subscribed only to `labtest.order.*` will not receive Appointment status changes such as scheduled or cancelled. The webhook payload body may have the following information if the appointment is in the `scheduled` status, after a **reschedule** has happened: ```json Walk-in Appointment Updated theme={null} { "event_type": "labtest.appointment.updated", "data": { "id": "06c2c65b-74a0-4f25-a4a9-44f796296355", "user_id": "acf79a82-0c2c-4ca0-998b-378931793905", "order_id": "1ed9c8d7-e1b4-4d61-8123-0f99de5ae99a", "order_transaction_id": "6424dd45-ee1a-49c6-ad0c-5769b8e03fc1", "address": { "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip_code": "91189", "country": "United States" }, "location": { "lng": -122.4194155, "lat": 37.7749295 }, "start_at": "2022-01-01T00:00:00", "end_at": "2022-01-01T00:00:00", "iana_timezone": "America/New_York", "type": "patient_service_center", "provider": "quest", "status": "confirmed", "event_status": "scheduled", "provider_id": "123", "can_reschedule": true, "event_data": { "origin": "patient", "is_reschedule": true }, "events": [ { "created_at": "2022-01-01T00:00:00Z", "data": null, "status": "scheduled" }, { "created_at": "2022-01-01T00:00:00Z", "data": { "origin": "patient", "is_reschedule": true }, "status": "scheduled" } ] } } ```
The `event_data` field contains relevant information regarding the current appointment status, and may be specific for each `provider`. # Ask on Order Entry (AOE) Source: https://docs.junction.com/lab/workflow/aoe Handle Ask on Order Entry (AOE) questions required for certain biomarkers, including the four question types and API integration. Some biomarkers require answers to clinical questions. This is referred to as AOE. These can be as simple as the volume of a particular marker or the patient's ethnicity. Questions that are related to fasting (e.g., code `FSTING`) do not need to be answered. Junction uses the default value you provided for fasting at the [lab test](/api-reference/lab-testing/post-test) creation time. However, if you do answer them, then the answered value overrides the preset test value. There are 4 types of AOE: 1. `choice` 2. `multiple_choice` 3. `numeric` 4. `text` `choice` and `multiple_choice` have a set list of answers to pick from, while `numeric` and `text` don't, and are free-form responses. AOE questions can also be required or optional. ## Where to find the questions As these AOE are directly related to biomarkers, you can find them in the [`GET /v3/lab_tests/markers`](/api-reference/lab-testing/biomarkers) endpoint or in the [`GET /v3/lab_tests/{lab_test_id}/markers`](/api-reference/lab-testing/lab-test-markers) endpoint, in the `aoe` object. As an example, let's look at the `Lead, Blood (Adult)` marker. We have omitted some extra questions for the sake of this doc. ```json theme={null} { "id": 173, "name": "Lead, Blood (Adult)", "provider_id": "007625", ... "questions": [ { "id": 1234567890251, "code": "BLPURP", "type": "choice", "value": "BLOOD LEAD PURPOSE", "constraint": null, "answers": [ { "id": 1234567890252, "code": "LCANS4", "value": "I - INITIAL" }, { "id": 1234567890253, "code": "LCANS5", "value": "R - REPEAT" }, { "id": 1234567890254, "code": "LCANS6", "value": "F - FOLLOW-UP" } ], "required": true, "sequence": 1 } ] } ``` Each question has its own `id`, which will be required to answer it. The types we refer to above are an enum that is represented by `type`. The `answers` list contains a list of possible answers in the case that `type` is one of `choice` or `multiple_choice`, otherwise it is empty. `required` determines whether the questions MUST be answered in order for the order to be valid; otherwise, an error will be shown: `Missing required questions - "question"`. ## How to answer For more information, refer to our [Knowledge Base article](https://support.junction.com/articles/1804950149-understanding-ask-on-order-entry-aoe-questions). Answering is done at order time, via the [`POST /v3/order`](/api-reference/lab-testing/create-order) endpoint, in the field `aoe_answers`. This field has the following format: ```json theme={null} { "aoe_answers": [ { "marker_id": , "question_id": , "answer": , } ] } ``` You will populate this list with the answers to the questions defined in the `marker` object, as explained [above](/lab/workflow/aoe#where-to-find-the-questions). The `marker_id` refers to the Junction [marker id](/api-reference/lab-testing/biomarkers), and the `question_id` to the id of the question being answered. For example, marker `Lead, Blood (Adult)`, has the following data: ```json theme={null} { "id": 173, "name": "Lead, Blood (Adult)", "provider_id": "007625", ... "questions": [ { "id": 1234567890251, "code": "BLPURP", "type": "choice", "value": "BLOOD LEAD PURPOSE", "constraint": null, "answers": [ { "id": 1234567890252, "code": "LCANS4", "value": "I - INITIAL" }, { "id": 1234567890253, "code": "LCANS5", "value": "R - REPEAT" }, { "id": 1234567890254, "code": "LCANS6", "value": "F - FOLLOW-UP" } ], "required": true, "sequence": 1 } ] } ``` In order to answer the required question, you will need the `marker_id` which is the `id` field, the `question_id` in `questions[0].id` and one of the `code` values in the `questions[0].answers` field. ### Answer types The `answer` field contains the actual answer to the question and its value will depend on the type and question itself. 1. `choice` and `multiple_choice` In this case, the `answer` should contain the `code` field in the list of `answers` provided, as shown [here](/lab/workflow/aoe#where-to-find-the-questions). E.g., the question is as follows for marker of id `173`: ```json theme={null} { "id": 173, "questions": [ { "id": 1234567890251, "code": "BLPURP", "type": "choice", "value": "BLOOD LEAD PURPOSE", "constraint": null, "answers": [ { "id": 1234567890252, "code": "LCANS4", "value": "I - INITIAL" }, { "id": 1234567890253, "code": "LCANS5", "value": "R - REPEAT" }, { "id": 1234567890254, "code": "LCANS6", "value": "F - FOLLOW-UP" } ], "required": true, "sequence": 1 } ] } ``` The answer is: ```json theme={null} { "aoe_answers": [ { "marker_id": 173, "question_id": 1234567890251, "answer": "LCANS4", } ] } ``` 2. `text` This case can encompass many responses, and depends on the question itself. In some instances, the `text` case contains a `constraint` field. This is a string tooltip indicator of the constraints applied by the lab on this particular question. E.g., the question is as follows for marker of id `173`: ```json theme={null} { "id": 173, "questions": [ { "id": 1234567890304, "code": "EDDATE", "type": "text", "constraint": null, "value": "EDD/EDC DATE", "answers": [], "required": true, "sequence": 2 }, ] } ``` The answer is: ```json theme={null} { "aoe_answers": [ { "marker_id": 173, "question_id": 1234567890304, "answer": "19900101", } ] } ``` 3. `numeric` In this case, the `answer` should be a numeric string representation of the actual value. E.g., the question is as follows for marker of id `173`: ```json theme={null} { "id": 173, "questions": [ { "id": 1234567890240, "code": "COLVOL", "type": "numeric", "constraint": null, "value": "URINE VOLUME (MILLILITERS)", "answers": [], "required": true, "sequence": 1 } ] } ``` The answer is: ```json theme={null} { "aoe_answers": [ { "marker_id": 173, "question_id": 1234567890240, "answer": "1000", } ] } ``` # Cancelling an Order Source: https://docs.junction.com/lab/workflow/cancelling-an-order Cancel lab test orders based on their current status and collection method, with guidance on timing to avoid unnecessary costs. Order cancellation depends on the current status of your order and its collection method. Orders follow a finite state machine (FSM) pattern with specific rules governing when cancellation is permitted. **Important timing considerations to avoid financial costs:** * **At-home phlebotomy**: Appointments cancelled more than 24 hours in advance will be fully refunded. Cancellations made less than 24 hours before the scheduled appointment are non-refundable. * **Testkits**: Cancel before shipment to avoid fees. Testkits typically ship within the same business day if orders are placed before 1pm EST. * **Walk-in tests**: Can generally be cancelled until sample collection begins. * **On-site collection**: Cancel before the collection event. ## When Orders Can Be Cancelled ### βœ… Generally Cancellable States All collection methods allow cancellation during these early phases: * `ordered` - Initial order placement * `requisition_created` - After requisition form is generated * `requisition_bypassed` - When requisition is bypassed * `awaiting_registration` - For registrable testkits ### ❌ Never Cancellable (Terminal States) Orders **cannot** be cancelled once they reach these states: * **Already cancelled**: `cancelled`, `do_not_process` * **Completed**: `completed`, `partial_results` * **Failed**: `lost`, `sample_error`, `failure_to_deliver_to_customer`, `failure_to_deliver_to_lab` ## Collection method-specific rules **βœ… Can cancel:** * `received.walk_in_test.ordered` * `received.walk_in_test.requisition_created` * `received.walk_in_test.requisition_bypassed` * `collecting_sample.walk_in_test.appointment_scheduled` * `collecting_sample.walk_in_test.appointment_cancelled` * `collecting_sample.walk_in_test.appointment_pending` **❌ Cannot cancel once collection begins:** * `cancelled.walk_in_test.cancelled` - Already cancelled * `completed.walk_in_test.completed` - Order completed * `sample_with_lab.walk_in_test.partial_results` - Has partial results * `collecting_sample.walk_in_test.redraw_available` - Order marked as final but has missing results * `failed.walk_in_test.sample_error` - Sample error occurred Cancelling a walk-in test order does **not** automatically cancel PSC appointments to prevent a poor patient experience, as it could lead to a patient arriving and their appointment being cancelled. Use the [PSC appointment cancellation endpoint](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) if you need to cancel the appointment separately. Orders can be reinstated by our support team if a patient shows up for an appointment related to a cancelled order. **βœ… Can cancel:** * `received.at_home_phlebotomy.ordered` * `received.at_home_phlebotomy.requisition_created` * `received.at_home_phlebotomy.requisition_bypassed` * `collecting_sample.at_home_phlebotomy.appointment_pending` * `collecting_sample.at_home_phlebotomy.appointment_scheduled` * `collecting_sample.at_home_phlebotomy.appointment_cancelled` * `collecting_sample.at_home_phlebotomy.draw_completed` **❌ Cannot cancel once collection begins:** * `cancelled.at_home_phlebotomy.cancelled` - Already cancelled * `completed.at_home_phlebotomy.completed` - Order completed * `sample_with_lab.at_home_phlebotomy.partial_results` - Has partial results * `failed.at_home_phlebotomy.sample_error` - Sample error occurred You can cancel the order directly - the system will automatically cancel any scheduled at-home phlebotomy appointments. Appointments cancelled with less than 24 hours' notice are non-refundable. **βœ… Can cancel:** * `received.testkit.ordered` * `received.testkit.awaiting_registration` * `received.testkit.requisition_created` * `received.testkit.requisition_bypassed` * `received.testkit.testkit_registered` **❌ Cannot cancel once shipped:** * `collecting_sample.testkit.out_for_delivery` * `collecting_sample.testkit.transit_customer` * `collecting_sample.testkit.with_customer` * `collecting_sample.testkit.transit_lab` * `sample_with_lab.testkit.delivered_to_lab` Testkits become non-cancellable once they enter the shipping phase to avoid logistics costs. Testkits typically ship within the same business day if orders are placed before 1pm EST. **βœ… Can cancel:** * `received.on_site_collection.ordered` * `received.on_site_collection.requisition_created` * `received.on_site_collection.requisition_bypassed` * `collecting_sample.on_site_collection.draw_completed` **❌ Cannot cancel once collection begins:** * `cancelled.on_site_collection.cancelled` - Already cancelled * `completed.on_site_collection.completed` - Order completed * `sample_with_lab.on_site_collection.partial_results` - Has partial results * `failed.on_site_collection.sample_error` - Sample error occurred ## How to Cancel ### Cancel Appointment (Optional - For Reference Only) **Note**: You can skip this step and go directly to [cancelling the order](#cancel-the-order). The system will automatically cancel at-home phlebotomy appointments when you cancel the order, but **will not** automatically cancel walk-in PSC appointments to avoid a poor patient experience where they arrive and their appointment is cancelled. If you need to cancel only the appointment (without cancelling the entire order), use the appropriate endpoint for your collection method: * **At-home phlebotomy**: [Appointment Cancellation endpoint](/api-reference/lab-testing/at-home-phlebotomy/appointment-cancelling) * **Walk-in tests (PSC)**: [PSC Appointment Cancellation endpoint](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) #### At-Home Phlebotomy Appointment Cancellation ```bash cURL theme={null} curl --request PATCH \ --url '{{BASE_URL}}/v3/order//phlebotomy/appointment/cancel' \ --header 'accept: application/json' \ --header 'x-vital-api-key: {YOUR_KEY}' \ --data '{"cancellation_reason_id": "7dfd7da5-ed6e-40bb-a7e4-c8003f0c10a9"}' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.cancel_phlebotomy_appointment( "", cancellation_reason_id="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelPhlebotomyAppointment({ orderId: "", cancellationReasonId: "", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelPhlebotomyAppointment( "", ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest.builder() .cancellationReasonId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelPhlebotomyAppointment(context.TODO(), &junction.ApiApiV1EndpointsVitalApiLabTestingOrdersHelpersAppointmentCancelRequest{ OrderId: "", CancellationReasonId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` #### Walk-In Test (PSC) Appointment Cancellation For walk-in tests scheduled at Patient Service Centers, use the PSC appointment cancellation endpoint: ```bash cURL theme={null} curl --request DELETE \ --url '{{BASE_URL}}/v3/order//appointment/psc/cancel' \ --header 'accept: application/json' \ --header 'x-vital-api-key: {YOUR_KEY}' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.cancel_psc_appointment( "", cancellation_reason_id="", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelPscAppointment({ orderId: "", cancellationReasonId: "", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelPscAppointment( "", VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest.builder() .cancellationReasonId("") .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelPscAppointment(context.TODO(), &junction.VitalCoreClientsLabTestGetlabsSchemaAppointmentCancelRequest{ OrderId: "", CancellationReasonId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ### Cancel the Order Use the [order cancellation endpoint](/api-reference/lab-testing/cancel-order) to cancel any lab test order. **Automatic Appointment Handling**: * **At-home phlebotomy**: Appointments are automatically cancelled when you cancel the order * **Walk-in PSC**: Appointments are **not** automatically cancelled to prevent poor patient experience if they show up. Orders can be reinstated if needed. ```bash cURL theme={null} curl --request DELETE \ --url {{BASE_URL}}/v3/lab_test//cancel \ --header 'Accept: application/json' \ --header 'x-vital-api-key: ' \ --header 'Content-Type: application/json' ``` ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.cancel_order("") ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.cancelOrder({ orderId: "" }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().cancelOrder(""); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.CancelOrder(context.TODO(), &junction.CancelOrderLabTestsRequest{ OrderId: "", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` ## Error Handling When attempting to cancel an order that cannot be cancelled, you'll receive an error response: ```json Error Response theme={null} { "error": "Bad Request", "message": "Transition from current_status to cancelled is not allowed", "status_code": 400 } ``` **Common reasons for cancellation failure:** * Order is already in a terminal state (completed, failed, or cancelled) * Testkit has already shipped * Sample has been collected or is with the lab * Results are already available (partial or complete) ## Checking Cancellation Eligibility Before attempting cancellation, check the order's current status using the [get order endpoint](/api-reference/lab-testing/get-order): ```bash Check Order Status theme={null} curl --request GET \ --url {{BASE_URL}}/v3/order/ \ --header 'x-vital-api-key: ' ``` Look for these indicators in the response: * `status` field shows the current high-level status * `events` array shows the detailed state progression * Orders in early states (`ordered`, `requisition_created`) are typically cancellable * Orders with `cancelled`, `completed`, or `failed` status cannot be cancelled ## Response Examples ### Successful Cancellation ```json Cancellation Success Response theme={null} { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": {"dob": "2020-01-01", "gender": "male"}, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789", }, "details": { "type": "testkit", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "shipment": { "id": "d55210cc-3d9f-4115-8262-5013f700c7be", "outbound_tracking_number": "", "outbound_tracking_url": "", "inbound_tracking_number": "", "inbound_tracking_url": "", "outbound_courier": "usps", "inbound_courier": "usps", "notes": "", "created_at": "2020-01-01T00:00:00.000Z", "updated_at": "2020-01-01T00:00:00.000Z", }, "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", }, }, "diagnostic_lab_test": { "name": "Lipids Panel", "description": "Cholesterol test", "method": "testkit", }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "cancelled", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered", }, { "id": 2, "created_at": "2022-01-01T00:00:00Z", "status": "cancelled.testkit.cancelled", } ], } ``` ### Successful Appointment Cancellation ```json Appointment Cancellation Response theme={null} { "id": "413d7205-f8a9-42ed-aa4a-edb99e481ca0", "user_id": "202b2c2f-fb4c-44dc-a4f8-621186fde227", "address": { "first_line": "West Lincoln Street", "second_line": "", "city": "Phoenix", "state": "AZ", "zip_code": "85004", "unit": "14" }, "location": { "lng": -112.0772235, "lat": 33.4421912 }, "start_at": "2023-05-17T20:00:00+00:00", "end_at": "2023-05-17T22:00:00+00:00", "iana_timezone": "America/Phoenix", "type": "phlebotomy", "provider": "getlabs", "status": "cancelled", "provider_id": "e89eb489-7382-4966-bb14-7ab4763eba6c", "can_reschedule": true } ``` ## Related Resources * [Order Lifecycle Overview](/lab/workflow/lab-test-lifecycle) * [API Reference: Cancel Order](/api-reference/lab-testing/cancel-order) * [API Reference: Cancel At-Home Appointment](/api-reference/lab-testing/at-home-phlebotomy/appointment-cancelling) * [API Reference: Cancel PSC Appointment](/api-reference/lab-testing/psc-scheduling/appointment-psc-cancelling) * [Webhooks for Order Events](/lab/testkits/webhooks) *** *For questions about specific cancellation scenarios, please contact support at [support@junction.com](mailto:support@junction.com)* # Clinical Notes Source: https://docs.junction.com/lab/workflow/clinical-comments Add clinical notes to lab orders at the order level or as a Lab Account default for requisition forms. Central labs (Labcorp, Quest, Sonora Quest and BioReference) allow you to pass in clinical notes. These are reflected in the Requisition form that is generated. Junction also allows you to set these notes, on an order-by-order basis, or as a [Lab Account](/lab/overview/lab-accounts) default. The Lab Account default is an internal configuration, contact your CSM to set this up. If your Lab Account has a default configured, then it will always be propagated to every order placed with the given Lab Account. ### Order Level Notes You can also pass in order-specific notes that will be displayed in the requisition form. This can be achieved via the `clinical_notes` field in the [Create Order endpoint](/api-reference/lab-testing/create-order). ### What happens when both the Order and the Lab Account have a clinical note? When this happens, Junction *concatenates* both of the notes, so they are always displayed. ### Usage Notes are new line separated (`\n`) strings. If you wish to provide more than one note, you can append a new line to your provided string. # Creating a Lab Test Source: https://docs.junction.com/lab/workflow/create-test Create custom lab tests by selecting biomarker IDs and collection methods, then submit them for Junction approval before ordering. Junction provides a way to create your own lab tests. A lab test is a collection or pre-set of orderable markers. These are made up of: 1. One or more marker IDs or Provider IDs. 2. The collection method: `testkit`, `walk_in_test`, `at_home_phlebotomy`, or `on_site_collection`. Once a Lab Test is created and approved, you can use it when making an order. When you create a Lab Test, it is not immediately available. We need to validate and approve it on our side, before you can use it when making orders. ### Example To begin, make a request to our [`GET /v3/lab_tests/markers`](/api-reference/lab-testing/biomarkers) endpoint, in order to choose the markers you want to test for. ```json Get all markers theme={null} { "markers": [ { "id": 1, "name": "17-OH Progesterone LCMS", "slug": "17-oh-progesterone-lcms", "description": "17-OH Progesterone LCMS", "lab_id": 1, "provider_id": "070085", "type": null, "unit": null, "price": "N/A" }, { "id": 2, "name": "ABO Grouping", "slug": "abo-grouping", "description": "ABO Grouping", "lab_id": 1, "provider_id": "006056", "type": null, "unit": null, "price": "N/A" } ], "total": 2, "page": 1, "size": 2 } ``` With this information, you can create a lab test using [`POST /v3/lab_tests`](/api-reference/lab-testing/post-test). As an example, let's say you wanted a test from `Labcorp`, with markers with provider IDs `006056` and `070085`: ```python Create a new test theme={null} from junction import Junction, LabTestCollectionMethod from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.create( name="Example test", description="Example test", method=LabTestCollectionMethod.AT_HOME_PHLEBOTOMY, provider_ids=["006056", "070085"], # or use the marker ids e.g marker_ids=[1, 2] ) ``` It is possible to create a test with either the marker id or provider id. Provider ids are the recommended way, since these are shared across environments. Not all labs provide these, so in their absence, use the marker id. Once your lab test creation is successful you will receive the following response: ```json theme={null} { "lab_test": { "name": "Example test", "description": "Example test", "sample_type": "serum", "method": "at_home_phlebotomy", "price": 10, "is_active": false, "status": "pending_approval", "lab": { "slug": "labcorp", "name": "LabCorp", "first_line_address": "123 Main St", "city": "San Francisco", "zipcode": "91789" }, "markers": [ { "name": "17-OH Progesterone LCMS", "slug": "17-oh-progesterone-lcms", "description": "17-OH Progesterone LCMS" }, { "name": "ABO Grouping", "slug": "abo-grouping", "description": "ABO Grouping" } ] } } ``` Note that `status` is set to `pending_approval`. You can verify when it changes to `active` by calling the [lab tests endpoint](/api-reference/lab-testing/tests-paginated). The `is_active` field is deprecated; use `status` instead. # Importing an Order Source: https://docs.junction.com/lab/workflow/importing-order Import externally-placed lab orders into Junction for centralized tracking and result delivery using the correct sample or requisition ID. This feature is in **closed beta**. Interested in this feature? Get in touch with your Customer Success Manager. If you want to track orders with Junction that weren't originally placed with Junction, you can import an order. It's crucial that imported orders are created with the correct sample ID. This is the **requisition number** or **control number** for Labcorp orders, or the **lab reference ID** for Quest orders. If in doubt, contact your Junction Customer Success Manager to confirm what you should supply for the sample ID. The sample ID must also uniquely identify the order. If you supply an ID that clashes with an existing order, that will result in a validation error. An imported order can be cancelled, receive results, and function similarly to orders originally placed with Junction, but with one important exception: a requisition will not be created. This means you cannot use the [endpoint to retrieve the requisition](/api-reference/lab-testing/requisition-pdf) for an imported order since Junction does not have access to it. After an order is successfully imported, it will be in the `requisition_bypassed` state (for example, an imported testkit order would have a `received.testkit.requisition_bypassed` status). This status supports transitioning to the same states that `requisition_created` does. Since import skips the regular order creation flow, no communications are sent to patients about the order being created, but communications are sent for subsequent events that might occur (order completion, for example). ### Example ```python Python theme={null} from junction import Billing, Gender, Junction, LabTestCollectionMethod, OrderSetRequest, PatientAddress, PatientDetailsWithValidation, PhysicianCreateRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.lab_tests.import_order( user_id="", billing_type=Billing.CLIENT_BILL, order_set=OrderSetRequest(lab_test_ids=[""]), collection_method=LabTestCollectionMethod.WALK_IN_TEST, physician=PhysicianCreateRequest(first_name="Jane", last_name="Doe", npi=""), patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="2020-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddress( receiver_name="John Doe", first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", phone_number="+1123456789", ), sample_id="1234567890", ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.labTests.importOrder({ userId: "", billingType: "client_bill", orderSet: { labTestIds: [""] }, collectionMethod: "walk_in_test", physician: { firstName: "Jane", lastName: "Doe", npi: "" }, patientDetails: { firstName: "John", lastName: "Doe", dob: "2020-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { receiverName: "John Doe", firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", phoneNumber: "+1123456789", }, sampleId: "1234567890", }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.labtests.requests.ImportOrderBody; import com.junction.api.types.Billing; import com.junction.api.types.Gender; import com.junction.api.types.LabTestCollectionMethod; import com.junction.api.types.OrderSetRequest; import com.junction.api.types.PatientAddress; import com.junction.api.types.PatientDetailsWithValidation; import com.junction.api.types.PhysicianCreateRequest; import java.util.List; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.labTests().importOrder( ImportOrderBody.builder() .userId("") .billingType(Billing.CLIENT_BILL) .orderSet(OrderSetRequest.builder() .labTestIds(List.of("")) .build()) .collectionMethod(LabTestCollectionMethod.WALK_IN_TEST) .patientDetails(PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("2020-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build()) .patientAddress(PatientAddress.builder() .receiverName("John Doe") .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .build()) .sampleId("1234567890") .physician(PhysicianCreateRequest.builder() .firstName("Jane") .lastName("Doe") .npi("") .build()) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.LabTests.ImportOrder(context.TODO(), &junction.ImportOrderBody{ UserId: "", BillingType: junction.BillingClientBill, OrderSet: &junction.OrderSetRequest{LabTestIds: []string{""}}, CollectionMethod: junction.LabTestCollectionMethodWalkInTest, Physician: &junction.PhysicianCreateRequest{ FirstName: "Jane", LastName: "Doe", Npi: "", }, PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "2020-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddress{ ReceiverName: "John Doe", FirstLine: "123 Main St.", City: "San Francisco", State: "CA", Zip: "91189", Country: "US", }, SampleId: "1234567890", }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` This example assumes you provide your own physician. The physician must be provided if your team configuration is set up as delegated. The billing type provided must also be appropriate to your team configuration. These aspects will be validated when making the request. Since the request represents an existing order, we don't perform strict address validation on the patient address, to make it easier to import orders exactly as they were placed in the original interface. The response object schema is the same as [creating an order](/api-reference/lab-testing/create-order). # Lab Test Lifecycle Source: https://docs.junction.com/lab/workflow/lab-test-lifecycle Understand the namespaced status system for lab test orders with high-level and modality-specific low-level status transitions. ## Introduction We encapsulate our lab test modalities in the `order` object. This is the main object you will interact with, as it contains all the information related to that lab test. An order has a high-level status which represents where the order is throughout its lifecycle, e.g., received/delivered/completed/cancelled, etc. The high-level status is the same across test modalities. On top of that, each modality has its own sub-statuses to represent lifecycle stages specific to that modality. For example, test-kits involve shipping of the box, so we have a whole set of statuses to track the shipment. **Please note**: To ensure future compatibility, we ask that you avoid exhaustive matching on enum values such as an order's status. We may introduce new statuses (and other enum values) over time, and code that assumes all current values are exhaustive could break or fail to compile with SDK upgrades. To stay compatible and benefit from future enhancements, treat unknown values gracefullyβ€”for example, by using default cases or limiting checks to only the values your integration depends on. ## Statuses Statuses are namespaced with the following format: `[HIGH-LEVEL STATUS].[TEST MODALITY].[LOW-LEVEL STATUS]` As an example, the status `collecting_sample.at_home_phlebotomy.appointment_scheduled` means the patient has scheduled an at-home phlebotomy appointment. ### High-level statuses The high-level statuses of an order are represented by `order.status`: * `received`: we received the order, stored it into our system, and started processing it. * `collecting_sample`: these track collecting the sample from the patient. For test-kits, these track the shipment of the kit. For at-home phlebotomy and walk-in tests, these track appointment scheduling and management. * `sample_with_lab`: the lab received the sample and is currently analyzing it. * `completed`: the order is complete and the results are ready. * `cancelled`: the order has been cancelled, by you or the patient. * `failed`: we failed to process the order. Modality-specific sub-statuses are encapsulated in the `order.events` list. These include a list of all the events for that test: ```json Test kit order status theme={null} { ..., "status": "cancelled", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.ordered", }, { "id": 2, "created_at": "2022-01-01T00:00:00Z", "status": "received.testkit.requisition_created", }, { "id": 3, "created_at": "2022-01-01T00:00:00Z", "status": "collecting_sample.testkit.transit_customer" }, ], } ``` Below is a full list of all the available statuses by test modality. The names should be self-descriptive. Please do not hesitate to contact us if you need any additional clarification! ### Test-kit statuses * `received.testkit.ordered` * `received.testkit.awaiting_registration` * `received.testkit.testkit_registered` * `received.testkit.requisition_created` * `received.testkit.requisition_bypassed` * `collecting_sample.testkit.transit_customer` * `collecting_sample.testkit.out_for_delivery` * `collecting_sample.testkit.with_customer` * `collecting_sample.testkit.transit_lab` * `collecting_sample.testkit.problem_in_transit_customer` * `collecting_sample.testkit.problem_in_transit_lab` * `sample_with_lab.testkit.delivered_to_lab` * `sample_with_lab.testkit.lab_processing_blocked` * `completed.testkit.completed` * `failed.testkit.failure_to_deliver_to_customer` * `failed.testkit.failure_to_deliver_to_lab` * `failed.testkit.sample_error` * `failed.testkit.lost` * `cancelled.testkit.cancelled` * `cancelled.testkit.do_not_process` ### Walk-in visit statuses * `received.walk_in_test.ordered` * `received.walk_in_test.requisition_created` * `received.walk_in_test.requisition_bypassed` * `collecting_sample.walk_in_test.appointment_pending` * `collecting_sample.walk_in_test.appointment_scheduled` * `collecting_sample.walk_in_test.appointment_cancelled` * `collecting_sample.walk_in_test.redraw_available` * `sample_with_lab.walk_in_test.partial_results` * `completed.walk_in_test.completed` * `failed.walk_in_test.sample_error` * `cancelled.walk_in_test.cancelled` ### At-home phlebotomy statuses * `received.at_home_phlebotomy.ordered` * `received.at_home_phlebotomy.requisition_created` * `received.at_home_phlebotomy.requisition_bypassed` * `collecting_sample.at_home_phlebotomy.appointment_pending` * `collecting_sample.at_home_phlebotomy.appointment_scheduled` * `collecting_sample.at_home_phlebotomy.draw_completed` * `collecting_sample.at_home_phlebotomy.appointment_cancelled` * `sample_with_lab.at_home_phlebotomy.partial_results` * `completed.at_home_phlebotomy.completed` * `failed.at_home_phlebotomy.sample_error` * `cancelled.at_home_phlebotomy.cancelled` ### On-site collection statuses (currently in beta testing) * `received.on_site_collection.ordered` * `received.on_site_collection.requisition_created` * `received.on_site_collection.requisition_bypassed` * `collecting_sample.on_site_collection.draw_completed` * `sample_with_lab.on_site_collection.partial_results` * `completed.on_site_collection.completed` * `failed.on_site_collection.sample_error` * `cancelled.on_site_collection.cancelled` # Ordering a Registrable Testkit Source: https://docs.junction.com/lab/workflow/order-registrable-testkit Use registrable testkits to ship kits without a bound patient, deferring patient registration until the testkit is activated. Under the [standard Testkit ordering flow](/api-reference/lab-testing/create-order), you place a Testkit order for a specific patient. The resulting Testkit is bound to that patient, and the Testkit cannot be passed on to someone else. With Registrable Testkits, Junction offers a different option β€” Testkits not bound to any specific patient can be ordered to a specific household address. The patient registration process is deferred until an actual patient intends to use the Testkit. For guidance on self-ordering, proxy ordering, and bulk inventory workflows, see [Proxy and Inventory Workflows for Registrable Testkits](/lab/workflow/registrable-testkit-proxy-inventory-workflows). Note that this only applies to Testkits, not Walk-in Tests or At-home Phlebotomy. This involves two steps: 1. Ordering the Testkit. 2. Registering a patient. After step 1, the order is sent to the requested address and generates all the same webhooks as a regular order would. However, it is stuck in the `received.testkit.awaiting_registration` state, meaning that no requisition form is generated for this order, and no results can be obtained until step 2 is done. After step 2, the order flow resumes as normal, the patient sends the `testkit` to the lab, the order is progressed to the `received.testkit.testkit_registered` state and, again, all the same webhooks as in the regular order flow are dispatched. ### Example To make an order, make a request to our [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order), to fulfill step 1. ```python Python theme={null} from junction import Junction, ShippingAddressWithValidation from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.testkit.create_order( user_id="", lab_test_id="", shipping_details=ShippingAddressWithValidation( receiver_name="John Doe", first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", phone_number="+11234567890", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.testkit.createOrder({ userId: "", labTestId: "", shippingDetails: { receiverName: "John Doe", firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", phoneNumber: "+11234567890", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.testkit.requests.CreateRegistrableTestkitOrderRequest; import com.junction.api.types.ShippingAddressWithValidation; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.testkit().createOrder( CreateRegistrableTestkitOrderRequest.builder() .userId("") .labTestId("") .shippingDetails(ShippingAddressWithValidation.builder() .receiverName("John Doe") .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .phoneNumber("+11234567890") .build()) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) response, err := c.Testkit.CreateOrder(context.TODO(), &junction.CreateRegistrableTestkitOrderRequest{ UserId: "", LabTestId: "", ShippingDetails: &junction.ShippingAddressWithValidation{ ReceiverName: "John Doe", FirstLine: "123 Main St.", City: "San Francisco", State: "CA", Zip: "91189", Country: "US", PhoneNumber: "+11234567890", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` The `testkit` is now ordered, and will be sent to the specified address. Once delivered, it can be kept until its expiration. Once the `testkit` is with its intended patient, it should be registered (step 2). In order to register, Junction requires a `sample_id`, which is found within the `testkit` itself. This is a unique identifier. Junction also requires the patient details and address. Besides this, if using Junction's physician network, then supplying the consents field is required. If providing your own physician, then the physician information is required. For this example, we will assume the use of your own physician. To register a `testkit` order, make a request to our [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order), to fulfill step 2. ```python Python theme={null} from junction import Gender, Junction, PatientAddressWithValidation, PatientDetailsWithValidation, PhysicianCreateRequestBase from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) data = client.testkit.register( user_id="", sample_id="123123123", patient_details=PatientDetailsWithValidation( first_name="John", last_name="Doe", dob="2020-01-01", gender=Gender.MALE, phone_number="+1123456789", email="email@email.com", ), patient_address=PatientAddressWithValidation( first_line="123 Main St.", second_line="Apt. 208", city="San Francisco", state="CA", zip="91189", country="US", ), physician=PhysicianCreateRequestBase( first_name="Doctor", last_name="Doc", npi="123123123", ), ) ``` ```typescript TypeScript theme={null} import { JunctionClient, JunctionEnvironment } from "@junction-api/sdk"; const client = new JunctionClient({ apiKey: "YOUR_API_KEY", environment: JunctionEnvironment.Sandbox, }); const data = await client.testkit.register({ userId: "", sampleId: "123123123", patientDetails: { firstName: "John", lastName: "Doe", dob: "2020-01-01", gender: "male", phoneNumber: "+1123456789", email: "email@email.com", }, patientAddress: { firstLine: "123 Main St.", secondLine: "Apt. 208", city: "San Francisco", state: "CA", zip: "91189", country: "US", }, physician: { firstName: "Doctor", lastName: "Doc", npi: "123123123", }, }); ``` ```java Java theme={null} import com.junction.api.Junction; import com.junction.api.core.Environment; import com.junction.api.resources.testkit.requests.RegisterTestkitRequest; import com.junction.api.types.Gender; import com.junction.api.types.PatientAddressWithValidation; import com.junction.api.types.PatientDetailsWithValidation; import com.junction.api.types.PhysicianCreateRequestBase; Junction client = Junction.builder() .apiKey("YOUR_API_KEY") .environment(Environment.SANDBOX) .build(); var data = client.testkit().register( RegisterTestkitRequest.builder() .sampleId("123123123") .patientDetails(PatientDetailsWithValidation.builder() .firstName("John") .lastName("Doe") .dob("2020-01-01") .gender(Gender.MALE) .phoneNumber("+1123456789") .email("email@email.com") .build()) .patientAddress(PatientAddressWithValidation.builder() .firstLine("123 Main St.") .city("San Francisco") .state("CA") .zip("91189") .country("US") .build()) .userId("") .physician(PhysicianCreateRequestBase.builder() .firstName("Doctor") .lastName("Doc") .npi("123123123") .build()) .build() ); ``` ```go Go theme={null} import ( "context" junction "github.com/junction-api/junction-go" "github.com/junction-api/junction-go/client" "github.com/junction-api/junction-go/option" ) c := client.NewClient( option.WithApiKey("YOUR_API_KEY"), option.WithBaseURL(junction.Environments.Sandbox), ) userId := "" response, err := c.Testkit.Register(context.TODO(), &junction.RegisterTestkitRequest{ UserId: &userId, SampleId: "123123123", PatientDetails: &junction.PatientDetailsWithValidation{ FirstName: "John", LastName: "Doe", Dob: "2020-01-01", Gender: junction.GenderMale, PhoneNumber: "+1123456789", Email: "email@email.com", }, PatientAddress: &junction.PatientAddressWithValidation{ FirstLine: "123 Main St.", City: "San Francisco", State: "CA", Zip: "91189", Country: "US", }, Physician: &junction.PhysicianCreateRequestBase{ FirstName: "Doctor", LastName: "Doc", Npi: "123123123", }, }) if err != nil { return err } fmt.Printf("Received data %s\n", response) ``` Your `testkit` order is now registered, and the order flow should resume as normal. For more information regarding the lifecycle of a test, refer to the [lab test lifecycle](/lab/workflow/lab-test-lifecycle) page. # Order Requirements Source: https://docs.junction.com/lab/workflow/order-requirements Review all requirements for placing a lab test order including patient consents, physician options, and patient name validation rules. ### Consents When you order a lab test through our API, you may have to collect consents from the patient and forward them to us. The following consents may include: * `hipaa-authorization`. * `terms-of-use`. * `telehealth-informed-consent`. ### Physician As mentioned [in the introduction](/lab/overview/introduction#features), you don't need to have your own Physician to place orders with Junction. When you [order a test](/lab/overview/quickstart#3-placing-an-order), you can pass an optional `physician` argument. If provided, the order will use your physician. If not, your order will go through with Junction's physician network. For more information, please check [our lab testing page](https://tryvital.io/labs) and [book an introductory call with us](https://cal.com/team/vital/discovery-call). ### Patient Name Validation Patient names must conform to a specific regex pattern due to lab restrictions. This validation applies to all name fields including `first_name` and `last_name`. **Regex Pattern:** ``` ^([a-zA-Z0-9]{1})([a-zA-Z0-9-.,']*(\s[a-zA-Z0-9-.,']+)*[a-zA-Z0-9-.,']?)$ ``` **Validation Rules:** * Must start with an alphanumeric character (not space, hyphen, or punctuation) * Only allows letters (a-z, A-Z), numbers (0-9), hyphens (-), periods (.), commas (,), apostrophes (') * Spaces are only allowed between words * Cannot start or end with a space * Cannot have consecutive spaces **Valid Name Examples:** * `John` * `Mary-Jane` * `O'Connor` * `Dr. Smith` * `Jean-Pierre` **Invalid Name Examples:** * ` John` (starts with space) * `John ` (ends with space) * `-John` (starts with hyphen) * `John@Smith` (contains @) * `JosΓ©` (contains accented character) ### Minors Ordering for minors (under 18 years old) requires a specific configuration, which you can request from your Junction Customer Success Manager. Once enabled, you are able to order for a minor patient by providing information regarding the medical proxy. This information can be supplied at [ordering time](/api-reference/lab-testing/create-order#body-patient-details-medical-proxy), or at any time by updating the [user demographics](/api-reference/user/upsert-info#body-medical-proxy). # Order Transactions Source: https://docs.junction.com/lab/workflow/order-transactions Understand the importance of order transactions and how they are used. ## Order Transactions and Initial Orders Junction uses the concept of **order transactions** to group related orders together and provide unified results. An order transaction represents a single testing journey, which will include, at a minimum, one `initial` order. An order transaction is created whenever a new `initial` order is created and a link is established between the two entities. * `initial` orders are orders that are not derived from another order. This is denoted in the order's `origin` field. * Order transactions have a `status` field, which can be `active`, `completed`, or `cancelled`. * `active` - one or more orders belonging to the order transaction are in progress * `completed` - all expected lab work for this transaction is completed and no further updates are expected * `cancelled` - all orders belonging to the order transaction have been cancelled * An order can only ever belong to one order transaction We recommend that you store both the `order_id` and `order_transaction_id` when placing an order in Junction. Both of these IDs will be needed when implementing some of Junction's current and future features like [redraws](/lab/workflow/redraws). ## API Endpoints The following endpoints are available to retrieve order transaction information and combined results for all orders within a transaction: * `GET /v3/order_transaction/{order_transaction_id}` - Get an order transaction's details and list of orders * `GET /v3/order_transaction/{order_transaction_id}/result` - Get combined results for an order transaction in JSON format * `GET /v3/order_transaction/{order_transaction_id}/result/pdf` - Get combined results for an order transaction in PDF format Responses for the following endpoints also include order transaction details: * `GET /v3/orders` - Get a list of filtered orders (including the ability to filter by order transaction ID) * `GET /v3/order/{order_id}` - Get an individual order * `GET /v3/order/{order_id}/result` - Get an individual order's results # Ordering Source: https://docs.junction.com/lab/workflow/ordering Learn the ordering concepts including markers, lab tests, and the various order_set field combinations for placing lab test orders. # Concepts Junction has a series of concepts to grasp regarding ordering: * [Lab Tests](/lab/workflow/create-test) * [Lifecycle of an Order](/lab/workflow/lab-test-lifecycle) * [Order Transactions](/lab/workflow/order-transactions) * [AOE](/lab/workflow/aoe) * [Registrable Kits](/lab/workflow/order-registrable-testkit) * [Scheduled Orders](/lab/workflow/scheduled-orders) In this document, we will focus on orderable panels/biomarkers. ### Markers [*Markers*](/api-reference/lab-testing/biomarkers) are individual, orderable tests, at the lab level. So, for example, at *Labcorp* you can order a `Lipid Panel` test and a `Vitamin D` test, a `panel` and a `biomarker` respectively. At Junction, these are both referred to as **markers**. ### Lab Tests [*Lab Tests*](/api-reference/lab-testing/post-test) are a collection of markers, or a preset combination of markers, that you can order. Using the example above, you can create a `Labcorp Lipid Panel and Vitamin D` lab test. You can then place orders at Junction using this preset. This is useful for situations where you repeatedly want to order the same markers. # Ordering When placing an [Order](/api-reference/lab-testing/create-order), you will see an `order_set` field. This is what defines what markers will be ordered. There are multiple combinations allowed with this field, so let's explore all of them. ### Ordering a *Lab Test* When ordering from **one** previously created *Lab Test*, the `order_set` field should be populated as follows: ```python Python theme={null} from junction import Junction, OrderSetRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.create_order( order_set=OrderSetRequest( lab_test_ids=[""], ), # ... ) ``` ### Ordering from multiple *Lab Tests* You may want to combine two or more existing Lab Tests without creating a new one. This is possible by doing: ```python Python theme={null} from junction import Junction, OrderSetRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.create_order( order_set=OrderSetRequest( lab_test_ids=["", ""], ), # ... ) ``` ### Ordering without a *Lab Test* This is what Junction calls `Γ  la carte` ordering. You may want to order from the marker compendium without creating a preset. `Γ  la carte` ordering is generally available to all teams. Not all markers are enabled for `Γ  la carte` ordering β€” see [Γ€ La Carte Markers](#Γ -la-carte-markers) below. It is possible to order `Γ  la carte` using Junction `marker_ids` or the lab's `provider_ids`. ```python Python theme={null} from junction import AddOnOrder, Junction, LabTestCollectionMethod, OrderSetRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.create_order( order_set=OrderSetRequest( add_on=AddOnOrder( provider_ids=["322022"], # marker_ids=[1], ), ), collection_method=LabTestCollectionMethod.WALK_IN_TEST, # ... ) ``` ### Order *Lab Tests* with extra *Markers* You may also add extra **markers** to an order. For example, you want to order the `Labcorp Lipid Panel and Vitamin D` but for this particular patient, you also want to order a `CBC Panel`. ```python Python theme={null} from junction import AddOnOrder, Junction, LabTestCollectionMethod, OrderSetRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.create_order( order_set=OrderSetRequest( lab_test_ids=[""], add_on=AddOnOrder( provider_ids=["322022"], # marker_ids=[1], ), ), collection_method=LabTestCollectionMethod.WALK_IN_TEST, # ... ) ``` When supplying the `add_on` field, it is always required to provide the `collection_method` field. ## Collection Method As further explored in the documentation, Junction also has the concept of *Collection Method*. Junction currently supports four methods: [`At Home Phlebotomy`](/lab/at-home-phlebotomy/overview), [`Walk In`](/lab/walk-in/overview), [`Testkits`](/lab/testkits/overview), and [`On-Site Collection`](/lab/on-site-collection/overview). When ordering, you must select one of these, either at lab test creation, or at ordering time. ```python Python theme={null} from junction import Junction, LabTestCollectionMethod, OrderSetRequest from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) client.lab_tests.create_order( order_set=OrderSetRequest( lab_test_ids=[""], ), collection_method=LabTestCollectionMethod.WALK_IN_TEST, # ... ) ``` ## Γ€ La Carte Markers As mentioned above, not all `markers` are `Γ  la carte` orderable. You can find which ones are orderable via the [GET /v3/lab\_tests/markers](/api-reference/lab-testing/biomarkers). ```python Python theme={null} from junction import Junction from junction.environment import JunctionEnvironment client = Junction( api_key="YOUR_API_KEY", environment=JunctionEnvironment.SANDBOX, ) markers = client.lab_tests.get_markers( name="322022", a_la_carte_enabled=True, ) if not all(m.a_la_carte_enabled for m in markers.markers): raise Exception("Markers not a_la_carte_enabled") ``` ## Error Cases With the existence of various allowed combinations with the `order_set` field, there are many validations that are done server side. Here are some of the errors you can expect to encounter: ### 400 Bad Request 1. `collection_method must be set if add_on is set`: When the `add_on` field is supplied, you must provide the `collection_method`. 2. `marker_ids or provider_ids must be set in add_on`: One of `marker_ids` or `provider_ids` must be set, if the `add_on` field is provided. 3. `cannot set both marker_ids and provider_ids in add_on`: Similarly, only one of these two fields can be provided. 4. `cannot order lab_tests from multiple labs`: You can only order multiple lab tests from the same lab. 5. `cannot order lab tests with multiple collection methods`: You must supply a `collection_method` if ordering multiple lab tests with multiple collection methods. 6. `Lab does not allow gender `: The associated lab restricts which patient genders it accepts. This restriction applies to the entire lab, not to individual lab tests. # Partial Result Notifications Source: https://docs.junction.com/lab/workflow/partials Configure partial result handling to receive webhook notifications when some but not all biomarker results are ready for an order. Orders may have partial results, meaning that the lab has made available part of the result, while the full result is not complete. In general, these are short-lived and as such, Junction does not expose them via webhooks. Some orders, however, have long-lived partial results, specifically when one ordered marker takes significantly longer to result than the others. In these situations, clients may want to be notified of the existence of partial results. As such, Junction provides a team-level configuration that enables the delivery of partial result webhooks. Similarly to other events, these are triggered via a `labtest.order.updated` event in the system. Orders can also experience multiple partials in their lifecycle. In these cases, Junction will send a webhook for each partial update. So if your order experiences two partial results before a final, complete result, you should expect to receive two `labtest.order.updated` webhooks with `partial` status. For example, in the second partial result, you would receive a webhook with the following body: Note that the `events` block contains two `sample_with_lab.walk_in_test.partial_results` events. ```json Walk-in Order Updated theme={null} { "id": "84d96c03-6b1c-4226-ad8f-ef44a6bc08af", "team_id": "6353bcab-3526-4838-8c92-063fa760fb6b", "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2020-01-01", "gender": "male" }, "patient_address": { "receiver_name": "John Doe", "first_line": "123 Main St.", "second_line": "Apt. 208", "city": "San Francisco", "state": "CA", "zip": "91189", "country": "United States", "phone_number": "+1123456789" }, "details": { "type": "walk_in_test", "data": { "id": "a655f0e4-6405-4a1d-80b7-66f06c2108a7", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z" } }, "sample_id": "123456789", "notes": "This is a note", "created_at": "2020-01-01T00:00:00Z", "updated_at": "2020-01-01T00:00:00Z", "status": "sample_with_lab", "events": [ { "id": 1, "created_at": "2022-01-01T00:00:00Z", "status": "received.walk_in_test.ordered" }, { "id": 2, "created_at": "2022-01-02T00:00:00Z", "status": "received.walk_in_test.requisition_created" }, { "id": 3, "created_at": "2022-01-03T00:00:00Z", "status": "sample_with_lab.walk_in_test.partial_results" }, { "id": 4, "created_at": "2022-01-04T00:00:00Z", "status": "sample_with_lab.walk_in_test.partial_results" } ] } ``` # Redraws Source: https://docs.junction.com/lab/workflow/redraws Handle redraw scenarios where patients return for a new blood draw due to missing results. Interested in this feature? Get in touch with your Customer Success Manager. Please note that this feature is only available for walk-in tests with Labcorp, Quest, and BioReference. A patient may be eligible for a redraw if their order has missing results due to a lab error. To get a redraw, the patient will need to go back to the PSC with a new requisition form, listing only the missing biomarkers that need to be retested. To facilitate this flow, Junction uses the concept of [order transactions](/lab/workflow/order-transactions), which in the case of a redraw flow, will include one initial order and at most, one redraw order. ## Order Transactions and Redraw Orders If an `initial` order is eligible for a redraw, rather than transitioning the [low-level status](/lab/workflow/lab-test-lifecycle) of the order to `completed`, the order status is set to `redraw_available`. * At this point, a new order is created, with `origin` set to `redraw`, and it is linked to the same order transaction as the `initial` order * The order transaction's `status` field will be as follows: * `active` - one or more orders belonging to the order transaction are in progress * `completed` - all expected lab work for this transaction is completed and no further updates are expected * `cancelled` - the initial order has been cancelled (and there's no redraw order), or both the initial and redraw orders have been cancelled ### Webhooks * A `labtest.order.updated` [webhook](/lab/walk-in/webhooks) will be sent for the `initial` order when it transitions to the `redraw_available` status * Additionally, `labtest.order.created` and `labtest.order.updated` [webhooks](/lab/walk-in/webhooks) will be sent for the `redraw` order, when it is created and transitions to the `requisition_created` status upon the requisition being processed * The `labtest.order.created` and `labtest.order.updated` webhook payloads will include origin and order transaction details (including a list of orders that belong to the transaction, ordered by ascending date of order creation) - see the example payload on the [webhooks](/lab/walk-in/webhooks) page for more details * Ordering of webhook delivery is not guaranteed and should not be relied upon ### Monitoring updates and completion * The results for the `initial` order will be available via the [results API](/lab/results/result-formats) when the `redraw_available` event is received. **No further updates for this order should be expected.** * The `redraw` order will move through the usual [order lifecycle](/lab/walk-in/order-lifecycle) and will emit its own webhooks so that updates can be tracked. * A patient can only go through one redraw per order transaction. This means that a `redraw` order will never transition to a `redraw_available` state. * When results for the `redraw` order have been received and processed, the `redraw` order status will transition to `completed`, regardless of whether there are still missing results. The order transaction status will also be marked as `completed`. ## Key things to note * The order transaction should be used as the primary way to reason about all related orders. A workflow for monitoring redraws could be as follows: * Save the order transaction ID associated with an order at the point of its creation * When processing order webhooks, if an initial order is in a `redraw_available` state, check the order transaction details in the payload to retrieve the order ID for the new redraw order * Monitor webhooks for the redraw order to get the latest updates * Once the redraw order is completed, use the order transaction endpoint to retrieve combined results ## Cancelling a Redraw Order * Once the `initial` order transitions to `redraw_available` state, it can no longer be cancelled. * To cancel the `redraw` order, use the [cancel order endpoint](/api-reference/lab-testing/cancel-order) with the `redraw` order ID (not the `initial` order ID). The redraw order follows the standard [walk-in test cancellation rules](/lab/workflow/cancelling-an-order). ## Integrating with Order Transactions We recommend that you store both the `order_id` and `order_transaction_id` when placing an order in Junction. This way, if you receive a webhook for an order that you have not seen in your system, you will be able to link it to the initial order via the `order_transaction_id`. From there, you can always use the `order_transaction_id` directly to obtain results, ensuring you always get the complete set of results for a particular order transaction. # Proxy Ordering Registrable Testkits Source: https://docs.junction.com/lab/workflow/registrable-testkit-proxy-inventory-workflows Recommended flows for proxy ordering and inventory workflows with registrable testkits. Junction's registrable testkit flow supports ordering testkits before the final patient registration step is completed. These are also known as "unregistered" testkits because the patient registration step happens after the kit is ordered. The initial [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order) request still requires a `user_id`. That user can be the intended patient if they are already known, or it can be a stock/inventory user that your system uses while the final patient is still unknown. When the kit is registered with [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order), you can provide a different `user_id`. If that user exists on the same team as the order, Junction rebinds the order to that user during registration. If `user_id` is omitted, the order stays bound to the user from the original order request. This workflow guide outlines recommended implementation patterns for two flows where the patient may not be the person or system initiating the order: * A user orders a registrable testkit on behalf of another person. * A clinic orders registrable testkits in bulk for on-hand inventory. These are general recommendations. Your implementation may need to adjust these patterns based on your specific user model, inventory workflow, registration workflow, and result display/retrieval requirements. The `user_id` on the create request is the current order owner. The `user_id` on the registration request is the final patient and result owner when it is supplied. Registration-time rebinding only works for an existing user on the same team as the order. ## Relevant API requests These flows use the following Junction API requests: * Use [`POST /v2/user`](/api-reference/user/create-user) to create a Junction user when the intended patient or stock/inventory user does not already exist in Junction. * Use [`GET /v2/user/{user_id}`](/api-reference/user/get-user) when you already have the Junction `user_id` and need to retrieve that user. * Use [`GET /v2/user/resolve/{client_user_id}`](/api-reference/user/resolve-user) when you have your own `client_user_id` and need to look up the corresponding Junction user. * Use [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order) to create a registrable testkit order. * Use [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order) to register the kit when the final patient information is available. In the flows below, "create or resolve a user" means: first look up the existing Junction user using `GET /v2/user/{user_id}` if you already store the Junction `user_id`, or `GET /v2/user/resolve/{client_user_id}` if you store your own user identifier. If no Junction user exists, create one with `POST /v2/user`. ## Scenario 1: User A orders a testkit for User B ### Example User A places an unregistered testkit order for User B. User B is the intended patient and will register the kit using their own demographic information. ### Recommended flow Junction does not model this as a separate proxy-ordering concept. From Junction's perspective, this is still a normal [registrable testkit order](/lab/workflow/order-registrable-testkit). Your application decides whether to bind the order to the final patient at order time or at registration time. If User B is known before the kit is ordered, create the Junction order directly for User B: 1. User A starts the order in your application. 2. Your application determines that the intended patient and result owner is User B. 3. Create or resolve User B in Junction. 4. Place the registrable testkit order with [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order) using User B's Junction `user_id`. 5. Register the kit with [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order). You can omit `user_id` because the order is already bound to User B. 6. Order and results are associated with User B. ### If the final patient is not known yet If User A orders the kit before the final patient is known, use the same pattern as the inventory workflow: 1. Create or resolve a stock, household, account, or orderer Junction user for the initial order. 2. Place the registrable testkit order with that user's `user_id`. 3. When User B is known, create or resolve User B in Junction. 4. Register the kit for that Junction order with User B's Junction `user_id` and User B's patient information. 5. Junction rebinds the order to User B during registration. ## Scenario 2: Bulk registrable kits for inventory ### Example Your clinic wants to order 100 registrable testkits and keep the physical kits in inventory or on site before the final patients are known. For example, you may need kits available at a location so they can be handed to patients later. ### Recommended flow For inventory workflows, create one or more dedicated Junction users to represent stock inventory before patient assignment. These can be scoped however your application needs, such as one stock user per clinic location, program, warehouse, or inventory pool. For example, if you need 100 kits for one clinic location: 1. Create or resolve a Junction stock user for that location, such as `clinic_a_inventory`. 2. Place 100 registrable testkit orders with [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order), using that stock user's Junction `user_id`. 3. Store the Junction order ID for each inventory order. 4. When a final patient is assigned to a kit or claims a kit, create or resolve that patient in Junction. 5. Register the kit with [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order), using the Junction order ID, the patient's Junction `user_id`, and the patient's registration details. 6. Junction rebinds the order from the stock user to the patient user during registration. Results are associated with the patient user. ## Example inventory mapping Your inventory tracking may look like this. The only Junction identifier you need to keep for registration is the order ID. Any extra fields are application-specific. | Field | Description | | ------------------------ | ------------------------------------------------------- | | Junction order ID | The Junction order created for this kit | | Patient ID | Your patient ID, once the kit is assigned or claimed | | Patient Junction user ID | The Junction user supplied at registration time | | Status | Example inventory status maintained by your application | | Junction Order ID | Patient ID | Patient Junction User ID | Status | | ----------------- | ------------ | ------------------------ | ---------- | | order\_001 | null | null | available | | order\_002 | patient\_123 | junction\_user\_123 | registered | | order\_003 | patient\_456 | junction\_user\_456 | registered | ## Webhook and event attribution Before registration, order and shipping events are associated with the user from the original [`POST /v3/order/testkit`](/api-reference/lab-testing/create-unregistered-order) request. In an inventory workflow, that is usually your stock user. After registration-time rebinding, the registration event and later order lifecycle events are associated with the patient user supplied in [`POST /v3/order/testkit/register`](/api-reference/lab-testing/register-order). Because of this, your application should not treat pre-registration webhook `user_id` or `client_user_id` values as the final patient identity for inventory-held kits. Use your inventory mapping and the post-registration order state as the source of truth for final patient ownership. # Scheduled Orders Source: https://docs.junction.com/lab/workflow/scheduled-orders Schedule lab test orders for future fulfillment dates using the activate_by parameter for follow-up testing workflows. Junction provides a way to schedule your orders for a future date, both via the API and via the Junction Dashboard. A scheduled order is one that will only be fulfilled in the future, so it won't be created in the Partner Laboratories until the defined date. This is useful for defining follow-up orders after placing an initial Lab Order for a patient. ## Ordering through the API To place a scheduled order through the API, you should use the [Create Order endpoint](/api-reference/lab-testing/create-order), passing the `activate_by` date parameter. The `activate_by` parameter defines when that order is scheduled for, and it will move from the `ordered` to the `requisition_created` status when the date arrives. If you want to query all placed orders, you may use [Get Orders endpoint](/api-reference/lab-testing/get-orders), passing an `order_activation_types` query parameter, which accepts the following values `["current", "scheduled"]`. * If the parameter is not provided, every order is returned. * If `current` is provided, orders with a `null` `activate_by` date or with `activate_by` set before the current date are returned. * If `scheduled` is provided, orders with an `activate_by` date greater than the current date are returned. Placing a scheduled order for January 6, 2025 would look like this: ```json Placing a Scheduled Order request theme={null} { "user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "patient_details": { "dob": "2022-07-06T22:20:26.796Z", "gender": "male | female", "email": "test@test.com" }, "patient_address": { "receiver_name": "John Doe", "street": "Hazel Road", "street_number": "102", "city": "San Francisco", "state": "CA", "zip": "91789", "country": "U.S.", "phone_number": "+14158180852" }, "lab_test_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "physician": { "first_name": "John", "last_name": "Doe", "email": "john@doe.com", "npi": "123456789", "licensed_states": ["CA", "NY"], "created_at": "2022-07-06T22:20:26.796Z", "updated_at": "2022-07-06T22:20:26.796Z" }, "activate_by": "2025-01-06" } ``` ## Ordering through the Junction Dashboard To place a scheduled order through the dashboard, just follow the normal procedure until you reach the Lab Testing selection screen. Notice that there is a checkbox for defining this order as scheduled for the future. After the checkbox is selected, you can pass in the desired scheduled date. After that, you can filter out the `Scheduled` and `Current` orders in the dashboard using the filter in the orders listing. # Unmatched lab results Source: https://docs.junction.com/lab/workflow/unmatched-results Review lab results that could not be automatically matched to an order, including webhooks, listing, accepting, rejecting, and escalating. # Unmatched Lab Results Integration Guide The Unmatched Results API lets you review a lab result that could not be safely attached to an order automatically. You can accept a proposed match, reject the result, or ask the Junction operations team to review it. This guide covers: * receiving review notifications by webhook; * listing and retrieving unmatched results; * accepting, rejecting, or escalating a result; and * understanding the available match cases. ## Recommended integration flow 1. Subscribe your webhook endpoint to `labtest.match_review.created`. 2. When the webhook arrives, store its `data.id` as the unmatched-result ID. 3. Fetch the full item with `GET /v3/unmatched_result/{id}`. 4. Present the result, patient context, and candidate orders to a reviewer. 5. Display only the actions listed in `allowed_actions`. 6. Call the accept or resolve endpoint with the reviewer's decision. 7. Use the returned resource as the source of truth for the final state and store its `order_transaction.id` to track related orders. You can also poll the list endpoint to reconcile missed or delayed webhook deliveries. ## Test your integration in Sandbox The unmatched-result testing API creates realistic review items in Junction Sandbox. It creates the required Sandbox orders, or uses orders that you provide, generates a central-lab result, and sends it through the normal matching and review flow. You do not need to create HL7, upload a result, or configure a lab account. After a test run succeeds, use its `raw_result_id` with the normal unmatched-results API to test your polling, webhook, review, accept, reject, and escalation flows. The testing API is available only in Sandbox and returns `404 Not Found` in production. It also requires the unmatched-result testing feature to be enabled for your Sandbox team. Contact your Junction representative to enable it. Test fixtures: * support Labcorp, Quest, Sonora Quest, and BioReference panels; * produce the same decision codes described in [Available decision cases](#available-decision-cases); * emit the normal `labtest.match_review.created` and `labtest.match_review.updated` webhooks; and * persist in Sandbox. There is no cleanup or cancellation endpoint. Enabling the testing API in Sandbox does not enable automatic unmatched-result routing in production. Production uses a separate feature configuration. ### Run a test 1. Call [the case catalog](/api-reference/lab-testing/unmatched-results/list-unmatched-result-test-cases) and choose a case. 2. Choose `managed` orders for Junction-created fixtures or `provided` orders to use existing Sandbox orders. 3. [Create a test run](/api-reference/lab-testing/unmatched-results/create-unmatched-result-test) with a stable `X-Idempotency-Key`. 4. [Poll the run](/api-reference/lab-testing/unmatched-results/get-unmatched-result-test) until its status is `succeeded` or `failed`. 5. On success, retrieve the generated item with `GET /v3/unmatched_result/{raw_result_id}` and process it through the normal accept or resolve endpoints. 6. Reconcile the API state with the normal match-review webhooks. The case catalog is the source of truth for each case's required order roles, target statuses, and lab constraints. Do not hard-code these requirements. This request creates a completed-order match with Junction-managed orders: ```bash theme={null} curl --fail-with-body --request POST \ --url 'https://api.sandbox.us.junction.com/v3/unmatched_result_test' \ --header "x-vital-api-key: $JUNCTION_API_KEY" \ --header 'X-Idempotency-Key: match-completed-001' \ --header 'content-type: application/json' \ --data '{ "case": "match_completed", "order_source": "managed", "result_status": "final" }' ``` The API returns `202 Accepted` with a run ID: ```json theme={null} { "run_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "status": "queued" } ``` Poll the run using that ID: ```bash theme={null} curl --fail-with-body \ --url 'https://api.sandbox.us.junction.com/v3/unmatched_result_test/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb' \ --header "x-vital-api-key: $JUNCTION_API_KEY" ``` When the run succeeds, the response includes the generated `raw_result_id` and any orders that Junction created: ```json theme={null} { "run_id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "status": "succeeded", "stage": "succeeded", "case": "match_completed", "order_source": "managed", "result_status": "final", "orders": { "provenance": { "order_id": "11111111-1111-1111-1111-111111111111", "user_id": "22222222-2222-2222-2222-222222222222", "order_transaction_id": "33333333-3333-3333-3333-333333333333" } }, "raw_result_id": "44444444-4444-4444-4444-444444444444", "error": null, "created_at": "2026-07-20T10:00:00Z", "updated_at": "2026-07-20T10:00:08Z", "started_at": "2026-07-20T10:00:01Z", "completed_at": "2026-07-20T10:00:08Z" } ``` Managed mode is available for every case except `wrong_collection`. That case requires a provided at-home phlebotomy order. In `provided` mode, the `orders` object must contain exactly the role names returned by the case catalog, and the orders must belong to the authenticated Sandbox team. If Junction finds more than one eligible central-lab panel, include `lab_test_id` in the create request. For `wrong_lab`, use `wrong_lab_test_id` in managed mode to select the panel for the order at the other central lab. Keep the idempotency key stable when retrying after a client timeout. Reusing the same key and request returns the existing run; reusing it with a different request returns `409 Conflict`. ## Webhook ### Event type ```text theme={null} labtest.match_review.created ``` The event is sent when an unmatched result first becomes available for customer review. An item that is only awaiting internal operations review does not emit this event. The webhook is a notification, not the complete review record. Fetch `data.id` from the API before displaying or resolving the item. Example payload: ```json theme={null} { "event_type": "labtest.match_review.created", "team_id": "44444444-4444-4444-4444-444444444444", "user_id": "11111111-1111-1111-1111-111111111111", "client_user_id": "customer-patient-123", "data": { "id": "6c3a56b7-c3ef-4edb-889a-6c4c874bcf00", "status": "pending_customer_review", "decision_code": "match_sample_id_mismatch_demo", "sub_reason_codes": [] } } ``` Configure this event on your existing webhook destination; it does not require a separate callback URL. Verify each delivery using the signing secret for that destination, return a successful response promptly, and process repeated deliveries idempotently. ## API endpoints ### List unmatched results ```http theme={null} GET /v3/unmatched_result ``` Example: ```bash theme={null} curl --request GET \ --url 'https://api.tryvital.io/v3/unmatched_result?status=pending_customer_review&lab_slug=labcorp&limit=50' \ --header "x-vital-api-key: $VITAL_API_KEY" ``` Query parameters: | Parameter | Type | Description | | ------------------ | ------- | ----------------------------------------------------------------------- | | `limit` | integer | Page size. Defaults to `50`. | | `next_cursor` | string | Opaque cursor returned by the previous page. | | `status` | string | `pending_customer_review`, `pending_ops_review`, or `resolved`. | | `decision_code` | string | One of the decision codes listed below. | | `lab_slug` | string | Lab identifier, such as `labcorp` or `quest`. | | `created_at_start` | date | Result receipt date on or after this UTC date, formatted `YYYY-MM-DD`. | | `created_at_end` | date | Result receipt date on or before this UTC date, formatted `YYYY-MM-DD`. | Without a `status` filter, the endpoint returns actionable customer items and items that you escalated with `unsure`. Resolved items are excluded by default. Response: ```json theme={null} { "data": [ { "id": "6c3a56b7-c3ef-4edb-889a-6c4c874bcf00", "status": "pending_customer_review", "decision_code": "match_sample_id_mismatch_demo", "sub_reason_codes": [], "reason": "The sample matched, but the demographics do not line up with the existing order.", "patient": { "first_name": "Ada", "last_name": "Lovelace", "dob": "1815-12-10T00:00:00Z", "gender": "female" }, "lab": { "id": 1, "name": "Labcorp", "slug": "labcorp" }, "markers": [ { "provider_id": "005009", "name": "Complete Blood Count" } ], "interpretation": "abnormal", "result_status": "partial", "note": null, "allowed_actions": ["accept", "reject", "unsure"], "candidate_groups": [ { "user_id": "11111111-1111-1111-1111-111111111111", "candidates": [ { "candidate_type": "provenance_order", "order_id": "22222222-2222-2222-2222-222222222222", "order_transaction_id": "33333333-3333-3333-3333-333333333333", "last_status": "completed", "confidence_level": "high", "confidence_score": 0.9, "reasons": ["sample_id_match", "demographic_mismatch"], "marker_overlap": null, "status_context": null } ] } ], "created_at": "2026-07-15T14:50:40Z", "updated_at": "2026-07-15T14:50:40Z", "reviewed_at": null } ], "next_cursor": null } ``` Pass `next_cursor` unchanged into the next request. Do not parse or construct cursor values in your application. ### Get one unmatched result ```http theme={null} GET /v3/unmatched_result/{raw_result_id} ``` ```bash theme={null} curl --request GET \ --url 'https://api.tryvital.io/v3/unmatched_result/6c3a56b7-c3ef-4edb-889a-6c4c874bcf00' \ --header "x-vital-api-key: $VITAL_API_KEY" ``` The response uses the same unmatched-result shape as an item in the list response. Important fields: | Field | Meaning | | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | | `id` | Raw result ID used by the API and webhook. | | `status` | Current review state. | | `decision_code` | The primary reason the result entered this flow. | | `reason` | Human-readable summary for the reviewer. | | `result_status` | Whether the incoming lab result is `partial` or `final`. | | `allowed_actions` | Actions currently accepted by the API. Always use this field to enable UI controls. | | `candidate_groups` | Candidate orders grouped by Junction `user_id`. | | `candidate_groups[].candidates[].order_transaction_id` | Groups a candidate with its related original, replacement, or recreated orders. | Candidate confidence and reason codes are review aids; they do not replace human confirmation. A `provenance_order` is the order associated with the incoming sample or result history. An `order_option` is another order that may be a valid target. ### Accept a match ```http theme={null} POST /v3/unmatched_result/{raw_result_id}/accept ``` Use `accept` only when it appears in `allowed_actions`. Request fields: | Field | Required | Description | | ---------- | -------- | ---------------------------------------------------------------------------------------- | | `order_id` | No | Existing Junction order that should receive the result. | | `user_id` | No | Junction user who should own a replacement order when an existing order is not selected. | | `note` | No | Review context for audit and support. | If both `user_id` and `order_id` are supplied, the order must belong to that user. Send an empty object only when accepting the system's unambiguous default target. For ambiguous demographic or no-match cases, explicitly select an `order_id` or `user_id`. Example: ```bash theme={null} curl --request POST \ --url 'https://api.tryvital.io/v3/unmatched_result/6c3a56b7-c3ef-4edb-889a-6c4c874bcf00/accept' \ --header "x-vital-api-key: $VITAL_API_KEY" \ --header 'content-type: application/json' \ --data '{ "order_id": "22222222-2222-2222-2222-222222222222", "note": "Confirmed against the requisition." }' ``` The response is the standard lab order object. Depending on the decision case, acceptance may use the selected order or create/recreate an appropriate order. Always persist the order ID returned by this endpoint instead of assuming it is the same as a candidate order ID. ### Track related orders with an order transaction An order transaction groups orders that belong to the same order lifecycle. For example, an original order and an order created to replace it can have different order IDs while sharing one order transaction ID. The candidate records expose `order_transaction_id` when one is available. The order returned by `accept` includes the authoritative `order_transaction`. An abridged response looks like: ```json theme={null} { "id": "55555555-5555-5555-5555-555555555555", "order_transaction": { "id": "33333333-3333-3333-3333-333333333333", "status": "active", "orders": [ { "id": "22222222-2222-2222-2222-222222222222", "low_level_status": "cancelled", "origin": "initial", "parent_id": null }, { "id": "55555555-5555-5555-5555-555555555555", "low_level_status": "completed", "origin": "recreation", "parent_id": "22222222-2222-2222-2222-222222222222" } ] } } ``` Use `order_transaction.id` as the grouping key in your system and keep each individual order ID as a member of that group. Use `parent_id` to identify the direct predecessor and `low_level_status` to determine what happened to each order. Do not overwrite the original order ID with the replacement order ID or assume that a candidate order remains the active order after acceptance. You can retrieve all orders in the group with: ```http theme={null} GET /v3/orders?order_transaction_id={order_transaction_id} ``` Always take the transaction from the order returned by `accept`. If acceptance creates an order for a different patient, its transaction may differ from the candidate transaction shown before review. ### Reject or escalate a result ```http theme={null} POST /v3/unmatched_result/{raw_result_id}/resolve ``` Request body: ```json theme={null} { "action": "reject", "note": "This result does not belong to our patient." } ``` Available actions: | Action | Outcome | | -------- | --------------------------------------------------------------------------- | | `reject` | Marks the review item as resolved without attaching the result to an order. | | `unsure` | Sends the item to the Junction operations team for review. | Example escalation: ```bash theme={null} curl --request POST \ --url 'https://api.tryvital.io/v3/unmatched_result/6c3a56b7-c3ef-4edb-889a-6c4c874bcf00/resolve' \ --header "x-vital-api-key: $VITAL_API_KEY" \ --header 'content-type: application/json' \ --data '{ "action": "unsure", "note": "The demographics match two patients. Please review." }' ``` The response is the updated unmatched result. After `unsure`, its status is `pending_ops_review` and `allowed_actions` is empty. After `reject`, its status is `resolved` and `allowed_actions` is empty. ## Review statuses | Status | Meaning | | ------------------------- | ---------------------------------------------------------------------- | | `pending_customer_review` | The result is waiting for your decision. | | `pending_ops_review` | You selected `unsure` and Junction operations is reviewing the result. | | `resolved` | A reviewer rejected the result or otherwise completed the review. | ## Available decision cases The `decision_code` describes why automatic matching stopped. Use the API's `reason`, candidates, and `allowed_actions` together when presenting a case. | Decision code | Meaning | What to verify | | ------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | | `match_completed` | The sample matched an order that is already completed. | Confirm whether the new result belongs to the same patient and test. | | `match_cancelled` | The sample matched an order that is cancelled. | Confirm whether the result is valid and should be released through a replacement order. | | `wrong_collection` | The linked order is not in a valid collection or result-ready state. | Confirm that the collection occurred and that the candidate order is correct. | | `wrong_lab` | The patient demographics match, but the open order is for another central lab. | Confirm the receiving lab, patient, and test before accepting. | | `multiple_demo_match` | The demographics match more than one patient. | Select the correct patient and order; use `unsure` if identity cannot be confirmed. | | `match_sample_id_mismatch_demo` | The sample identifier matches an order, but the result demographics do not. | Resolve the demographic conflict before attaching the result. | | `match_demo` | The demographics match a patient, but not one unambiguous order. | Select the correct candidate order or patient. | | `no_match` | No patient or order could be matched confidently. | Select a known patient/order, reject the result, or escalate it. | ### Candidate reason codes Each candidate may include one or more machine-readable reasons: | Category | Reason codes | | ------------- | -------------------------------------------------------------------------------- | | Identity | `sample_id_match`, `demographic_match`, `demographic_mismatch`, `same_user` | | Lab | `possible_wrong_lab`, `same_lab` | | Order state | `matched_completed_order`, `matched_cancelled_order`, `invalid_collection_state` | | Test contents | `marker_overlap_exact`, `marker_overlap_partial`, `marker_overlap_none` | ## Error handling | HTTP status | Meaning | | ----------- | ---------------------------------------------------------------------------------------------------------------- | | `400` | The unmatched-results review queue is not enabled for the authenticated team. | | `404` | The item, user, or order was not found for the authenticated team, or the item is no longer customer-reviewable. | | `422` | The request is invalid, inconsistent with the selected user/order, or cannot be completed for the case. | Because another reviewer may act on an item first, re-fetch the item after a failed action before prompting the user to retry. Never attempt to work around a `404` by using an ID from another team. ## Integration checklist * Enable the unmatched-results review queue for the correct environment and team. * Subscribe the existing webhook destination to `labtest.match_review.created`. * Verify webhook signatures and handle repeated deliveries safely. * Fetch the full item from the API after receiving a webhook. * Use `allowed_actions` to control available review actions. * Require an explicit patient/order selection for ambiguous cases. * Store the order and `order_transaction.id` returned by `accept`. * Group related orders by transaction ID while retaining each individual order ID. * Reconcile outstanding items periodically with the list endpoint. # Data Prioritization Source: https://docs.junction.com/sense/data-prioritization Learn how Junction Sense automatically prioritizes data from multiple providers and source types, keeping only the highest-priority source per group. ## Overview Data prioritization automatically kicks in whenever you use a [Group By clause](/sense/query-dsl/group-by-clause). Within each group outlined by your [Group By clause](/sense/query-dsl/group-by-clause), the query executor would **implicitly**: * Sub-group the data further by their Provider and their [Source Type](/wearables/providers/data-attributions); * Keep only data from the sub-group that has the highest Source Type priority, or the highest Provider priority when multiple sub-groups exist for the same Source Type. Data prioritization works only in a [Group By](/sense/query-dsl/group-by-clause) context. If both the *Provider* and *Source Type* Source Columns are present in the [Group By clause](/sense/query-dsl/group-by-clause), the implicit [Data Prioritization](/sense/data-prioritization) behavior would be disabled. You are querying Sleep Score grouped by every 1 day: ```json theme={null} { "select": [ { "func": "newest", "arg": { "value_macro": "sleep_score" } } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "sleep" } } ] } ``` Assuming this timeline: * Day 1: The user connected Oura. * Day 5: The user connected Apple HealthKit. * Both Oura and HealthKit have been consistently sending sleep data every day since connected. #### If your team priority states that Apple HealthKit > Oura The query result would be: * Day 1-4: Sleep Score computed from Oura sleep data * Day 5-7: Sleep Score computed from Apple HealthKit sleep data #### If your team priority states that Oura > Apple HealthKit The query result would be: * Day 1-7: Sleep Score computed from Oura sleep data Apple HealthKit data are ignored in this case, because Oura is available throughout all days and has higher provider priority. ## Previewing the prioritization effect You can experiment and preview the effect of prioritization using the [Query API](/sense/using-query-api). By specifying a list of provider slugs in `config.provider_priority_overrides`, you instruct the query executor to treat these providers as the highest priority β€” above the team provider priority β€” specifically in this query invocation. ## Managing Provider Priorities You can manage the provider priorities for each summary type through the **Data Priority** section of the [Junction Dashboard](https://app.junction.com/). A larger number indicates a higher priority. ## Source Type Priorities We use pre-assigned, non-configurable Source Type priorities that follow the general expectation of data reliability. *(sorted from highest priority to lowest priority)* * `lab` * `automatic` * `watch` * `ring` * `chest_strap` * `scale` * `cuff` * `fingerprick` * `manual_scan` * `phone` * `app` * `multiple_sources` * `unknown` # Examples Source: https://docs.junction.com/sense/examples Explore practical code examples of Junction Sense Continuous Query use cases including daily sleep analysis, in both Python and JSON DSL. A couple of examples to get you started with [Continuous Query](/continuous-query-overview): ## Daily Sleep Analysis ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Sleep.col("efficiency").mean(), va.Sleep.score().mean(), va.Sleep.chronotype().newest() ).where( "type = 'long_sleep'" ).group_by( va.date_trunc(va.Sleep.index(), 1, "day") ).finalize() ``` ```jsonc JSON DSL theme={null} { "where": "type = 'long_sleep'", "select": [ { "group_key": "*" }, { "arg": { "sleep": "efficiency" }, "func": "mean" }, { "arg": { "value_macro": "sleep_score", "version": "automatic" }, "func": "mean" }, { "arg": { "value_macro": "chronotype", "version": "automatic" }, "func": "newest" } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "sleep" } } ] } ``` ## Weekly Insights Into Users' Activity ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Activity.col("heart_rate_resting").mean(), va.Activity.col("calories_total").max(), va.Activity.col("steps").min(), va.Activity.col("duration_active_second").mean() ).group_by( va.date_trunc(va.Activity.index(), 1, "week") ).finalize() ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "arg": { "activity": "heart_rate_resting" }, "func": "mean" }, { "arg": { "activity": "calories_total" }, "func": "max" }, { "arg": { "activity": "steps" }, "func": "min" }, { "arg": { "activity": "duration_active_second" }, "func": "mean" } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "week" }, "arg": { "index": "activity" } } ] } ``` ## First Glucose Measurement Of The Day Grouped By Source Type and Provider ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Timeseries.col("glucose").field("value").oldest() ).group_by( va.date_trunc(va.Timeseries.index(), 1, "day"), va.Source.col("source_provider"), va.Source.col("source_type") ).finalize() ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "arg": { "field": "value", "timeseries": "glucose" }, "func": "oldest" } ], "group_by": [ { "arg": { "index": "timeseries" }, "date_trunc": {"unit": "day", "value": 1} }, {"source": "source_provider"}, {"source": "source_type"} ] } ``` ## Daily Summaries of Metabolic Biomarkers Grouped By Source Type and Provider ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Timeseries.col("glucose").field("value").mean(), va.Timeseries.col("heartrate").field("value").mean(), va.Timeseries.col("steps").field("value").sum(), va.Timeseries.col("hrv").field("value").mean(), va.Timeseries.col("calories_active").field("value").sum(), va.Timeseries.col("body_temperature").field("value").mean(), va.Timeseries.col("body_temperature").field("value").min(), va.Timeseries.col("body_temperature").field("value").max(), ).group_by( va.date_trunc(va.Timeseries.index(), 1, "day"), va.Source.col("source_provider"), va.Source.col("source_type"), ).finalize() ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "arg": { "timeseries": "glucose", "field": "value" }, "func": "mean" }, { "arg": { "timeseries": "heartrate", "field": "value" }, "func": "mean" }, { "arg": { "timeseries": "steps", "field": "value" }, "func": "sum" }, { "arg": { "timeseries": "hrv", "field": "value" }, "func": "mean" }, { "arg": { "timeseries": "calories_active", "field": "value" }, "func": "sum" }, { "arg": { "timeseries": "body_temperature", "field": "value" }, "func": "mean" }, { "arg": { "timeseries": "body_temperature", "field": "value" }, "func": "min" }, { "arg": { "timeseries": "body_temperature", "field": "value" }, "func": "max" } ], "group_by": [ { "arg": { "index": "timeseries" }, "date_trunc": {"unit": "day", "value": 1} }, {"source": "source_provider"}, {"source": "source_type"} ] } ``` ## Weekly Exercise Summary ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.Workout.col("calories").max(), va.Workout.col("calories").min(), va.Workout.col("heart_rate_zone_1").mean(), va.Workout.col("heart_rate_zone_2").mean(), va.Workout.col("heart_rate_zone_3").mean(), va.Workout.col("heart_rate_zone_4").mean(), va.Workout.col("heart_rate_zone_5").mean(), va.Workout.col("heart_rate_zone_6").mean(), va.Workout.col("distance_meter").max(), va.Workout.col("duration_active_second").mean() ).group_by( va.date_trunc(va.Workout.index(), 1, "week") ).finalize() ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "arg": { "workout": "calories" }, "func": "max" }, { "arg": { "workout": "calories" }, "func": "min" }, { "arg": { "workout": "heart_rate_zone_1" }, "func": "mean" }, { "arg": { "workout": "heart_rate_zone_2" }, "func": "mean" }, { "arg": { "workout": "heart_rate_zone_3" }, "func": "mean" }, { "arg": { "workout": "heart_rate_zone_4" }, "func": "mean" }, { "arg": { "workout": "heart_rate_zone_5" }, "func": "mean" }, { "arg": { "workout": "heart_rate_zone_6" }, "func": "mean" }, { "arg": { "workout": "distance_meter" }, "func": "max" }, { "arg": { "workout": "duration_active_second" }, "func": "mean" } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "week" }, "arg": { "index": "workout" } } ] } ``` ## Menstrual Cycle Summary Period end, cycle end, mean basal body temperature, and number of meaningful flow days β€” one row per cycle. ```python Python DSL theme={null} import vitalx.aggregation as va va.select( va.group_key("*"), va.MenstrualCycle.col("period_end").newest(), va.MenstrualCycle.col("cycle_end").newest(), va.MenstrualCycle.col("basal_body_temperature") .unnest_and_select(lambda col: col.field("value").mean()) .mean(), va.MenstrualCycle.col("menstrual_flow") .unnest_and_select(lambda col: col.count()) .where("flow != 'none'") .mean(), ).group_by( va.date_trunc(va.MenstrualCycle.index(), 1, "day") ).finalize() ``` ```jsonc JSON DSL theme={null} { "select": [ { "group_key": "*" }, { "func": "newest", "arg": { "menstrual_cycle": "period_end" } }, { "func": "newest", "arg": { "menstrual_cycle": "cycle_end" } }, { "func": "mean", "arg": { "select": { "func": "mean", "arg": { "field_for": "menstrual_cycle", "basal_body_temperature": "value" } }, "from": { "unnest": { "menstrual_cycle": "basal_body_temperature" } } } }, { "func": "mean", "arg": { "select": { "func": "count", "arg": null }, "from": { "unnest": { "menstrual_cycle": "menstrual_flow" } }, "where": "flow != 'none'" } } ], "group_by": [ { "date_trunc": { "value": 1, "unit": "day" }, "arg": { "index": "menstrual_cycle" } } ] } ``` # Managing Queries Source: https://docs.junction.com/sense/managing-queries Create, edit, and manage your Continuous Query configurations using the Junction Dashboard.