Skip to main content

WhoopClient

The WhoopClient class provides programmatic access to the WHOOP API with automatic token management and data normalization.

Constructor

import { WhoopClient } from '@wellpipe/whoop';

const client = new WhoopClient(tokenProvider: TokenProvider, options?: WhoopClientOptions);

Parameters

ParameterTypeRequiredDescription
tokenProviderTokenProviderYesToken management implementation
optionsWhoopClientOptionsNoClient configuration

Options

interface WhoopClientOptions {
/** Base URL for WHOOP API (default: https://api.prod.whoop.com) */
baseUrl?: string;

/** Request timeout in milliseconds (default: 30000) */
timeout?: number;

/** Maximum retry attempts (default: 3) */
maxRetries?: number;

/** Enable debug logging (default: false) */
debug?: boolean;
}

HealthProvider Methods

These methods implement the HealthProvider interface from @wellpipe/core.

getSleep

Get normalized sleep data for a date range.

async getSleep(startDate: string, endDate: string): Promise<SleepData[]>

Parameters:

  • startDate - Start date (YYYY-MM-DD or ISO 8601)
  • endDate - End date (YYYY-MM-DD or ISO 8601)

Returns: Array of SleepData objects

Example:

const sleepData = await client.getSleep('2024-01-01', '2024-01-07');

for (const sleep of sleepData) {
console.log(`${sleep.start}: Score ${sleep.score}, Duration ${sleep.durationMs / 3600000}h`);
}

getRecovery

Get normalized recovery data for a date range.

async getRecovery(startDate: string, endDate: string): Promise<RecoveryData[]>

Parameters:

  • startDate - Start date (YYYY-MM-DD)
  • endDate - End date (YYYY-MM-DD)

Returns: Array of RecoveryData objects

Example:

const recoveryData = await client.getRecovery('2024-01-01', '2024-01-07');

for (const recovery of recoveryData) {
console.log(`${recovery.date}: Score ${recovery.score}, HRV ${recovery.metrics?.hrv}ms`);
}

getWorkouts

Get normalized workout data for a date range.

async getWorkouts(startDate: string, endDate: string): Promise<WorkoutData[]>

Parameters:

  • startDate - Start date (YYYY-MM-DD or ISO 8601)
  • endDate - End date (YYYY-MM-DD or ISO 8601)

Returns: Array of WorkoutData objects

Example:

const workouts = await client.getWorkouts('2024-01-01', '2024-01-07');

for (const workout of workouts) {
console.log(`${workout.sportType}: Strain ${workout.strain}, Duration ${workout.durationMs / 60000}min`);
}

Extended Methods

These methods provide additional functionality beyond the core interface.

getCycles

Get physiological cycle data (the daily period from wake to wake).

async getCycles(startDate: string, endDate: string): Promise<CycleData[]>

Returns:

interface CycleData {
id: string;
start: string;
end: string;
strain: number;
kilojoules: number;
averageHeartRate: number;
maxHeartRate: number;
}

getProfile

Get user profile information.

async getProfile(): Promise<UserProfile>

Returns:

interface UserProfile {
userId: string;
email: string;
firstName: string;
lastName: string;
}

getBodyMeasurement

Get body measurement data.

async getBodyMeasurement(): Promise<BodyMeasurement>

Returns:

interface BodyMeasurement {
heightMeter: number;
weightKilogram: number;
maxHeartRate: number;
}

Raw API Access

For advanced use cases, you can access the raw WHOOP API responses.

getRawSleep

async getRawSleep(params: {
start?: string;
end?: string;
limit?: number;
nextToken?: string;
}): Promise<WhoopSleepResponse>

getRawRecovery

async getRawRecovery(params: {
start?: string;
end?: string;
limit?: number;
nextToken?: string;
}): Promise<WhoopRecoveryResponse>

getRawWorkouts

async getRawWorkouts(params: {
start?: string;
end?: string;
limit?: number;
nextToken?: string;
}): Promise<WhoopWorkoutResponse>

Error Handling

The client throws typed errors for different failure scenarios:

import { WhoopApiError, WhoopAuthError, WhoopRateLimitError } from '@wellpipe/whoop';

try {
const data = await client.getSleep('2024-01-01', '2024-01-07');
} catch (error) {
if (error instanceof WhoopAuthError) {
// Token expired or invalid - need to re-authenticate
console.error('Authentication failed:', error.message);
} else if (error instanceof WhoopRateLimitError) {
// Rate limit exceeded - wait and retry
console.error('Rate limited, retry after:', error.retryAfter);
} else if (error instanceof WhoopApiError) {
// Other API error
console.error('API error:', error.statusCode, error.message);
} else {
throw error;
}
}

Error Types

ErrorDescription
WhoopAuthErrorToken invalid or expired (401)
WhoopRateLimitErrorRate limit exceeded (429)
WhoopApiErrorOther API errors

Pagination

WHOOP API responses are paginated. The client handles pagination automatically, but you can control it for large datasets:

// Get all data (automatic pagination)
const allSleep = await client.getSleep('2024-01-01', '2024-12-31');

// Or paginate manually for memory efficiency
async function* getSleepPaginated(client: WhoopClient, start: string, end: string) {
let nextToken: string | undefined;

do {
const response = await client.getRawSleep({ start, end, limit: 25, nextToken });
yield* response.records;
nextToken = response.next_token;
} while (nextToken);
}

for await (const sleep of getSleepPaginated(client, '2024-01-01', '2024-12-31')) {
console.log(sleep);
}

Testing

Use the mock client for testing:

import { MockWhoopClient } from '@wellpipe/whoop/testing';

const mockClient = new MockWhoopClient();

// Set up mock data
mockClient.setSleepData([
{
id: 'test-1',
providerId: '1',
start: '2024-01-15T23:00:00.000Z',
end: '2024-01-16T07:00:00.000Z',
durationMs: 28800000,
isNap: false,
score: 85,
},
]);

// Use in tests
const sleep = await mockClient.getSleep('2024-01-15', '2024-01-16');
expect(sleep).toHaveLength(1);
expect(sleep[0].score).toBe(85);