Skip to main content

Toast Notification API

The Toast Notification API is a lightweight HTTP REST server that allows external applications to send toast notifications to your Mixlar device.

Base URL

http://localhost:8889

Network Access Options

  • Local: http://localhost:8889 (this computer only)
  • Local Network: http://[YOUR-LOCAL-IP]:8889 (e.g., http://192.168.1.100:8889)
  • Tailscale: http://[TAILSCALE-IP]:8889 or https://[HOSTNAME]:8889 (with certificates)
To get all available network addresses:
GET /api/toast/network

Authentication

All endpoints (except /health) require API key authentication.

Methods

Header Authentication (Recommended)
X-API-Key: your-api-key-here
Query Parameter Authentication
?api_key=your-api-key-here

Getting Your API Key

The API key is automatically generated on first startup and stored in mixer_config.json under the key toast_api_key. You can also:
  1. Check the console output when the server starts
  2. Use the Toast Settings UI in the desktop app
  3. Call POST /api/toast/regenerate to generate a new key

Rate Limiting

  • Limit: 30 requests per minute per IP address
  • Window: 60 seconds rolling window
  • Response: HTTP 429 Too Many Requests
{
  "error": "Rate limited",
  "message": "Too many requests"
}

Endpoints

Health Check

Check if the API server is running.
GET /api/toast/health
Authentication: Not required Response: 200 OK
{
  "status": "ok",
  "version": "1.0",
  "port": 8889
}

Send Toast Notification

Send a toast notification to the device.
POST /api/toast/send
Authentication: Required Request Body:
{
  "message": "Build Complete!",
  "icon": "checkmark",
  "subtitle": "webpack compiled successfully",
  "duration_ms": 5000,
  "color": "00FF00"
}
Parameters:
FieldTypeRequiredDescriptionConstraints
messagestringYesHeader text displayed in boldMax 30 characters
iconstringNoIcon name (see below)Default: "bell"
subtitlestringNoSubtitle text displayed belowMax 40 characters
duration_msintegerNoDisplay duration in milliseconds1000-30000, default: 3000
colorstringNoBackground color (hex)With or without # prefix
Available Icons:
  • bell - Notification bell
  • checkmark - Success checkmark
  • warning - Warning triangle
  • close - Error/close X
  • settings - Gear icon
  • wifi - WiFi signal
  • audio - Speaker icon
  • play - Play button
  • pause - Pause button
  • volume - Volume icon
  • mute - Mute icon
  • power - Power button
  • refresh - Refresh/reload
  • home - Home icon
  • download - Download arrow
  • upload - Upload arrow
Response: 200 OK
{
  "status": "success",
  "message": "Toast notification sent"
}
Error Responses: 400 Bad Request - Missing required fields
{
  "error": "Bad request",
  "message": "message field is required"
}
401 Unauthorized - Invalid API key
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
429 Too Many Requests - Rate limit exceeded
{
  "error": "Rate limited",
  "message": "Too many requests"
}

List Toast Handlers

Get a list of all available toast handlers and their status.
GET /api/toast/handlers
Authentication: Required Response: 200 OK
{
  "status": "success",
  "handlers": [
    {
      "id": "obs",
      "name": "OBS Studio",
      "enabled": true,
      "loaded": true,
      "color": "#9147FF"
    },
    {
      "id": "spotify",
      "name": "Spotify",
      "enabled": true,
      "loaded": false,
      "color": "#1DB954"
    }
  ]
}

Get Server Status

Get information about the API server and device connection.
GET /api/toast/status
Authentication: Required Response: 200 OK
{
  "status": "success",
  "server_running": true,
  "device_connected": true,
  "port": 8889,
  "rate_limit": {
    "window_seconds": 60,
    "max_requests": 30
  }
}

Get Network Information

Get all available network addresses and Tailscale status.
GET /api/toast/network
Authentication: Required Response: 200 OK
{
  "status": "success",
  "addresses": [
    {
      "ip": "localhost",
      "url": "http://localhost:8889",
      "type": "This Computer"
    },
    {
      "ip": "100.64.1.2",
      "url": "https://mydevice.tailnet.ts.net:8889",
      "type": "Tailscale (HTTPS - Secure Remote Access)",
      "tailscale": true,
      "https": true
    },
    {
      "ip": "192.168.1.100",
      "url": "http://192.168.1.100:8889",
      "type": "Local Network"
    }
  ],
  "tailscale": {
    "installed": true,
    "running": true,
    "ip": "100.64.1.2",
    "hostname": "mydevice.tailnet.ts.net"
  },
  "recommended": "tailscale"
}

