Complete reference for every REST endpoint exposed by the Piumy core. AllDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/chamilonster/Piumy/llms.txt
Use this file to discover all available pages before exploring further.
/api/* paths require the X-API-Key header (or ?key= query param) when PIMYWA_API_KEY is set. The /healthz endpoint has no authentication requirement.
All successful responses are application/json unless noted otherwise. Error responses follow the shape {"error": "<message>"}.
GET /healthz
Simple liveness check. Returns the plain text stringok with a 200 status. Use this for load balancer probes or systemd ExecStartPost checks.
Auth: None
GET /api/status
Returns the current switchboard status snapshot — the same data written tostatus.json on disk. Includes WhatsApp connection state, queue depth, mood, battery, system metrics, and agent connectivity. See the status.json contract for the complete field reference.
Auth: Required
GET /api/chats
Lists recent chats, ordered by last activity. Returns metadata for each chat including JID, display name, current mode, and last message preview. Auth: RequiredMaximum number of chats to return.
GET /api/messages
Returns messages from a specific chat, ordered newest-first. Auth: RequiredThe chat’s JID (e.g.
56999999999@s.whatsapp.net). Required.Maximum number of messages to return.
GET /api/queue
Returns advanced-mode messages that are waiting for an agent to handle. This is the same set that drives thequeue field in the status snapshot.
Auth: Required
Maximum number of queued messages to return.
POST /api/send
Queues an outbound message. The gateway dispatches it with the configured anti-ban delay (PIMYWA_DELAY_DISPATCH_MIN / PIMYWA_DELAY_DISPATCH_MAX). The message is rate-limited by PIMYWA_RATE_LIMIT_PER_MIN and PIMYWA_RATE_LIMIT_PER_DAY. Rejected outright if the kill switch is on (muted: true).
Auth: Required
Destination JID (e.g.
56999999999@s.whatsapp.net).Message text to send.
POST /api/mode
Sets a chat’s routing mode.auto enables the bridge for auto-replies; advanced puts the chat in the agent queue.
Auth: Required
The chat’s JID.
auto or advanced.POST /api/escalate
Convenience wrapper aroundPOST /api/mode that always sets the chat to advanced. Equivalent to {"Chat": "...", "Mode": "advanced"} but more explicit about intent.
Auth: Required
The chat’s JID.
POST /api/handled
Marks a specific message as handled so it no longer appears in the advanced-mode queue. Auth: RequiredThe chat’s JID.
The message ID to mark as handled.
GET /api/battery/log
Returns a window of the discharge/charge trace CSV rows written by the power adapter (adapters/power/timeremain.py). Useful for rendering a time-series battery chart on the dashboard. Returns the most recent rows up to limit, oldest first.
If PIMYWA_BATTERY_LOG_FILE is not configured or the file does not yet exist, this endpoint returns an empty array ([]) rather than an error — a missing trace is a normal degraded state, not a broken deployment.
Auth: Required
Maximum number of trace rows to return (most recent window).
Unix timestamp of the sample.
Raw cell voltage in millivolts, or
null if not available from the hardware.Raw voltage-curve battery percentage (can appear jumpy — prefer
linearized_pct for display).Linearized battery percentage as estimated by the power adapter’s adaptive model.
true if the power adapter inferred charging at this sample.GET /api/events
Opens a Server-Sent Events (SSE) stream. The server emits adata: event on every inbound message nudge. A keep-alive comment (: keep-alive) is sent every 20 seconds so the connection stays alive through proxies and load balancers.
Use this for real-time dashboard updates without polling GET /api/status.
Auth: Required (key may be passed via ?key= for EventSource compatibility)
Response content-type: text/event-stream
When using the browser’s native
EventSource API, the X-API-Key header
cannot be set. Pass the key via ?key= instead. On a trusted LAN this is
acceptable; be aware the key may appear in proxy access logs.GET /api/qr.svg
Returns the current WhatsApp linking QR code as an SVG image. Returns404 when no QR data is available (the gateway is not in QR/linking mode).
Auth: Required
Response content-type: image/svg+xml
{"error": "no QR data"} with status 404 when the gateway is not in linking mode.
GET /api/settings
Returns the current runtime settings, including media download filters, anti-ban delay windows, and rate limits. Also includes the floors and ceilings enforced by the guardrails (delay floors can never be tightened below the shipped defaults; rate limit ceilings can never be loosened past the configured maximums). Auth: RequiredPOST /api/settings
Updates runtime settings. Changes take effect immediately without a restart. The response echoes the effective (post-guardrail-clamp) settings. Guardrails:- Delay windows can only be loosened (slower), never tightened below the shipped defaults.
- Rate limits can only be tightened (lower), never raised past the configured ceilings.
media_max_mbis floored at a sane minimum so the media GC can never be effectively disabled.
GET /api/settings with the effective post-clamp values.
GET /api/killswitch
Returns the current state of the kill switch (mute). When the kill switch is on,send_message (via MCP) and POST /api/send are both rejected, and the status mood becomes muted.
Auth: Required
POST /api/killswitch
Enables or disables the kill switch. The state is mirrored intostatus.json as muted so the display adapter can show the muted face.
Auth: Required
true to mute all outbound sends; false to resume.GET /api/gateway
Returns the current WhatsApp gateway running state and connection information. Auth: RequiredPOST /api/gateway
Starts or stops the WhatsApp gateway connection loop."link"→ callsStart(): launches the connect/QR loop; arms the 3-minute QR exposure cap."disconnect"→ callsStop(): cancels the loop and resets state to idle.
503 if the gateway is not available.
Auth: Required
"link" to start the gateway or "disconnect" to stop it.POST /api/reconnect
Clears the reconnect-paused state and restarts the gateway connection loop. Use this whenreconnect_paused is true in the status snapshot (the anti-ban governor paused reconnection after too many consecutive failures).
Returns 503 if the gateway is not available.
Auth: Required
Body: None
GET /api/backup
Returns session backup status: whether backups are enabled, how many are retained, and the most recent backup’s metadata. Returns503 if PIMYWA_BACKUP_KEY is not set (backups are disabled).
Auth: Required
POST /api/backup
Triggers a manual session backup immediately. Returns the resulting backup file metadata. Returns503 if backups are disabled (no PIMYWA_BACKUP_KEY configured).
Session restore is deliberately not exposed over the REST API. It is a
CLI-only operation (
pimywa restore-session) — replacing the live session
over the LAN is intentionally out of scope for this API.GET /api/mcp-guard
Returns the MCP anti-flood limiter status: the effective configuration plus every currently-tracked MCP client (session ID, throttle/block state). Session IDs are opaque per-connection identifiers — never the auth token. Returns503 if the guard is not available.
Auth: Required
POST /api/mcp-guard
Updates the MCP anti-flood thresholds at runtime. Changes take effect immediately. The response echoes the effective post-clamp values. Guardrails:rate_per_min: floored at 10, ceilinged at 600.emit_rate_per_min: floored at 2, ceilinged at 100.block_threshold: floored at 1, ceilinged at 20.block_cooldown_sec: floored at 30 seconds, ceilinged at 3600 seconds (1 hour).
503 if the guard is not available.
Auth: Required
Maximum general tool calls per minute per MCP session.
Maximum emit tool calls (send_message, escalate) per minute per session.
Consecutive throttled calls that trip the circuit breaker.
How long (in seconds) a tripped session remains blocked.
GET /api/mcp-guard with the effective post-clamp values.
GET /api/router
Returns the current in-memory router configuration: the whitelist,allow_all flag, default_mode, and routes. See router.json reference for the full field documentation.
Auth: Required
POST /api/router/whitelist
Adds or removes a JID from the in-memory whitelist and persists the change torouter.json immediately. The gateway sees the change at once — no restart required.
Returns 503 if the router manager is not available.
Auth: Required
The JID to add or remove (e.g.
56999999999@s.whatsapp.net)."add" or "remove". The add action is idempotent — adding an already-present JID is a no-op.GET /api/router).
POST /api/router/allowall
Enables or disables theallow_all flag. When true, the whitelist check is skipped entirely — any number can send messages through the gateway. The change is persisted to router.json immediately.
Returns 503 if the router manager is not available.
Auth: Required
true to allow all inbound senders; false to re-enable the whitelist.GET /api/router).
GET /api/rules
Returns the current global and by-type rules tiers. A chat with no per-chat rules inherits from the by-type tier (based on whether it is a group or individual chat); if that is also empty, the global default applies. Auth: RequiredPOST /api/rules/type
Sets the by-type rules tier forindividual or group chats. Applies to all chats of that type that have no per-chat rules of their own.
Auth: Required
"individual" or "group".The rules text to set. Pass an empty string to clear.
POST /api/rules/default
Sets the global default rules — the catch-all for chats that have neither per-chat rules nor matching by-type rules. Auth: RequiredThe default rules text. Pass an empty string to clear.
POST /api/chats/boss
Marks or unmarks a chat as the trusted owner (is_boss). The owner chat receives privileged commands. This endpoint is deliberately not reachable from MCP — only the REST API (dashboard/owner) may set the boss flag.
Auth: Required
The chat’s JID.
true to grant owner trust; false to revoke it.POST /api/chats/rules
Sets per-chat behavior rules — instructions for how the AI should respond to this specific chat. Overrides the by-type and default rules tiers for this chat. This endpoint is deliberately not reachable from MCP — an agent must never rewrite the rules it is judged against. Auth: RequiredThe chat’s JID.
The rules text. Pass an empty string to clear per-chat rules (the chat then inherits from the by-type or default tier).
POST /api/chats/description
Sets a chat’s description — a note about the chat (for a 1-1 contact) or the WhatsApp group topic (for a group). The description is visible to the AI via MCP context. Auth: RequiredThe chat’s JID.
The description text. Pass an empty string to clear.
POST /api/chats/confirmation
Sets a chat’s confirmation baseline and default confirmer. Determines whether auto-reply drafts for this chat require owner approval before sending. This endpoint is deliberately not reachable from MCP — an agent must not be able to change its own confirmation baseline. Auth: RequiredThe chat’s JID.
"none" (send drafts automatically) or "required" (hold drafts for owner approval).Optional JID of the default confirmer (the contact who approves drafts). Leave empty to use the system default.
POST /api/drafts/approve
Approves a pending auto-reply draft and moves it into the outbox for sending (with the normal anti-ban pacing). Optionally edits the draft text before approval. This endpoint is deliberately not reachable from MCP — only the owner approves drafts. Auth: RequiredThe draft ID (integer).
Optional edited text. When provided, replaces the original draft text before sending.
404 if the draft is not found or is no longer pending.
POST /api/drafts/discard
Marks a pending auto-reply draft as discarded — it will never be sent. The action is permanent. This endpoint is deliberately not reachable from MCP. Auth: RequiredThe draft ID (integer).
404 if the draft is not found or is no longer pending.