API Reference

July 1, 2026 ยท View on GitHub

Overview

Muximux provides a REST API for managing configuration, apps, groups, health, authentication, icons, and themes. All endpoints return JSON.

When authentication is enabled, most endpoints require a valid session cookie or API key (X-Api-Key header). Write operations (POST, PUT, DELETE) require the admin role.


Authentication

EndpointMethodAuth RequiredDescription
/api/auth/loginPOSTNoLogin with username/password
/api/auth/logoutPOSTNoLogout (clears session)
/api/auth/statusGETNoCheck auth status and current user
/api/auth/meGETYesGet current user details
/api/auth/passwordPOSTYesChange password (builtin auth only)
/api/auth/usersGETAdminList all users
/api/auth/usersPOSTAdminCreate a new user
/api/auth/users/{username}PUTAdminUpdate user role/email/display name
/api/auth/users/{username}DELETEAdminDelete a user
/api/auth/methodPUTAdminSwitch authentication method
/api/auth/api-keyGETAdminReport whether an instance API key is configured (never returns the key)
/api/auth/api-keyPOSTAdminGenerate or rotate the instance API key
/api/auth/api-keyDELETEAdminClear the instance API key
/api/auth/setupPOSTNo (but requires X-Setup-Token)Initial setup (onboarding wizard). See Authentication > First-Run Setup for the token.
/api/auth/oidc/loginGETNoRedirect to OIDC provider
/api/auth/oidc/callbackGETNoOIDC callback handler

Login request:

POST /api/auth/login
{
  "username": "admin",
  "password": "secretpassword"
}

Login response:

{
  "success": true,
  "user": {
    "username": "admin",
    "role": "admin",
    "email": "admin@example.com",
    "display_name": "Admin User"
  }
}

Auth status response:

GET /api/auth/status

{
  "authenticated": true,
  "auth_method": "builtin",
  "oidc_enabled": false,
  "setup_required": false,
  "user": {
    "username": "admin",
    "role": "admin",
    "email": "admin@example.com",
    "display_name": "Admin User"
  }
}

The auth_method field returns the active authentication method: none, builtin, forward_auth, or oidc. The user field is only present when the request is authenticated. When auth_method is forward_auth and a logout URL is configured, the response includes a logout_url field for client-side redirect on sign-out.

API key authentication:

