Lab testing integration for healthtech: extending Junction’s example app

Amanda Savluchinske
April 30, 2025

Integrating lab testing into your healthtech product doesn’t have to be complicated. Many services specialize in connecting with labs across the country, saving development teams’ time by offering robust APIs that standardize integration. For this example, we’ve chosen to work with one such service: Junction.

In this article, we'd like to showcase how we extended Junction's example app to support a simple workflow for lab orders.

What is Junction (formerly Vital)?

Junction is a modern health data platform that enables developers to seamlessly integrate and manage information from various sources.

Key benefits include:

  • Unified integration with wearable devices and labs across the country;
  • Ready-made client libraries and comprehensive documentation;
  • Robust API with standardized data formats;
  • Built-in compliance and security features;
  • Scalable infrastructure for growing health applications.

This comprehensive approach makes the development process significantly easier for teams building impactful health and wellness solutions.

Formerly known as Vital, Junction recently completed a rebranding and secured $18 million in Series A funding, further underscoring its commitment to expanding developer-centric tools and services in the healthcare technology space.

Leveraging Junction for lab integration in digital health 

Now that we understand what Junction offers, let's explore how developers can leverage this platform for specific applications in digital health. The versatility of Junction's API makes it suitable for a wide range of healthcare scenarios.

Junction’s platform opens up a range of possibilities for digital health applications, particularly in lab integrations. Telehealth providers, for example, can quickly implement lab ordering and result retrieval without having to manage multiple lab partnerships on their own.

Remote patient monitoring solutions can also benefit by combining lab data with real-time device readings for a more comprehensive view of patient health. In addition, wellness and preventative care applications can leverage Junction to give users on-demand access to lab tests and results.

Of course, there are alternatives to Junction as well. Platforms like GetLabs offer unified healthcare data access and can serve similar needs, each with its own approach and feature set. Depending on your product requirements, whether you prioritize specific integrations, data standards, or types of support, any of these platforms may fit the bill. The key is finding a solution that aligns with your product’s roadmap, compliance obligations, and development resources.

Extending Junction’s quickstart app to support lab orders

Having evaluated Junction's capabilities, we wanted to put theory into practice by building a functional lab ordering system. This hands-on approach would allow us to firsthand assess the platform's developer experience and API robustness.

The company provides several libraries in the most popular programming languages for integrating with their APIs and a quick-start example project in Next.js, TypeScript, and FastAPI, showcasing their integration with wearable technology.

Some of Junction's many libraries on GitHub: https://github.com/tryVital

Upon reviewing their quick-start example project, we observed no instances where they integrated their own lab functionality. They offer a robust dashboard enabling users to perform most required actions.

This represents a significant product differentiator for businesses aiming to develop simple MVPs or relying on internal staff for scheduling tests. However, in this age of personalization, it's clear that many companies prefer to integrate and create their own experiences instead of disrupting workflows by forcing users to switch to another platform for specific actions.

A screenshot of Junction's dashboard showing a test catalog.

Therefore, we expanded the original quick-start example into our own fork. In this fork, we demonstrate how simple it can be to create a lab test ordering experience from scratch using Junction's API. 

Developer experience: exploring Junction’s sandbox and documentation

From the get-go, we noticed how developer-friendly Junction is. They offer a sandbox for testing purposes, which contains excellent examples of data like laboratories across the country, biomarkers, etc.

Companies must ensure that no sensitive data is shared without the correct safeguards in an industry as regulated and privacy-centered as health. Sandbox environments with this level of quality dummy data are great finds that allow software engineers to build experiences that come close to how they'll work out in reality without compromising privacy.

Junction also has a fair share of API documentation, with tips on how to get started with the integration, API references, explanations of how webhooks and events work, and ETL pipelines.

Building the lab workflow: panels, biomarkers, orders, results

After forking the original quick-start repo, we quickly noticed that the example app's API version was older than what we needed for our implementation. After updating the library, we were good to go with our experiment.