Example Usage

cURL

Basic Example:
curl -X POST http://localhost:8889/api/toast/send \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Test Notification",
    "icon": "bell",
    "subtitle": "From API",
    "duration_ms": 5000,
    "color": "FF5733"
  }'
Success Notification:
curl -X POST http://localhost:8889/api/toast/send \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Build Complete!",
    "icon": "checkmark",
    "color": "00FF00"
  }'
Error Notification:
curl -X POST http://localhost:8889/api/toast/send \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Build Failed",
    "icon": "close",
    "subtitle": "Check console for errors",
    "duration_ms": 10000,
    "color": "FF0000"
  }'

Python

import requests

API_KEY = "YOUR_API_KEY_HERE"
BASE_URL = "http://localhost:8889"

def send_toast(message, icon="bell", subtitle=None, duration_ms=3000, color=None):
    """Send a toast notification."""
    url = f"{BASE_URL}/api/toast/send"
    headers = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json"
    }

    payload = {
        "message": message,
        "icon": icon
    }

    if subtitle:
        payload["subtitle"] = subtitle
    if duration_ms:
        payload["duration_ms"] = duration_ms
    if color:
        payload["color"] = color

    response = requests.post(url, json=payload, headers=headers)
    return response.json()

# Examples
send_toast("Server Started", icon="checkmark", color="00FF00")
send_toast("New Email", icon="bell", subtitle="From: john@example.com")
send_toast("Critical Error", icon="warning", color="FF0000", duration_ms=10000)

JavaScript / Node.js

const axios = require('axios');

const API_KEY = 'YOUR_API_KEY_HERE';
const BASE_URL = 'http://localhost:8889';

async function sendToast(message, options = {}) {
  const {
    icon = 'bell',
    subtitle = null,
    duration_ms = 3000,
    color = null
  } = options;

  const payload = { message, icon };
  if (subtitle) payload.subtitle = subtitle;
  if (duration_ms) payload.duration_ms = duration_ms;
  if (color) payload.color = color;

  try {
    const response = await axios.post(`${BASE_URL}/api/toast/send`, payload, {
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      }
    });
    return response.data;
  } catch (error) {
    console.error('Toast error:', error.response?.data || error.message);
    throw error;
  }
}

// Examples
await sendToast('Deployment Complete', { icon: 'checkmark', color: '00FF00' });
await sendToast('Test Failed', {
  icon: 'close',
  subtitle: 'Unit tests: 15 failed',
  color: 'FF0000',
  duration_ms: 8000
});

PowerShell

$apiKey = "YOUR_API_KEY_HERE"
$baseUrl = "http://localhost:8889"

