API endpoints
Pluma's HTTP API lives under /api/*. All routes go through the middleware chain withTrustedProxies → withLogging → withNoStoreOnUserContent → withAuth → withHostAllowlist → withCORS → mux. Browser sessions auth via WebAuthn passkeys; scripts auth via bearer token (Authorization: Bearer <token> or ?api_token=).
For deep request/response detail, the source is at server/handlers.go and the sibling *_handlers.go files. This page summarises the surface.
Chat & models
Method
Path
Notes
GET
/api/health
Upstream reachability + active connection summary.
GET
/api/models
Models the active LLM connection advertises through /v1/models.
POST
/api/chat
OpenAI-shaped streaming chat. Streams SSE when stream: true (the default for stateful conversations).
POST /api/chat request body:
{
"model" : "qwen2.5-32b-instruct" ,
"messages" : [{ "role" : "user" , "content" : "Hi" }],
"stream" : true ,
"conversation_id" : "abc123" ,
"user_message_id" : "u1" ,
"assistant_message_id" : "a1" ,
"temperature" : 0.7 ,
"top_p" : 0.95
}
Stateless mode (no conversation_id) returns a single OpenAI-shape JSON response when stream: false. Used by the auto-titler, prompt-derivation, and AI character creator.
Connections (LLM)
Method
Path
Notes
GET
/api/connections
List profiles (API keys redacted).
PUT
/api/connections
Create or update.
DELETE
/api/connections/{id}
Remove.
DELETE
/api/connections/{id}/key
Clear stored API key without removing the profile.
POST
/api/connections/{id}/activate
Mark active for the next /api/chat.
POST
/api/connections/test
Ping an unsaved profile to check reachability.
POST
/api/connections/discover
Probe localhost for running LLM servers.
Conversations
Method
Path
Notes
GET
/api/conversations
List with full message arrays. Decrypted on read.
GET
/api/conversations/{id}
Fetch one.
PUT
/api/conversations/{id}
Save (overwrite).
DELETE
/api/conversations/{id}
Remove.
PATCH
/api/conversations/{id}/draft
Persist the composer draft (encrypted alongside the conversation).
PATCH
/api/conversations/{id}/messages/{mid}
Edit one message in place.
DELETE
/api/conversations/{id}/messages/{mid}
Remove one message.
Characters
Method
Path
Notes
GET
/api/characters
List (includes external cards from card_dirs).
GET
/api/characters/{id}
Single card.
GET
/api/characters/{id}/avatar
Avatar PNG. ?w=<px> resizes server-side.
GET
/api/characters/{id}/avatar/status
Background portrait job state (none|pending|running|done|failed).
PUT
/api/characters/{id}
Update. Re-embeds the card JSON into the PNG so the file stays share-ready.
PUT
/api/characters/{id}/avatar
Replace the avatar; embeds the card JSON.
DELETE
/api/characters/{id}
Remove.
POST
/api/characters/import
Multipart PNG / JSON upload.
POST
/api/characters/import-url
URL import (chub.ai, direct .png/.json links). Uses the SSRF-restricted HTTP client.
GET
/api/characters/search
chub.ai proxy with query / tag / sort params.
POST
/api/characters/restore-pluma
Re-install the built-in Pluma character. Bypasses the builtin_pluma_installed flag.
Personas
Method
Path
Notes
GET
/api/personas
List.
GET
/api/personas/{id}
Single persona.
PUT
/api/personas/{id}
Create or update.
DELETE
/api/personas/{id}
Remove.
GET
/api/personas/{id}/avatar
Avatar (when set; stored as a portable Tavern v2 persona card).
PUT
/api/personas/{id}/avatar
Replace avatar.
HuggingFace model browser
Method
Path
Notes
GET
/api/models/browse?q=&format=
Search (format = gguf or mlx).
GET
/api/models/browse/files?repo=&format=
List candidate files in a repo.
POST
/api/models/download
Start a background download job.
GET
/api/models/downloads
Active + recent jobs with byte progress.
POST
/api/models/downloads/{id}/cancel
Stop a running job.
GET
/api/models/local
What's on disk under <datadir>/models/.
Image generation
Method
Path
Notes
GET
/api/image/connections
SD backend profiles (A1111 / ComfyUI).
PUT
/api/image/connections
Create or update.
DELETE
/api/image/connections/{id}
Remove.
POST
/api/image/connections/{id}/activate
Mark active.
POST
/api/image/connections/test
Reachability check.
POST
/api/image/discover
Probe A1111 (7860) + ComfyUI (8188).
GET
/api/image/connections/{id}/checkpoints
Live model list for the dropdown.
POST
/api/image/generate
Unified entry point. Body picks A1111 vs ComfyUI semantics by the active profile.
GET
/api/image/workflows
<datadir>/workflows/ contents.
GET
/api/image/workflows/{id}
Single workflow JSON.
PUT
/api/image/workflows/{id}
Save.
DELETE
/api/image/workflows/{id}
Remove.
Voice library + TTS
Method
Path
Notes
POST
/api/tts/speak
Synthesize one chunk. Body: { text, voice, model, format, base_url, ref_audio }.
GET
/api/tts/config
Current TTS endpoint + model + voice.
PUT
/api/tts/config
Update TTS endpoint + model + voice.
GET
/api/tts/voices?model=
Voices the upstream advertises (or that pluma found via filesystem scan / curated catalogue).
GET
/api/tts/models
Models the TTS upstream advertises.
GET
/api/voices
List voice-library samples.
POST
/api/voices
Upload an audio file (multipart: audio + name + description).
POST
/api/voices/from-url
Import from YouTube / SoundCloud / Vimeo / direct media URL via yt-dlp + SSRF guard.
GET
/api/voices/{id}
Sample metadata.
DELETE
/api/voices/{id}
Remove.
GET
/api/voices/{id}/audio
Serve the raw audio for preview.
Attachments
Method
Path
Notes
PUT
/api/attachments/{name}
Store an image blob.
GET
/api/attachments/{name}
Fetch.
DELETE
/api/attachments/{name}
Remove.
Auth (WebAuthn passkeys + bearer tokens)
Method
Path
Notes
GET
/api/auth/status
Per-origin paired + bypass state for the calling browser.
POST
/api/auth/register/begin
Start enrollment. First-per-RPID is open (grace window).
POST
/api/auth/register/finish
Complete enrollment.
POST
/api/auth/login/begin
Start sign-in challenge.
POST
/api/auth/login/finish
Complete sign-in; returns session cookie.
POST
/api/auth/logout
Clear session.
GET
/api/auth/credentials
List enrolled passkeys.
DELETE
/api/auth/credentials/{id}
Revoke a passkey.
POST
/api/auth/token
Mint a bearer token (requires session). Used by the pluma auth login CLI.
First-run wizard
Method
Path
Notes
GET
/api/setup/status
{ "completed": bool }.
POST
/api/setup/complete
Mark the wizard dismissed or finished.
Tailscale (embedded tsnet)
Method
Path
Notes
GET
/api/tailscale/status
{ enabled, mode, state, hostname, fqdn, port, auth_url, error }.
POST
/api/tailscale/enable
Live-enable; body { "hostname": "..." } optional.
POST
/api/tailscale/disable
Stop the node + wipe local state under <datadir>/tsnet/.