Non-browser integrations can authenticate with an API key via the X-Api-Key header, but only on allowlisted paths -- not every /api/* endpoint. Out of the box:

Example, calling Sonarr through Muximux with a configured bypass:

GET /proxy/sonarr/api/v3/series
X-Api-Key: your-api-key-here

State-changing endpoints like /api/config, /api/apps, /api/themes, and /api/auth/users require a session cookie -- the API key will not work against them. See Authentication > API Key Authentication for the full scope and setup instructions.

User Management

List users:

GET /api/auth/users

Returns an array of users (without password hashes):

[
  {"username": "admin", "role": "admin", "email": "admin@example.com", "display_name": "Admin User"},
  {"username": "viewer", "role": "user", "email": "", "display_name": ""}
]

Create user:

POST /api/auth/users
{
  "username": "newuser",
  "password": "minimum8chars",
  "role": "user",
  "email": "user@example.com",
  "display_name": "New User"
}

Validation: username is required, password must be at least 8 characters. Valid roles: admin, power-user, user. If the role is omitted or invalid, it defaults to user.

Update user:

PUT /api/auth/users/newuser
{
  "role": "admin",
  "email": "updated@example.com",
  "display_name": "Updated Name"
}

All fields are optional -- only provided fields are updated.

Delete user:

DELETE /api/auth/users/newuser

Constraints: you cannot delete your own account, and you cannot delete the last admin user.

Auth Method Switching

Switch authentication method:

PUT /api/auth/method
{
  "method": "forward_auth",
  "trusted_proxies": ["192.168.0.0/16"],
  "headers": {
    "user": "Remote-User",
    "email": "Remote-Email",
    "groups": "Remote-Groups",
    "name": "Remote-Name"
  },
  "logout_url": "https://auth.example.com/logout"
}

Valid methods: builtin, forward_auth, none. Switching to builtin requires at least one user to exist. Switching to forward_auth requires trusted_proxies. The optional logout_url configures where the browser redirects on sign-out to clear the auth provider's session. The change takes effect immediately without a restart.


Configuration

EndpointMethodRoleDescription
/api/configGETAnyGet full configuration
/api/configPUTAdminUpdate full configuration
/api/config/exportGETAdminDownload config as YAML (sensitive data stripped)
/api/config/importPOSTAdminParse and validate uploaded YAML, returns preview
/api/config/restorePOSTPre-setup only (requires X-Setup-Token)Replace the live config with an uploaded YAML during first-run onboarding
/api/appearanceGETAny authenticated user, or any caller with X-Api-KeyRead-only snapshot of language + theme + colors for embedded apps

The PUT endpoint accepts the full configuration object. Changes to most settings take effect immediately. Server-level settings (listen address, TLS, gateway) require a restart. Auth method changes can be made live via PUT /api/auth/method.

Export config:

GET /api/config/export

Returns a downloadable YAML file with password hashes, OIDC client secrets, and API keys removed. The filename includes the current date (e.g., muximux-config-2025-01-15.yaml).

Import config (preview):

POST /api/config/import
Content-Type: application/x-yaml

(YAML body, max 1 MB)

Validates the YAML and returns the parsed config as JSON for preview. The frontend can then apply it via PUT /api/config. Validation requires at least one app with a name and URL.

Restore config (first-run only):

POST /api/config/restore
Content-Type: application/x-yaml
X-Setup-Token: <token from server stdout or data/.setup-token>

(YAML body, max 1 MB)

Replaces the live config during the initial onboarding flow. Only accepted while the instance is in the pre-setup state; subsequent calls return 409 Conflict. Missing or invalid X-Setup-Token returns 401. See Authentication > First-Run Setup for how to find the token.

Appearance (read-only):

GET /api/appearance

Returns a JSON snapshot with language, theme (family, variant, id, is_dark), colors (a curated subset of CSS custom-property values), and theme_css_url. Embedded apps call this once on boot to sync their own styling with Muximux. See Apps > Appearance API for the full contract and usage examples.


Apps

EndpointMethodRoleDescription
/api/appsGETAnyList all apps
/api/appsPOSTAdminCreate a new app
/api/app/{name}GETAnyGet app by name
/api/app/{name}PUTAdminUpdate app
/api/app/{name}DELETEAdminDelete app
/api/app-action/{name}POSTPer-app role gateFire the app's configured http_action HTTP request
/api/app-docker/{name}/{start|stop|restart}POSTRole-gatedControl a Docker-tracked container (requires lifecycle_enabled + :rw socket)

Create app request:

POST /api/apps
{
  "name": "Sonarr",
  "url": "http://sonarr:8989",
  "icon": {
    "type": "dashboard",
    "name": "sonarr"
  },
  "group": "Media",
  "enabled": true,
  "open_mode": "iframe"
}

Groups

EndpointMethodRoleDescription
/api/groupsGETAnyList all groups
/api/groupsPOSTAdminCreate a new group
/api/group/{name}GETAnyGet group by name
/api/group/{name}PUTAdminUpdate group
/api/group/{name}DELETEAdminDelete group

Discovery

EndpointMethodRoleDescription
/api/discovery/docker/statusGETAdminDocker daemon reachability + discovery config
/api/discovery/docker/networksGETAdminList Docker networks for URL resolution
/api/discovery/docker/configPUTAdminUpdate discovery config (incl. auto_import mode, lifecycle_enabled)
/api/discovery/docker/testPOSTAdminTest a discovery config without saving
/api/discovery/docker/scanGETAdminScan the daemon, return importable containers
/api/discovery/docker/importPOSTAdminImport selected containers as apps
/api/discovery/docker/trackedGETAdminList apps currently tracked from Docker
/api/discovery/docker/track/{name}DELETEAdminDetach an app from Docker tracking
/api/discovery/docker/relink/probePOSTAdminProbe a container to re-link a detached app
/api/discovery/docker/relink/confirmPOSTAdminConfirm a re-link
/api/discovery/docker-stateGETAnyCurrent container-state map for tracked apps

Auto-import is opt-in via discovery.docker.auto_import (off, add, update, or sync). The discovery configuration is also part of the full configuration object, so it can be set via PUT /api/config as well as PUT /api/discovery/docker/config.


Health

EndpointMethodDescription
/api/healthGETSimple health probe (for load balancers)
/api/apps/healthGETGet health status for all apps
/api/apps/{name}/healthGETGet health status for one app
/api/apps/{name}/health/checkPOSTTrigger immediate health check

The /api/health endpoint always returns 200 OK when the server is running. It is intended for use with load balancers and uptime monitors.

Health status response:

{
  "name": "Sonarr",
  "status": "healthy",
  "response_time_ms": 42,
  "last_check": "2024-01-15T10:30:00Z",
  "uptime_percent": 99.8,
  "check_count": 1440,
  "success_count": 1437
}

Status values:

  • healthy -- Last check received an HTTP 2xx response
  • unhealthy -- Last check failed (error, timeout, or non-2xx response)
  • unknown -- App has not been checked yet

Icons

EndpointMethodRoleDescription
/api/icons/dashboardGETAnyList dashboard icons
/api/icons/dashboard/{name}GETAnyGet dashboard icon metadata
/api/icons/lucideGETAnyList Lucide icons
/api/icons/lucide/{name}GETAnyGet Lucide icon SVG
/api/icons/customGETAnyList custom icons
/api/icons/customPOSTAdminUpload custom icon (multipart, 2MB limit)
/api/icons/custom/fetchPOSTAdminDownload icon from URL and save locally
/api/icons/custom/{name}DELETEAdminDelete custom icon

Upload custom icon:

Send a multipart form request with the icon file:

POST /api/icons/custom
Content-Type: multipart/form-data

file: (binary data)

Accepted formats: PNG, SVG, JPG, WebP, GIF. Maximum file size: 2MB.

Fetch icon from URL:

Download an image from a remote URL and save it as a custom icon:

POST /api/icons/custom/fetch
Content-Type: application/json

{
  "url": "https://example.com/icon.png",
  "name": "my-icon"              // optional, derived from URL if omitted
}

The server downloads the image, validates the content type and size (2MB limit), and stores it locally. Returns {"name": "my-icon", "status": "uploaded"} on success.


Themes

EndpointMethodRoleDescription
/api/themesGETAnyList all themes
/api/themesPOSTAdminSave custom theme
/api/themes/{name}DELETEAdminDelete custom theme

Logs

EndpointMethodAuth RequiredDescription
/api/logs/recentGETAdminGet recent log entries from the in-memory buffer (audit entries, client IPs, and panic stacks make this admin-only)

Query parameters:

ParameterTypeDefaultDescription
limitint200Maximum number of entries to return
levelstringFilter by log level (debug, info, warn, error)
sourcestringFilter by source tag (http, audit, server, auth, health, proxy, websocket, caddy, config, icons, themes, discovery, gateway, system)

Example:

GET /api/logs/recent?limit=50&level=error

Response:

[
  {
    "timestamp": "2026-01-01T12:00:00Z",
    "level": "INFO",
    "message": "HTTP request",
    "source": "http",
    "attrs": {
      "method": "GET",
      "path": "/api/config",
      "status": "200",
      "latency_ms": "12",
      "request_id": "a1b2c3d4e5f6a7b8"
    }
  }
]

Logs are stored in a 1000-entry ring buffer. When the buffer is full, the oldest entries are dropped. Entries are also broadcast in real-time via WebSocket (see below).


System

EndpointMethodAuth RequiredDescription
/api/system/infoGETYesGet system information (admin-only fields like data_dir, environment, and uptime are scrubbed for non-admin callers)
/api/system/updatesGETAdminCheck for available updates

System info response:

{
  "version": "3.0.0",
  "commit": "abc1234",
  "build_date": "2025-01-15T00:00:00Z",
  "go_version": "go1.26.0",
  "os": "linux",
  "arch": "amd64",
  "uptime": "2d 5h 30m",
  "environment": "docker"
}

Update check response:

{
  "current_version": "3.1.1",
  "latest_version": "3.2.0",
  "update_available": true,
  "release_url": "https://github.com/mescon/Muximux/releases/tag/v3.2.0",
  "changelog": "..."
}

Proxy Status

EndpointMethodDescription
/api/proxy/statusGETGet Caddy proxy status

Response:

{
  "enabled": true,
  "running": true,
  "tls": true,
  "domain": "muximux.example.com"
}

Gateway

The declarative server.gateway_sites: model is the current gateway path (the legacy Caddyfile was removed in 3.1.0).

EndpointMethodRoleDescription
/api/gateway/sitesGETAdminList configured gateway sites
/api/gateway/sitesPOSTAdminCreate a gateway site
/api/gateway/sites/{domain}PUTAdminUpdate a gateway site
/api/gateway/sites/{domain}DELETEAdminDelete a gateway site
/api/gateway/validatePOSTAdminValidate a gateway site config without saving

/api/auth/forward is the internal forward-auth verify endpoint used by the gateway to gate access. It is not meant to be called directly from a browser (a direct hit returns 400).


WebSocket

EndpointProtocolDescription
/wsWebSocketReal-time event stream

Connect to /ws to receive real-time updates. Events are sent as JSON messages:

{"type": "config_updated", "payload": {...}}
{"type": "health_changed", "payload": [...]}
{"type": "app_health_changed", "payload": {"app": "Sonarr", "health": {"status": "healthy", ...}}}

Event types:

TypePayloadDescription
config_updatedFull config objectConfiguration was changed (via Settings panel or API)
health_changedArray of health statusesHealth status changed for one or more apps
app_health_changed{"app": "name", "health": {...}}Health status changed for a specific app
docker_state_changed{"app_name": "name", "state": {...}}Container state changed for a Docker-tracked app (status, health, restart count, etc.)
log_entryLogEntry objectA new log entry was recorded (see Logs section above). Admin-only: only broadcast to admin clients

The WebSocket client automatically reconnects if the connection drops, using exponential backoff (up to 30 seconds between retries, max 10 attempts).


Rate Limiting

The following endpoints are rate-limited to 5 attempts per IP address per minute to prevent brute-force attacks. If the limit is exceeded, the endpoint returns HTTP 429 (Too Many Requests).

  • POST /api/auth/login -- Login attempts
  • POST /api/auth/setup -- Initial setup attempts
  • GET /api/auth/oidc/login -- OIDC login redirects (shares the login limiter)

Other API endpoints are not rate-limited.