function Send-Toast {
    param(
        [string]$Message,
        [string]$Icon = "bell",
        [string]$Subtitle,
        [int]$DurationMs = 3000,
        [string]$Color
    )

    $headers = @{
        "X-API-Key" = $apiKey
        "Content-Type" = "application/json"
    }

    $body = @{
        message = $Message
        icon = $Icon
    }

    if ($Subtitle) { $body.subtitle = $Subtitle }
    if ($DurationMs) { $body.duration_ms = $DurationMs }
    if ($Color) { $body.color = $Color }

    $json = $body | ConvertTo-Json

    Invoke-RestMethod -Uri "$baseUrl/api/toast/send" `
        -Method Post `
        -Headers $headers `
        -Body $json
}

# Examples
Send-Toast -Message "Backup Complete" -Icon "checkmark" -Color "00FF00"
Send-Toast -Message "Disk Space Low" -Icon "warning" -Subtitle "Only 5GB remaining" -Color "FFA500"

Bash

#!/bin/bash

API_KEY="YOUR_API_KEY_HERE"
BASE_URL="http://localhost:8889"

send_toast() {
    local message="$1"
    local icon="${2:-bell}"
    local subtitle="$3"
    local duration_ms="${4:-3000}"
    local color="$5"

    local json="{\"message\":\"$message\",\"icon\":\"$icon\""

    [ -n "$subtitle" ] && json="$json,\"subtitle\":\"$subtitle\""
    [ -n "$duration_ms" ] && json="$json,\"duration_ms\":$duration_ms"
    [ -n "$color" ] && json="$json,\"color\":\"$color\""

    json="$json}"

    curl -X POST "$BASE_URL/api/toast/send" \
        -H "X-API-Key: $API_KEY" \
        -H "Content-Type: application/json" \
        -d "$json"
}

# Examples
send_toast "Tests Passed" "checkmark" "" 3000 "00FF00"
send_toast "Build Started" "settings" "Running webpack..." 5000 "0080FF"

Use Cases

CI/CD Integration

GitHub Actions:
- name: Notify Build Complete
  run: |
    curl -X POST http://YOUR_SERVER:8889/api/toast/send \
      -H "X-API-Key: ${{ secrets.TOAST_API_KEY }}" \
      -H "Content-Type: application/json" \
      -d '{"message": "Build Complete", "icon": "checkmark", "color": "00FF00"}'
Jenkins Pipeline:
post {
    success {
        sh '''
            curl -X POST http://localhost:8889/api/toast/send \
              -H "X-API-Key: ${TOAST_API_KEY}" \
              -H "Content-Type: application/json" \
              -d '{"message": "Deploy Success", "icon": "checkmark", "color": "00FF00"}'
        '''
    }
    failure {
        sh '''
            curl -X POST http://localhost:8889/api/toast/send \
              -H "X-API-Key: ${TOAST_API_KEY}" \
              -H "Content-Type: application/json" \
              -d '{"message": "Deploy Failed", "icon": "close", "color": "FF0000"}'
        '''
    }
}

Server Monitoring

# Monitor disk space
import psutil

def check_disk_space():
    disk = psutil.disk_usage('/')
    percent_used = disk.percent

    if percent_used > 90:
        send_toast(
            "Disk Space Critical",
            icon="warning",
            subtitle=f"{percent_used}% used",
            color="FF0000",
            duration_ms=10000
        )
    elif percent_used > 75:
        send_toast(
            "Disk Space Low",
            icon="warning",
            subtitle=f"{percent_used}% used",
            color="FFA500"
        )

Task Automation

# Long-running task completion
import time

def process_data():
    # Long task...
    time.sleep(3600)

    send_toast(
        "Data Processing Complete",
        icon="checkmark",
        subtitle="1000 records processed",
        color="00FF00"
    )

HTTPS with Tailscale

For secure remote access, use Tailscale with HTTPS:
  1. Install Tailscale: https://tailscale.com/download
  2. Enable MagicDNS: In Tailscale admin console
  3. Generate Certificates:
    tailscale cert yourhostname.tailnet.ts.net
    
  4. Place Certificates: Copy .crt and .key files to main/certs/ folder
  5. Restart App: API server will automatically detect and use HTTPS
Your API will now be available at:
https://yourhostname.tailnet.ts.net:8889

Troubleshooting

Cannot Connect to API

  1. Check if server is running:
    curl http://localhost:8889/api/toast/health
    
  2. Check firewall: Ensure port 8889 is not blocked
  3. Check device connection: API requires device to be connected

Unauthorized Errors

  1. Verify API key: Check mixer_config.json for toast_api_key
  2. Check header format: Use X-API-Key (case-sensitive)
  3. Regenerate key: Use desktop app settings or restart server

Rate Limit Errors

  1. Wait: Rate limits reset after 60 seconds
  2. Reduce frequency: Send max 30 requests per minute
  3. Batch notifications: Combine multiple events into single notification

Security Considerations

  • API Key Storage: Store API keys securely (environment variables, secrets manager)
  • Local Network: API accessible to anyone on your network by default
  • Tailscale: Recommended for secure remote access
  • HTTPS: Use Tailscale certificates for encrypted communication
  • Firewall: Block port 8889 from internet if not using Tailscale

Documentation Version: 1.0 Last Updated: 2025-12-10 API Port: 8889