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
| Parameter | Type | Required | Description |
|---|---|---|---|
tokenProvider | TokenProvider | Yes | Token management implementation |
options | WhoopClientOptions | No | Client 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
| Error | Description |
|---|---|
WhoopAuthError | Token invalid or expired (401) |
WhoopRateLimitError | Rate limit exceeded (429) |
WhoopApiError | Other 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);