The objective of our extension was to implement the following features into the quick-start example:

  • List and create lab panels;
  • View and select biomarkers;
  • List, create, and cancel lab orders;
  • View lab results.
from vital.client import Vital
from vital.environment import VitalEnvironment
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
import os
from dotenv import load_dotenv
load_dotenv()

app = FastAPI()
VITAL_API_KEY = os.getenv("VITAL_API_KEY")
VITAL_ENVIRONMENT = os.getenv("VITAL_ENV")

if VITAL_ENVIRONMENT == "sandbox":
    vital_env = VitalEnvironment.SANDBOX
elif VITAL_ENVIRONMENT == "production":
    vital_env = VitalEnvironment.PRODUCTION

client = Vital(api_key=VITAL_API_KEY, environment=vital_env)

app.add_middleware(
    CORSMiddleware,
    allow_origins=[*],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/token/{user_id}")
def get_token(user_id: str):
    return client.link.token(user_id=user_id)

The starting point was through biomarkers and lab panels, as they would be the basis for managing our lab orders. Lab panels work as “templates” for ordering lab tests. They can only be associated with one lab at a time, which in turn, contains biomarkers specific to that lab.

@app.get("/tests/")
def get_tests():
    return client.lab_tests.get()


@app.post("/tests/")
def create_test(data: dict):
    name = data["name"]
    method = data["method"]
    marker_ids = data["marker_ids"]
    method_mapping = {
        "testkit": LabTestCollectionMethod.TESTKIT,
        "walk_in_test": LabTestCollectionMethod.WALK_IN_TEST,
        "at_home_phlebotomy": LabTestCollectionMethod.AT_HOME_PHLEBOTOMY,
    }
    return client.lab_tests.create(name=name, description='', method=method_mapping[method], marker_ids=marker_ids)


@app.get("/markers/")
def get_markers(lab_id: Optional[int] = None):
    if lab_id:
        return client.lab_tests.get_markers(lab_id=lab_id)
    else:
        return client.lab_tests.get_markers()


@app.get("/tests/markers/{lab_test_id}/")
def get_markers_for_lab_test(lab_test_id: str):
    return client.lab_tests.get_markers_for_lab_test(lab_test_id=lab_test_id)

With panels out of the way, we implemented the actual ordering workflow: by getting orders, creating them, canceling, as well as fetching the results.

@app.get("/orders/")
def get_orders():
    return client.lab_tests.get_orders()


@app.post("/orders/")
def create_order(data: dict):
    return client.lab_tests.create_order(
        user_id=data["user_id"],
        patient_details=data["patient_details"],
        patient_address=data["patient_address"],
        order_set={"lab_test_ids": [data["lab_test_id"]]},
        collection_method=data["collection_method"]
    )


@app.post("/orders/{order_id}/cancel/")
def cancel_order(order_id: str):
    return client.lab_tests.cancel_order(order_id=order_id)


@app.get("/labs/")
def get_labs():
    return client.lab_tests.get_labs()


@app.get("/orders/{order_id}/results/pdf/")
def get_order_pdf(order_id: str):
    try:
        pdf_chunks = client.lab_tests.get_result_pdf(order_id=order_id)
        pdf_data = b''.join(list(pdf_chunks))
        
        return Response(
            content=pdf_data,
            media_type="application/pdf",
            headers={
                "Content-Disposition": f'attachment; filename="lab-results-{order_id}.pdf"'
            }
        )
    except Exception as e:
        print(f"Error fetching PDF: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))

Results: a working proof of concept for lab test integration

By the end of our experiment, we had a fully functional flow for lab panels, biomarkers, and orders, complete with the ability to create, update, and cancel lab orders and view detailed test results.

While most of our effort went into polishing the frontend experience, handling form validations, user feedback, and other UI details, the backend integration proved straightforward. Our results show that, with minimal code changes, you can quickly spin up a basic lab-testing workflow using Junction’s API, paving the way for more advanced functionality as your product scales.

Here's the full demo of the proof of concept:

You can check out the complete code here.

Need any help in your healthtech journey?
Get in touch with our experts for a consultation