Skip to content

Latest commit

 

History

History
632 lines (489 loc) · 14.1 KB

File metadata and controls

632 lines (489 loc) · 14.1 KB

Eight Sleep API Reference

Complete documentation for the Eight Sleep smart bed API integration and SmartBedAPI client library.

Table of Contents

Overview

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.

Base URLs

  • Authentication API: https://auth-api.8slp.net
  • Client API: https://client-api.8slp.net
  • Application API: https://app-api.8slp.net

Authentication

Eight Sleep uses OAuth 2.0 with session token-based authentication. The API supports both email/password and client credentials flows.

SmartBedAPI Class

Constructor

new SmartBedAPI(config: EightSleepConfig)

Parameters

Parameter Type Required Description
config EightSleepConfig Yes Authentication configuration

EightSleepConfig Interface

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)
}

Example

import { SmartBedAPI } from './src/smartbed-api';

const api = new SmartBedAPI({
  email: 'user@example.com',
  password: 'secure-password',
  clientId: '0894c7f33bb94800a03f1f4df13a4f38',
  clientSecret: 'f0954a3e0e9b47348e98fc5f0b2d45c3b4ba1790e65973febc690037bdadceba'
});

Methods

authenticate()

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 credentials
  • Error - Network or API communication error

Example:

try {
  const authData = await api.authenticate();
  console.log('Authentication successful');
} catch (error) {
  console.error('Authentication failed:', error.message);
}

getDevices()

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));

setTemperature()

Controls bed temperature for left and/or right sides.

async setTemperature(settings: TemperatureSettings): Promise<void>

Parameters

Parameter Type Required Description
settings TemperatureSettings Yes Temperature configuration

TemperatureSettings Interface

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/Off
  • 1 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 });

getStatus()

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);

turnOn()

Convenience method to turn on bed temperature control (sets to neutral).

async turnOn(side: 'left' | 'right' | 'both' = 'both'): Promise<void>

Parameters

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');

turnOff()

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');

API Endpoints

Authentication Endpoints

POST /v1/login

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)

Device Management Endpoints

GET /v1/users/{userId}/devices

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"]
  }
]

Temperature Control Endpoints

PUT /v1/devices/{deviceId}/temperature

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"
}

Status Endpoints

GET /v1/devices/{deviceId}/status

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
  }
}

Data Types

Device

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"]
}

BedSide

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
}

DeviceStatus

interface DeviceStatus {
  deviceId: string;     // Device identifier
  online: boolean;      // Is device online
  left: BedSide;        // Left side status
  right: BedSide;       // Right side status
}

AuthResponse

interface AuthResponse {
  session: {
    token: string;      // JWT session token
    userId: string;     // Authenticated user ID
    expiresAt: string;  // Token expiration time
  };
}

Response Formats

Success Response

All successful API calls return JSON with the requested data:

{
  "data": { ... },
  "success": true
}

Error Response

Failed API calls return JSON with error details:

{
  "error": {
    "code": "AUTHENTICATION_FAILED",
    "message": "Invalid email or password",
    "details": { ... }
  },
  "success": false
}

Error Handling

Common Error Codes

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

Error Handling Pattern

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);
  }
}

Rate Limiting

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

Best Practices

  1. Cache session tokens - Don't authenticate on every request
  2. Implement exponential backoff - Wait progressively longer between retries
  3. Batch operations - Group multiple temperature changes together
  4. 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);
  }
}

Code Examples

Basic Usage

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 });

Advanced Temperature Control

// 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 });
}

Error Recovery

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)
      );
    }
  }
}

Status Monitoring

// 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);

TypeScript Integration

// 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);
}