Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.feral.sh/llms.txt

Use this file to discover all available pages before exploring further.

Base URL

http://localhost:9090/api
All endpoints require the brain to be running (feral start). Responses are JSON.

Dashboard

MethodPathDescription
GET/api/dashboard/statusBrain status, uptime, connected devices
GET/api/dashboard/contextCurrent context window (health, scene, calendar)
GET/api/dashboard/timelineRecent events and conversations
POST/api/dashboard/commandSend a text command to the brain

Example: Send a command

curl -X POST http://localhost:9090/api/dashboard/command \
  -H "Content-Type: application/json" \
  -d '{ "text": "What is my heart rate?" }'
{
  "response": "Your heart rate is 72 bpm, measured 3 seconds ago from your wristband.",
  "sdui": null,
  "sources": ["wristband_a3f2"]
}

Skills

MethodPathDescription
GET/api/skillsList all registered skills
GET/api/skills/:idGet skill manifest and status
POST/api/skills/:id/executeManually trigger a skill
POST/api/skills/installInstall a skill from URL or local path
DELETE/api/skills/:idUninstall a skill

Example: List skills

curl http://localhost:9090/api/skills
{
  "skills": [
    { "id": "weather", "name": "Weather", "version": "1.2.0", "status": "active" },
    { "id": "calendar", "name": "Google Calendar", "version": "2.0.1", "status": "active" },
    { "id": "smart_home", "name": "Smart Home Control", "version": "1.0.0", "status": "active" }
  ]
}

Memory

MethodPathDescription
GET/api/memory/episodesList episodic memories (paginated)
GET/api/memory/searchSemantic search across all memory tiers
POST/api/memory/noteStore a note in the knowledge base
GET/api/memory/knowledgeQuery the knowledge graph
DELETE/api/memory/episodes/:idDelete a specific episode
curl "http://localhost:9090/api/memory/search?q=last+time+I+went+running&limit=5"
{
  "results": [
    {
      "id": "ep_2026_0410_morning",
      "timestamp": "2026-04-10T07:15:00Z",
      "summary": "Morning 5K run in Prospect Park. Avg HR 145 bpm, pace 5:20/km.",
      "relevance": 0.94
    }
  ]
}

Identity

MethodPathDescription
GET/api/identity/userGet current USER.md content
PUT/api/identity/userUpdate USER.md
GET/api/identity/soulGet SOUL.md (system persona)
GET/api/identity/twinQuery the digital twin
POST/api/identity/twin/askAsk the digital twin a question

Example: Ask the digital twin

curl -X POST http://localhost:9090/api/identity/twin/ask \
  -H "Content-Type: application/json" \
  -d '{ "question": "Would I enjoy this job offer?" }'
{
  "answer": "Based on your preference for remote work, interest in systems programming, and past dissatisfaction with large-company bureaucracy, this startup role aligns well. However, the on-call rotation conflicts with your sleep optimization goals.",
  "confidence": 0.82
}

Devices & Hardware

MethodPathDescription
GET/api/devices/connectedList all connected devices with types and metrics
GET/api/devices/pairedList paired devices (claimed by default; include_unclaimed=true optional)
POST/api/devices/pairMint daemon/browser pairing token
GET/api/devices/pair/urlMint one-time pair URL payload
GET/api/devices/pair/qrRender pair payload as QR image
GET/api/devices/pair/checkCheck token state (and PIN requirement)
POST/api/devices/pair/verify_pinVerify pairing PIN
POST/api/devices/pair/completeComplete phone/browser pairing
POST/api/devices/pair/pruneRevoke unclaimed tokens in bulk
POST/api/devices/handoffInitiate a session handoff between devices
DELETE/api/devices/{device_id}Revoke (un-pair) a device
GET/api/nodes/healthAll node health status with heartbeat freshness
GET/api/commands/recentRecent commands with full lifecycle state
GET/api/commands/{command_id}Single command detail including state history
POST/api/proactive/dismissDismiss a proactive alert (learns from it)

Access Mode & Remote Reachability

MethodPathDescription
GET/api/access/statusCurrent pairing mode + Tailscale/Funnel status
POST/api/access/remote-upEnable remote mode and Tailscale Funnel
POST/api/access/remote-downDisable remote mode and return to localhost mode

Approvals (Execution Inbox)

The approval inbox lets a non-chat client (web UI, CLI, mobile, automation) resolve pending tool-execution approvals without having to type an acknowledgement into a chat session. A pending request is created by the orchestrator whenever enforce_safety() blocks a tool call (see Autonomy Levels).
MethodPathDescription
GET/api/approvalsList pending tool-approval requests. Optional query params: session_id (filter), limit (1–500, default 100).
POST/api/approvals/{request_id}/approveApprove a pending request and execute the tool.
POST/api/approvals/{request_id}/rejectReject a pending request without executing.
Both approve and reject accept an optional JSON body:
{ "session_id": "s-abc123" }
When session_id is provided it must match the session that originated the request, or the call returns 409 session_mismatch.

Example: list pending approvals

curl "http://localhost:9090/api/approvals?session_id=s-abc123&limit=50"
{
  "count": 1,
  "approvals": [
    {
      "request_id": "apr_01HXYZ...",
      "session_id": "s-abc123",
      "tool_name": "browser__navigate",
      "args": { "url": "https://example.com" },
      "safety_level": "privileged",
      "created_at": 1746230412.81,
      "status": "pending"
    }
  ]
}

Example: approve

curl -X POST "http://localhost:9090/api/approvals/apr_01HXYZ.../approve" \
  -H "Content-Type: application/json" \
  -d '{ "session_id": "s-abc123" }'
{
  "success": true,
  "status": "approved",
  "request_id": "apr_01HXYZ...",
  "session_id": "s-abc123",
  "tool_name": "browser__navigate",
  "summary": "Navigated to https://example.com",
  "result": { "ok": true }
}

Example: reject

curl -X POST "http://localhost:9090/api/approvals/apr_01HXYZ.../reject" \
  -H "Content-Type: application/json" \
  -d '{ "session_id": "s-abc123" }'
{
  "success": true,
  "status": "rejected",
  "request_id": "apr_01HXYZ...",
  "session_id": "s-abc123",
  "tool_name": "browser__navigate"
}

Status codes

CodeMeaning
200Resolved (approved or rejected).
404Unknown request_id (already resolved, expired, or never existed).
409session_mismatch — supplied session_id does not match the pending request.
503Orchestrator or tool runner not initialised yet.

Channels

MethodPathDescription
GET/api/channelsList all channel statuses
GET/api/channels/:name/statusStatus of a specific channel (telegram, slack, etc.)
POST/api/channels/push/registerRegister a push notification device token
GET/api/channels/push/devicesList registered push devices
DELETE/api/channels/push/devices/:idUnregister a push device
POST/api/channels/push/testSend a test push notification

Error Format

All errors follow a consistent shape:
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Skill 'invalid_id' not found.",
    "details": null
  }
}
HTTP CodeMeaning
400Bad request — invalid parameters
401Unauthorized — missing or invalid token
404Resource not found
409Conflict — device already paired, skill already installed
500Internal brain error