Private Beta 25 integration spots available this quarter

Add clinical-grade lung monitoring in 50 lines of code.

LungDx turns the front camera into a spirometer. One SDK. Spirometry-quality respiratory metrics in your app - no hardware, no extra steps for the user.

Validated against hospital spirometers
Processes on-device
HIPAA-ready
Live 30s session
14
br/min
Resp. rate
3.42
L
FEV1
412
L/min
Peak flow
Regular
Pattern
14
br/min
Resp. Rate
3.42
L
FEV1
412
L/min
Peak Flow
Regular
Pattern

What is this, actually?

A 30-second session. Your app calls one method. The user breathes normally. You get structured respiratory data.

Capture

Your app calls LungDx.startSession(). The user holds the phone in front of them and breathes normally for 30 seconds. No forced maneuvers, no special instructions.

Process

Our on-device model analyzes facial micro-movements, chest rise, and photoplethysmography-style color shifts. All computation stays on the device - no frames are transmitted.

Return

You receive a structured JSON object with respiratory rate, FEV1, peak flow, and a breathing-pattern classification - ready to display, log, or sync to your backend.

let session = try await LungDx.startSession(.thirtySecondScreen)
let result = try await session.measurement

// result.fev1             → 3.42 L
// result.respiratoryRate  → 14 br/min
// result.peakFlow         → 412 L/min
// result.pattern          → .regular
// result.confidence       → 0.93
val session = LungDx.startSession(SessionType.THIRTY_SECOND_SCREEN)
val result = session.measurement.await()

// result.fev1             → 3.42f
// result.respiratoryRate  → 14
// result.peakFlow         → 412f
// result.pattern          → Pattern.REGULAR
// result.confidence       → 0.93f
import { LungDx } from '@lungdx/web-sdk'

const session = await LungDx.startSession({ duration: 30 })
const result = await session.measurement

// result.fev1             → 3.42
// result.respiratoryRate  → 14
// result.peakFlow         → 412
// result.pattern          → 'regular'
// result.confidence       → 0.93
import { LungDx, SessionType } from '@lungdx/react-native'

const result = await LungDx.measure({
  type: SessionType.THIRTY_SECOND,
  onProgress: (pct) => setProgress(pct),
})

// result.fev1             → 3.42
// result.respiratoryRate  → 14
// result.confidence       → 0.93
final result = await LungDx.startSession(
  type: SessionType.thirtySecondScreen,
)

// result.fev1             → 3.42
// result.respiratoryRate  → 14
// result.peakFlow         → 412
// result.pattern          → BreathingPattern.regular
Full quickstart →

Why it works

Every claim is backed by data. Here are the four we lead with.

r=0.91

Validated against hospital spirometers

n=412 paired measurements across FEV1. Collected across three clinical sites.

Read the paper →
47

Device models tested

Works on phones from 2018 onward, across iOS and Android. Full compatibility matrix available.

See device support →
<3%

Performance variance across skin tones

Validated across Fitzpatrick I–VI in our validation set. Inclusive by design, not retrofit.

Demographic breakdown →
0 bytes

Raw video transmitted

No raw video leaves the device. Ever. Only derived metrics, and only if you explicitly request result sync.

Privacy architecture →

From zero to measurement in 5 minutes

  1. 1
    Install the SDKOne package. No native dependencies to configure.
  2. 2
    Initialize with your API keyOne line at app start. Keys are scoped per-environment.
  3. 3
    Start a session30-second measurement, fully on-device.
  4. 4
    Read resultsTyped result object: FEV1, RR, peak flow, confidence.
Full quickstart →
// 1. Install: Swift Package Manager
// .package(url: "https://github.com/lungdx/lungdx-swift", from: "1.0.0")

// 2. Initialize (AppDelegate / @main)
import LungDx

LungDx.configure(apiKey: "lx_your_key_here")

// 3. Request permission (once)
await LungDx.requestCameraPermission()

// 4. Start a session
let session = try await LungDx.startSession(.thirtySecondScreen)
let result = try await session.measurement

// 5. Handle the result
guard result.confidence > 0.8 else {
  handleLowConfidence(result.confidenceReason)
  return
}

display(fev1: result.fev1, rr: result.respiratoryRate)
// 1. Install: build.gradle.kts
// implementation("com.lungdx:sdk-android:1.0.0")

// 2. Initialize (Application class)
LungDx.configure(apiKey = "lx_your_key_here")

// 3. Request permission (once)
LungDx.requestCameraPermission(this)

// 4. Start a session (coroutine scope)
val session = LungDx.startSession(SessionType.THIRTY_SECOND_SCREEN)
val result = session.measurement.await()

// 5. Handle the result
if (result.confidence < 0.8f) {
  handleLowConfidence(result.confidenceReason)
  return
}
displayMetrics(result)
// 1. Install
// npm install @lungdx/web-sdk

// 2. Initialize (once at app start)
import { LungDx } from '@lungdx/web-sdk'

LungDx.configure({ apiKey: 'lx_your_key_here' })

// 3. Request permission
await LungDx.requestCameraPermission()

// 4. Start a session
const session = await LungDx.startSession({ duration: 30 })
const result = await session.measurement

// 5. Handle the result
if (result.confidence < 0.8) {
  handleLowConfidence(result.confidenceReason)
} else {
  displayMetrics(result)
}
// 1. Install
// npm install @lungdx/react-native
// npx pod-install (iOS)

// 2. Initialize
import { LungDx } from '@lungdx/react-native'
LungDx.configure({ apiKey: 'lx_your_key_here' })

// 3. In your component
const measureLungs = async () => {
  const result = await LungDx.measure({
    type: 'thirty_second',
    onProgress: (pct) => setProgress(pct),
  })
  if (result.confidence >= 0.8) {
    setMetrics(result)
  }
}
// 1. Install: pubspec.yaml
// lungdx_flutter: ^1.0.0

// 2. Initialize
import 'package:lungdx_flutter/lungdx_flutter.dart';

await LungDx.configure(apiKey: 'lx_your_key_here');

// 3. Start a session
final result = await LungDx.startSession(
  type: SessionType.thirtySecondScreen,
);

// 4. Handle the result
if (result.confidence < 0.8) {
  handleLowConfidence(result);
} else {
  displayMetrics(result);
}

Currently in private beta

Working with 14 digital health teams across asthma management, telehealth, and digital therapeutics.

See open beta partners →

We're letting in 25 more teams this quarter.

If you're shipping a health app and want to add lung monitoring, tell us about it.

Apply for early access →