Skip to content

API Reference

Judah Paul edited this page Sep 13, 2026 · 14 revisions

🌐 API Reference

GPT Home exposes a REST API via FastAPI for the web interface and external integrations. This page documents all available endpoints, their parameters, and responses.

Overview

The FastAPI application is defined in src/backend.py and serves:

  • React frontend (SPA)
  • Settings management
  • Event log streaming
  • Integration management (Spotify, Hue, CalDAV, etc.)
  • System control endpoints
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         FastAPI Backend                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   Static Files  β”‚  β”‚   API Routes    β”‚  β”‚   SSE Streaming         β”‚ β”‚
β”‚  β”‚                 β”‚  β”‚                 β”‚  β”‚                         β”‚ β”‚
β”‚  β”‚ /static/*       β”‚  β”‚ /api/settings   β”‚  β”‚ /logs/stream            β”‚ β”‚
β”‚  β”‚ /favicon.ico    β”‚  β”‚ /logs           β”‚  β”‚                         β”‚ β”‚
β”‚  β”‚ /robot.gif      β”‚  β”‚ /connect-*      β”‚  β”‚ Server-Sent Events      β”‚ β”‚
β”‚  β”‚ /* (React SPA)  β”‚  β”‚ /spotify-*      β”‚  β”‚ Real-time log updates   β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ /hue-*          β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                       β”‚ /calendar-*     β”‚                              β”‚
β”‚                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                              β”‚
β”‚                                                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Base URL

  • Local network: http://gpt-home.local or http://<ip-address>
  • Default port: 80 (handled by uvicorn via supervisor)

Settings Endpoints

POST /api/settings

Read or update application settings.

Read Settings:

// Request
{
  "action": "read"
}

// Response
{
  "model": "gpt-4o-mini",
  "temperature": 0.7,
  "max_tokens": 1024,
  "keyword": "computer",
  "sayHeard": false,
  "custom_instructions": "",
  "dark_mode": true,
  "litellm_api_key": "sk-..."
}

Update Settings:

// Request
{
  "action": "update",
  "data": {
    "model": "claude-3-haiku-20240307",
    "temperature": 0.5,
    "litellm_api_key": "sk-ant-..."
  }
}

// Response - Same as read, with updated values

POST /api/settings/dark-mode

Toggle dark mode for the web interface.

// Request (optional - toggle)
{
  "darkMode": true
}

// Response
{
  "success": true,
  "darkMode": true
}

POST /availableModels

Get list of all models supported by LiteLLM.

// Response
{
  "models": [
    "gpt-4o-mini",
    "gpt-4o",
    "claude-3-haiku-20240307",
    "gemini/gemini-1.5-flash",
    ...
  ]
}

POST /updateModel

Change the active AI model.

// Request
{
  "model_id": "claude-3-haiku-20240307"
}

// Response
{
  "model": "claude-3-haiku-20240307"
}

Event Logs Endpoints

POST /logs

Get complete event logs.

// Response
{
  "log_data": "INFO: Application started...\nSUCCESS: Processed query...\n..."
}

POST /new-logs

Get new log entries since last check.

// Request query parameter
?last_line_number=150

// Response
{
  "last_logs": ["INFO: New log entry 1", "SUCCESS: New log entry 2"],
  "new_last_line_number": 152
}

GET /logs/stream

Server-Sent Events (SSE) stream for real-time log updates.

Event: message
Data: {"content": "INFO: Log entry", "type": "info"}

Event: ping
Data: ""  (heartbeat every 15 seconds)

JavaScript Client:

const eventSource = new EventSource('/logs/stream?last_line_number=0');

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(`[${data.type}] ${data.content}`);
};

eventSource.addEventListener('ping', () => {
  console.log('Heartbeat received');
});

POST /clear-logs

Clear all event logs.

// Response
"Logs cleared"

Memory Management

POST /clearMemory

Clear all conversation history and stored memories. This is irreversible.

// Response (success)
{
  "success": true,
  "message": "Memory cleared successfully"
}

// Response (error)
{
  "success": false,
  "message": "Error description"
}

What gets cleared:

  • checkpoints - Conversation state history
  • checkpoint_blobs - Checkpoint binary data
  • checkpoint_writes - Checkpoint write records
  • store - All semantic and episodic memories

GET /speechCapabilities

Get current TTS/STT capabilities based on API key provider.

// Response
{
  "provider": "openai",      // Detected provider or null
  "tts_available": true,     // LiteLLM TTS support
  "stt_available": true      // LiteLLM STT support
}

Integration Management

POST /connect-service

Connect a third-party service by providing credentials.

Spotify:

// Request
{
  "name": "spotify",
  "fields": {
    "CLIENT ID": "your-client-id",
    "CLIENT SECRET": "your-client-secret"
  }
}

// Response
{
  "success": true
}

OpenWeather:

// Request
{
  "name": "openweather",
  "fields": {
    "API KEY": "your-api-key"
  }
}

// Response
{
  "success": true
}

Philips Hue:

// Request
{
  "name": "philipshue",
  "fields": {
    "BRIDGE IP ADDRESS": "192.168.1.100"
  }
}

// Response
{
  "success": true
}
// Note: Requires pressing bridge button within 30 seconds

CalDAV:

// Request
{
  "name": "caldav",
  "fields": {
    "URL": "https://caldav.server.com/dav/",
    "USERNAME": "user",
    "PASSWORD": "password"
  }
}

// Response
{
  "success": true
}

POST /disconnect-service

Disconnect a third-party service.

// Request
{
  "name": "spotify"  // or "openweather", "philipshue", "caldav"
}

// Response
{
  "success": true
}

POST /get-service-statuses

Check connection status of all services.

// Response
{
  "statuses": {
    "Spotify": true,
    "OpenWeather": true,
    "PhilipsHue": false,
    "CalDAV": true
  }
}

Spotify Endpoints

POST /spotify-control

Control Spotify playback.

// Request - Play/Pause
{
  "text": "pause"
}

// Request - Search and play
{
  "text": "play bohemian rhapsody"
}

// Request - Skip
{
  "text": "next song"
}

// Response
{
  "message": "Paused playback."
}

GET /api/spotify/playback

Get current Spotify playback state.

// Response (playing)
{
  "is_playing": true,
  "track": "Song Name",
  "artist": "Artist Name",
  "album": "Album Name",
  "album_art_url": "https://...",
  "progress_ms": 30000,
  "duration_ms": 180000,
  "progress_pct": 0.16
}

// Response (not playing)
{
  "is_playing": false
}

POST /api/spotify/pair-speaker

Start the device pairing flow that signs the speaker into Spotify Connect.

// Response
{
  "user_code": "ABCDEF",
  "verification_url": "https://spotify.com/pair?code=ABCDEF",
  "interval": 5
}

GET /api/spotify/pair-speaker/poll

Poll the pairing flow. On approval the backend stores the speaker refresh token and provisions spotifyd.

// Response (waiting)
{ "status": "pending" }

// Response (approved)
{ "status": "authorized", "message": "Speaker paired successfully!" }

GET /api/spotify/speaker-status

Report whether the speaker is paired with a Spotify account.

// Response
{ "paired": true }

Note: Spotify, Philips Hue, Calendar, and Weather functionality is accessed through the LangGraph agent via voice commands, not through separate REST endpoints. The agent uses tools defined in src/tools/ to handle these integrations.


Display Endpoints

GPT Home supports HDMI, PiScreen, SPI, and I2C displays with multiple display modes.

GET /api/display/status

Get current display status and capabilities.

// Response
{
  "available": true,
  "displays": [
    {
      "type": "tft_lcd",
      "width": 320,
      "height": 240,
      "interface": "spi"
    }
  ],
  "active": true,
  "current_mode": "smart"
}

POST /api/display/mode

Set the display mode.

// Request
{
  "mode": "smart"  // smart, clock, weather, gallery, waveform, or off
}

// Response
{
  "success": true,
  "mode": "smart"
}

Available Modes:

Mode Description
smart Context-aware display (shows relevant info based on activity)
clock Digital clock display
weather Current weather conditions
gallery Rotating image slideshow
waveform Audio waveform visualization
off Display off (blank screen)

Waveform Behavior:

  • Architecture: Uses WaveformMediator as single source of truth with Observer pattern for display updates.
  • SMART mode: Fusion layout β€” always shows compact clock (upper) + voice-gated waveform bars (lower). Bars animate when speech detected, show as flat 2px lines when silent.
  • WAVEFORM mode: Always shows audio visualization regardless of voice detection.
  • I2C display: Always shows waveform with flat bars when silent (hidden during Spotify playback).
  • Tool animation exclusion: Waveform is skipped when a tool animation is active (weather, timer, Spotify, lights, etc.).
  • Screensaver: Audio activity automatically deactivates the screensaver.

POST /api/display/test

Display a test message on the screen.

// Response
{
  "success": true,
  "message": "Test message displayed"
}

POST /api/gallery/upload

Upload an image to the gallery. Accepts multipart form data.

Limits:

  • Maximum file size: 50MB
  • Supported formats: JPEG, PNG, GIF, BMP, WebP
Content-Type: multipart/form-data
Field: file (image file)
// Success Response
{
  "success": true,
  "name": "image.jpg",
  "path": "/path/to/gallery/image.jpg",
  "size": 102400
}

// Error Responses
// 400 - Invalid file type
{"success": false, "message": "Invalid file type: .txt"}

// 413 - File too large (nginx limit)
// Returns HTTP 413 Request Entity Too Large

DELETE /api/gallery/{filename}

Delete an image from the gallery.

// Response
{
  "success": true,
  "message": "Image deleted"
}

POST /api/display/refresh

Re-detect displays and reinitialize the display manager.

// Response
{
  "success": true,
  "message": "Display manager reinitialized"
}

POST /api/display/power-on

Attempt to power on the display (useful for HDMI standby recovery).

// Response
{
  "success": true,
  "message": "Power-on signal sent"
}

GET /api/display/debug

Get detailed display debug information for troubleshooting.

// Response
{
  "framebuffers": ["/dev/fb0"],
  "drm_connectors": [
    {"name": "HDMI-A-1", "status": "connected"}
  ],
  "dri_devices": ["/dev/dri/card0", "/dev/dri/card1"],
  "hdmi_config": {
    "hdmi_force_hotplug": "1",
    "hdmi_drive": "2"
  }
}

Screensaver Endpoints

The screensaver is a burn-in protection layer that works across all display modes. When active, it pauses the current mode and shows an animated screensaver. User activity (voice commands, interactions) automatically deactivates it and resumes the previous display mode.

GET /api/display/screensaver/status

Get screensaver status and settings.

// Response
{
  "success": true,
  "enabled": true,
  "timeout": 300,
  "style": "starfield",
  "is_active": false,
  "current_mode": "smart",
  "time_until_activation": 245.5,
  "available_styles": ["starfield", "matrix", "bounce", "fade"]
}

POST /api/display/screensaver/settings

Update screensaver settings.

// Request
{
  "enabled": true,
  "timeout": 600,
  "style": "matrix"
}

// Response
{
  "success": true,
  "message": "Screensaver settings updated",
  "settings": {
    "enabled": true,
    "timeout": 600,
    "style": "matrix"
  }
}

Available Styles:

Style Description
starfield Stars flying through space (3D effect)
matrix Matrix-style digital rain
bounce Bouncing logo that changes color on edge hits (DVD style)
fade Smooth color cycling with pulsing rings and centered clock

POST /api/display/screensaver/activate

Manually activate the screensaver.

// Response
{
  "success": true,
  "message": "Screensaver activated",
  "paused_mode": "smart"
}

POST /api/display/screensaver/deactivate

Manually deactivate the screensaver and return to previous mode.

// Response
{
  "success": true,
  "message": "Screensaver deactivated",
  "resumed_mode": "smart"
}

POST /api/display/screensaver/poke

Register activity to reset the screensaver inactivity timer.

// Response
{
  "success": true,
  "message": "Activity registered"
}

Audio Endpoints

GET /api/audio/devices

Get list of available audio output devices.

// Response
{
  "success": true,
  "devices": [
    {
      "id": "hw:0,0",
      "name": "bcm2835 Headphones",
      "type": "alsa"
    },
    {
      "id": "hw:1,0",
      "name": "USB Audio Device",
      "type": "alsa"
    }
  ],
  "current": "hw:0,0"
}

POST /api/audio/device

Set the audio output device.

// Request
{
  "device": "hw:1,0"
}

// Response
{
  "success": true,
  "current": "hw:1,0"
}

GET /api/audio/volume

Get current audio volume level.

// Response
{
  "success": true,
  "volume": 75
}

POST /api/audio/volume

Set audio volume level.

// Request
{
  "volume": 80
}

// Response
{
  "success": true,
  "volume": 80
}

GET /api/audio/mic-gain

Get current microphone capture gain level.

// Response
{
  "gain": 80,
  "card": "2"
}

POST /api/audio/mic-gain

Set microphone capture gain level. On startup, the system auto-sets gain to 30% if it detects the current level is below 50%.

// Request
{
  "gain": 80
}

// Response
{
  "success": true,
  "gain": 80,
  "card": "2"
}

GET /api/audio/vad-threshold

Get current voice activity detection (VAD) threshold.

// Response
{
  "threshold": -50.0
}

POST /api/audio/vad-threshold

Set VAD threshold in dB. Lower values = more sensitive (picks up quieter speech), higher values = less sensitive (rejects background noise). Default is -55 dB.

// Request
{
  "threshold": -50
}

// Response
{
  "success": true,
  "threshold": -50.0
}

System Monitor Endpoints

GET /api/system/stats

Get current system resource usage statistics (CPU, memory, disk, network).

// Response
{
  "cpu": {
    "percent": [12.5, 8.3, 15.2, 10.1],
    "percent_total": 11.5,
    "count": 4,
    "count_logical": 4,
    "freq_current": 1500.0,
    "freq_max": 1800.0,
    "load_avg": [0.52, 0.48, 0.45]
  },
  "memory": {
    "total": 4294967296,
    "available": 2147483648,
    "used": 2147483648,
    "percent": 50.0,
    "swap_total": 1073741824,
    "swap_used": 0,
    "swap_percent": 0.0
  },
  "disk": {
    "total": 32212254720,
    "used": 16106127360,
    "free": 16106127360,
    "percent": 50.0
  },
  "network": {
    "bytes_sent": 1234567890,
    "bytes_recv": 9876543210,
    "packets_sent": 12345,
    "packets_recv": 54321
  },
  "temperatures": {
    "cpu_thermal": 45.2
  },
  "boot_time": 1704067200.0,
  "timestamp": 1704153600.0
}

GET /api/system/processes

Get list of running processes sorted by resource usage.

// Response
{
  "processes": [
    {
      "pid": 1234,
      "name": "python",
      "cpu_percent": 15.2,
      "memory_percent": 8.5,
      "status": "running",
      "username": "root",
      "create_time": 1704067200.0
    }
  ],
  "total": 150
}

GET /api/system/info

Get static system information.

// Response
{
  "system": "Linux",
  "node": "raspberrypi",
  "release": "6.1.0-rpi7-rpi-v8",
  "version": "#1 SMP PREEMPT Debian 1:6.1.63-1+rpt1",
  "machine": "aarch64",
  "processor": "",
  "python_version": "3.11.2",
  "boot_time": 1704067200.0,
  "uptime": 86400.0
}

Terminal WebSocket Endpoint

WS /api/terminal/ws

WebSocket endpoint providing interactive shell access to the system. Uses a PTY (pseudo-terminal) to provide a full terminal experience including support for interactive applications like vim, htop, etc.

Connection:

const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const ws = new WebSocket(`${protocol}//${window.location.host}/api/terminal/ws`);
ws.binaryType = "arraybuffer";

Sending Input:

// Send text/keystrokes to the terminal
ws.send("ls -la\n");

// Send resize event when terminal dimensions change
ws.send(JSON.stringify({
  type: "resize",
  rows: 24,
  cols: 80
}));

Receiving Output:

ws.onmessage = (event) => {
  if (event.data instanceof ArrayBuffer) {
    const text = new TextDecoder().decode(event.data);
    terminal.write(text);
  }
};

Features:

  • Full PTY support with ANSI color codes
  • Terminal resize support
  • Automatic reconnection on disconnect
  • xterm-256color terminal type

Security Note: This endpoint provides shell access to the container. In production environments, ensure appropriate authentication and network security measures are in place.


System Control Endpoints

// Response
{
  "ip": "192.168.1.50"
}

Note: This IP is displayed on connected displays and used in configuration messages to help users access the web interface.

POST /gptRestart

Restart the GPT Home application container. Triggers a graceful shutdown of the app process, and Docker's restart: unless-stopped policy automatically restarts the container.

// Response
{
  "success": true
}

POST /spotifyRestart

Restart the Spotifyd container via Docker.

// Response
{
  "success": true
}

GET /api/system/reboot-needed

Check if a system reboot is needed due to hardware configuration changes. Set automatically when phantom I2S devices are detected, hardware display mode changes, resolution changes, or rotation changes.

// Response
{
  "reboot_needed": true,
  "reason": "Stale audio overlay removed β€” reboot to apply changes"
}

POST /reboot

Reboot the Raspberry Pi host system (requires privileged container).

// Response
{
  "success": true
}

POST /shutdown

Shutdown the Raspberry Pi host system (requires privileged container).

// Response
{
  "success": true
}

Password Protection

POST /hashPassword

Hash a password for storage.

// Request
{
  "password": "mypassword"
}

// Response
{
  "success": true,
  "hashedPassword": "sha256-hash-here"
}

POST /getHashedPassword

Get the stored password hash.

// Response
{
  "success": true,
  "hashedPassword": "sha256-hash-here"
}

POST /setHashedPassword

Set a new password hash directly.

// Request
{
  "hashedPassword": "sha256-hash-here"
}

// Response
{
  "success": true
}

POST /changePassword

Change password with old password verification.

// Request
{
  "oldPassword": "current-password",
  "newPassword": "new-password"
}

// Response (success)
{
  "success": true
}

// Response (error)
HTTP 401: "Incorrect password"

Error Handling

All endpoints return errors in a consistent format:

{
  "error": "Error description",
  "traceback": "Full traceback (in debug mode)"
}

HTTP Status Codes:

  • 200 - Success
  • 400 - Bad Request (invalid input)
  • 401 - Unauthorized (password required)
  • 404 - Not Found
  • 500 - Internal Server Error

CORS and Headers

The FastAPI app is configured for local network access:

app = FastAPI()

# Static files served from React build
app.mount("/static", StaticFiles(directory="frontend/build/static"))

# SSE streaming headers
headers={
    "Cache-Control": "no-cache, no-store, must-revalidate",
    "Connection": "keep-alive",
    "X-Accel-Buffering": "no",  # Disable nginx buffering
}

Action Router Interface

The main entry point for voice commands (internal):

# src/routes.py
async def action_router(
    text: str,
    user_id: str = "default",
    thread_id: Optional[str] = None
) -> str:
    """
    Main entry point for processing user requests.
    
    Routes the text through the LangGraph agent which will:
    1. Search relevant memories for context
    2. Determine the appropriate tool(s) to use
    3. Execute the action
    4. Optionally save new memories
    5. Return the response
    """

This is called internally by app.py after voice recognition, not exposed as an HTTP endpoint.


Next Steps

Clone this wiki locally