Complete documentation for the Eight Sleep smart bed API integration and SmartBedAPI client library.
- Overview
- Authentication
- SmartBedAPI Class
- API Endpoints
- Data Types
- Response Formats
- Error Handling
- Rate Limiting
- Code Examples
The Eight Sleep API provides programmatic access to Pod smart bed temperature control, user management, and device status monitoring. This reference covers the complete API surface available through the SmartBedAPI client library.
- Authentication API:
https://auth-api.8slp.net - Client API:
https://client-api.8slp.net - Application API:
https://app-api.8slp.net
Eight Sleep uses OAuth 2.0 with session token-based authentication. The API supports both email/password and client credentials flows.
new SmartBedAPI(config: EightSleepConfig)| Parameter | Type | Required | Description |
|---|---|---|---|
config |
EightSleepConfig |
Yes | Authentication configuration |
interface EightSleepConfig {
email: string; // Eight Sleep account email
password: string; // Eight Sleep account password
clientId?: string; // OAuth client ID (optional)
clientSecret?: string; // OAuth client secret (optional)
}import { SmartBedAPI } from './src/smartbed-api';
const api = new SmartBedAPI({
email: 'user@example.com',
password: 'secure-password',
clientId: '0894c7f33bb94800a03f1f4df13a4f38',
clientSecret: 'f0954a3e0e9b47348e98fc5f0b2d45c3b4ba1790e65973febc690037bdadceba'
});Authenticates with Eight Sleep servers and retrieves session token.
async authenticate(): Promise<AuthResponse>Returns: Promise<AuthResponse> - Authentication response with session details
Throws:
Error- Authentication failed with invalid credentialsError- Network or API communication error
Example:
try {
const authData = await api.authenticate();
console.log('Authentication successful');
} catch (error) {
console.error('Authentication failed:', error.message);
}Retrieves list of devices associated with the authenticated user account.
async getDevices(): Promise<Device[]>Returns: Promise<Device[]> - Array of device objects
Auto-authenticates: Yes (calls authenticate() if no token present)
Example:
const devices = await api.getDevices();
console.log('Found devices:', devices.map(d => d.id));Controls bed temperature for left and/or right sides.
async setTemperature(settings: TemperatureSettings): Promise<void>| Parameter | Type | Required | Description |
|---|---|---|---|
settings |
TemperatureSettings |
Yes | Temperature configuration |
interface TemperatureSettings {
left?: number; // Left side temperature (-100 to 100)
right?: number; // Right side temperature (-100 to 100)
duration?: number; // Duration in seconds (0 = continuous)
}Temperature Scale:
-100 to -1: Cooling (cold)0: Neutral/Off1 to 100: Heating (warm)
Examples:
// Set both sides to cool
await api.setTemperature({ left: -50, right: -50 });
// Set left cool, right warm for 1 hour
await api.setTemperature({
left: -30,
right: 40,
duration: 3600
});
// Turn off right side only
await api.setTemperature({ right: 0 });Retrieves current device status including temperature, presence, and settings.
async getStatus(): Promise<DeviceStatus>Returns: Promise<DeviceStatus> - Current device status
Example:
const status = await api.getStatus();
console.log('Current left temp:', status.left.tempBed);
console.log('Target right temp:', status.right.tempTarget);Convenience method to turn on bed temperature control (sets to neutral).
async turnOn(side: 'left' | 'right' | 'both' = 'both'): Promise<void>| Parameter | Type | Default | Description |
|---|---|---|---|
side |
'left' | 'right' | 'both' |
'both' |
Which side(s) to turn on |
Example:
// Turn on both sides (neutral temperature)
await api.turnOn();
// Turn on left side only
await api.turnOn('left');Convenience method to turn off bed temperature control.
async turnOff(side: 'left' | 'right' | 'both' = 'both'): Promise<void>Parameters: Same as turnOn()
Example:
// Turn off both sides
await api.turnOff();
// Turn off right side only
await api.turnOff('right');Authenticates user and returns session token.
URL: https://auth-api.8slp.net/v1/login
Request Body:
{
"email": "user@example.com",
"password": "password",
"client_id": "optional_client_id",
"client_secret": "optional_client_secret"
}Response:
{
"session": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"userId": "user-uuid-here",
"expiresAt": "2024-01-01T00:00:00Z"
}
}Alternative URL: https://client-api.8slp.net/v1/login (fallback endpoint)
Retrieves devices for authenticated user.
URL: https://client-api.8slp.net/v1/users/{userId}/devices
Headers:
Authorization: Bearer {token}
Session-Token: {token}
Response:
[
{
"id": "device-uuid",
"deviceId": "POD12345",
"model": "pod-pro",
"firmwareVersion": "1.2.3",
"sides": ["left", "right"]
}
]Sets bed temperature for specified device.
URL: https://client-api.8slp.net/v1/devices/{deviceId}/temperature
Headers:
Authorization: Bearer {token}
Session-Token: {token}
Content-Type: application/json
Request Body:
{
"left": {
"level": -50,
"duration": 3600
},
"right": {
"level": 25,
"duration": 0
}
}Response:
{
"success": true,
"message": "Temperature updated"
}Retrieves current device status and settings.
URL: https://client-api.8slp.net/v1/devices/{deviceId}/status
Headers:
Authorization: Bearer {token}
Session-Token: {token}
Response:
{
"deviceId": "device-uuid",
"online": true,
"left": {
"isOwner": true,
"userId": "user-uuid",
"side": "left",
"presence": true,
"tempTarget": -50,
"tempBed": -45
},
"right": {
"isOwner": false,
"userId": "partner-uuid",
"side": "right",
"presence": false,
"tempTarget": 0,
"tempBed": 2
}
}interface Device {
id: string; // Unique device identifier
deviceId: string; // Human-readable device ID
model: string; // Device model (e.g., "pod-pro")
firmwareVersion: string; // Current firmware version
sides: string[]; // Available sides ["left", "right"]
}interface BedSide {
isOwner: boolean; // Is current user the owner of this side
userId: string; // User ID for this side
side: 'left' | 'right'; // Which side of the bed
presence: boolean; // Is someone currently in bed
tempTarget: number; // Target temperature (-100 to 100)
tempBed: number; // Current bed temperature
}interface DeviceStatus {
deviceId: string; // Device identifier
online: boolean; // Is device online
left: BedSide; // Left side status
right: BedSide; // Right side status
}interface AuthResponse {
session: {
token: string; // JWT session token
userId: string; // Authenticated user ID
expiresAt: string; // Token expiration time
};
}All successful API calls return JSON with the requested data:
{
"data": { ... },
"success": true
}Failed API calls return JSON with error details:
{
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Invalid email or password",
"details": { ... }
},
"success": false
}| Code | Description | HTTP Status |
|---|---|---|
AUTHENTICATION_FAILED |
Invalid credentials | 401 |
TOKEN_EXPIRED |
Session token expired | 401 |
DEVICE_NOT_FOUND |
Device ID not found | 404 |
INVALID_TEMPERATURE |
Temperature out of range | 400 |
RATE_LIMIT_EXCEEDED |
Too many requests | 429 |
DEVICE_OFFLINE |
Device not connected | 503 |
try {
await api.setTemperature({ left: -50, right: 25 });
} catch (error) {
if (error.message.includes('401')) {
// Re-authenticate and retry
await api.authenticate();
await api.setTemperature({ left: -50, right: 25 });
} else if (error.message.includes('429')) {
// Rate limited - wait and retry
await new Promise(resolve => setTimeout(resolve, 5000));
await api.setTemperature({ left: -50, right: 25 });
} else {
console.error('API Error:', error.message);
}
}The Eight Sleep API implements rate limiting to prevent abuse:
- Authentication: 5 requests per minute
- Device Status: 30 requests per minute
- Temperature Control: 20 requests per minute
- Device List: 10 requests per minute
- Cache session tokens - Don't authenticate on every request
- Implement exponential backoff - Wait progressively longer between retries
- Batch operations - Group multiple temperature changes together
- Monitor rate limits - Check response headers for limit information
class RateLimitedAPI extends SmartBedAPI {
private lastRequest = 0;
private minInterval = 3000; // 3 seconds minimum between requests
async setTemperature(settings: TemperatureSettings) {
const now = Date.now();
const timeSinceLastRequest = now - this.lastRequest;
if (timeSinceLastRequest < this.minInterval) {
await new Promise(resolve =>
setTimeout(resolve, this.minInterval - timeSinceLastRequest)
);
}
this.lastRequest = Date.now();
return super.setTemperature(settings);
}
}import { SmartBedAPI } from './src/smartbed-api';
const api = new SmartBedAPI({
email: process.env.EIGHT_SLEEP_EMAIL!,
password: process.env.EIGHT_SLEEP_PASSWORD!
});
// Authenticate and get device info
await api.authenticate();
const devices = await api.getDevices();
console.log('Connected to device:', devices[0].deviceId);
// Set temperature
await api.setTemperature({ left: -30, right: 20 });// Create temperature schedule
const schedule = [
{ time: '22:00', temp: { left: -20, right: -20 } }, // Cool for sleep
{ time: '06:00', temp: { left: 10, right: 10 } }, // Warm for wake
{ time: '08:00', temp: { left: 0, right: 0 } } // Turn off
];
for (const event of schedule) {
// Schedule with duration until next event
const duration = getSecondsUntil(event.time);
await api.setTemperature({ ...event.temp, duration });
}async function setTemperatureWithRetry(api: SmartBedAPI, settings: TemperatureSettings) {
const maxRetries = 3;
let attempt = 0;
while (attempt < maxRetries) {
try {
await api.setTemperature(settings);
return; // Success
} catch (error) {
attempt++;
if (error.message.includes('401') && attempt === 1) {
// Re-authenticate on first 401 error
await api.authenticate();
continue;
}
if (attempt >= maxRetries) {
throw error; // Give up after max retries
}
// Exponential backoff
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, attempt) * 1000)
);
}
}
}// Monitor bed status every 30 seconds
setInterval(async () => {
try {
const status = await api.getStatus();
console.log(`Left: ${status.left.tempBed}°C (target: ${status.left.tempTarget}°C)`);
console.log(`Right: ${status.right.tempBed}°C (target: ${status.right.tempTarget}°C)`);
// Alert if someone gets in bed
if (status.left.presence && !previousStatus?.left.presence) {
console.log('Someone got into the left side of the bed');
}
previousStatus = status;
} catch (error) {
console.error('Status check failed:', error.message);
}
}, 30000);// Type-safe temperature presets
interface TemperaturePreset {
name: string;
settings: TemperatureSettings;
description: string;
}
const presets: TemperaturePreset[] = [
{
name: 'sleep',
settings: { left: -40, right: -40, duration: 28800 }, // 8 hours
description: 'Cool temperature for sleeping'
},
{
name: 'wake',
settings: { left: 15, right: 15, duration: 1800 }, // 30 minutes
description: 'Gentle warming for wake-up'
},
{
name: 'off',
settings: { left: 0, right: 0 },
description: 'Turn off temperature control'
}
];
// Apply preset by name
async function applyPreset(api: SmartBedAPI, presetName: string) {
const preset = presets.find(p => p.name === presetName);
if (!preset) {
throw new Error(`Preset '${presetName}' not found`);
}
console.log(`Applying ${preset.name}: ${preset.description}`);
await api.setTemperature(preset.settings);
}