Morphee API Reference
Complete API documentation for morphee-server (Rust/axum).
Last Updated: February 28, 2026
Base URL
Development: http://localhost:3000
Production: https://yourdomain.com/v1
The morphee-server is a Rust/axum HTTP server wrapping morphee-core. Base URL is configurable via MORPHEE_HOST/MORPHEE_PORT.
Note: The Python backend (FastAPI, port 8000) was retired in V2.0. Legacy Python API docs are archived at docs/archive/api-python-legacy.md.
Authentication
Status: Implemented (Supabase Auth with GoTrue)
Protected endpoints require JWT authentication in the Authorization header:
Authorization: Bearer <jwt_token>
Get your access token by signing in or signing up through the /v1/auth/signup or /v1/auth/signin endpoints.
Authentication Flow:
- Sign up →
/v1/auth/signup→ Receiveaccess_tokenandrefresh_token - Sign in →
/v1/auth/signin→ Receiveaccess_tokenandrefresh_token - Use access_token in
Authorization: Bearer <token>header for protected endpoints - Refresh token when expired →
/v1/auth/refresh
The AuthIdentity middleware verifies tokens via CompositeAuth (SupabaseAuth + MorpheeAuth, routing by JWT iss claim).
Common Response Formats
Success Response
{
"id": "uuid",
"status": "success",
"data": { ... }
}
Error Response
{
"detail": "Error message",
"status_code": 400,
"error_type": "ValidationError"
}
HTTP Status Codes
200 OK: Successful GET request201 Created: Successful POST request204 No Content: Successful DELETE request400 Bad Request: Invalid request data404 Not Found: Resource not found422 Unprocessable Entity: Validation error500 Internal Server Error: Server error
Health
GET /health
Health check endpoint (no auth required).
Response: 200 OK
{ "status": "ok" }
Auth & Knowledge Signing
POST /v1/auth/verify
Verify a JWT token and return identity.
Request:
{ "token": "eyJ..." }
Response: 200 OK
{ "id": "user-uuid", "provider": "Supabase", "roles": ["user"], "group_id": "group-uuid" }
POST /v1/auth/token
Issue a new JWT token (for child/service accounts).
GET /v1/auth/signers
List trusted signers for the authenticated user's group.
POST /v1/knowledge/sign
Sign compiled knowledge (WASM binary) with Ed25519.
POST /v1/knowledge/verify
Verify a knowledge signature and trust chain.
Chat (SSE Streaming)
POST /v1/chat
Send a message and receive SSE-streamed response. Requires auth.
Request:
{
"content": "What is 2+2?",
"conversation_id": "optional-uuid",
"space_id": "optional-uuid"
}
Response: SSE stream with events:
data: {"event":"conversation_id","data":"conv-uuid"}
data: {"event":"text_delta","data":"The answer"}
data: {"event":"text_delta","data":" is 4."}
data: {"event":"done","data":null}
Event types: conversation_id, text_delta, tool_use, tool_result, approval_request, done, error
POST /v1/chat/component-event
Dispatch a component event (stub — logs and returns acknowledgment). Requires auth.
Request:
{
"source": { "component_id": "c1", "component_type": "form", "conversation_id": "conv-uuid" },
"event_type": "submit",
"payload": { "name": "Alice" },
"tier": "ai_turn"
}
Response: 200 OK
{ "status": "received" }
POST /v1/chat/approve/{id}
Approve a pending tool/action (stub). Requires auth.
Response: 200 OK
{ "status": "approved", "approval_id": "uuid" }
Conversations
GET /v1/conversations
List conversations (group-scoped). Supports pagination via ?limit=50&offset=0.
Response: 200 OK — Array of Conversation objects.
POST /v1/conversations
Create a new conversation.
Request:
{
"title": "Math Help",
"space_id": "optional-uuid"
}
Response: 201 Created — Conversation object.
GET /v1/conversations/{id}
Get a specific conversation.
PATCH /v1/conversations/{id}
Update a conversation (title, archived status).
Request:
{
"title": "Updated Title",
"archived": false
}
DELETE /v1/conversations/{id}
Delete a conversation and all its messages (cascade).
GET /v1/conversations/{id}/messages
List messages for a conversation.
Response: 200 OK — Array of PersistedMessage objects with role, content, tool_calls, tool_results, metadata, pinned, reactions, edited_at.
POST /v1/conversations/{id}/messages/{msg_id}/pin
Pin a message. Requires auth.
Response: 200 OK
{ "status": "pinned" }
DELETE /v1/conversations/{id}/messages/{msg_id}/pin
Unpin a message. Requires auth.
Response: 200 OK
{ "status": "unpinned" }
GET /v1/conversations/{id}/messages/pinned
List pinned messages for a conversation. Requires auth.
Response: 200 OK — Array of PersistedMessage objects where pinned=true.
POST /v1/conversations/{id}/messages/{msg_id}/react
Add a reaction to a message. Requires auth.
Request:
{ "emoji": "👍" }
Response: 200 OK
{ "status": "reaction_added" }
DELETE /v1/conversations/{id}/messages/{msg_id}/react
Remove a reaction from a message. Requires auth.
Request:
{ "emoji": "👍" }
Response: 200 OK
{ "status": "reaction_removed" }
PATCH /v1/conversations/{id}/messages/{msg_id}
Update message content. Sets edited_at timestamp. Requires auth.
Request:
{ "content": "Updated message text" }
Response: 200 OK
{ "status": "updated" }
POST /v1/conversations/{id}/regenerate
Regenerate the last AI response (stub). Requires auth.
Response: 200 OK
{ "status": "not_implemented" }
POST /v1/conversations/sync-local
Sync a local conversation to the server. Creates conversation if needed, inserts user + assistant messages. Requires auth.
Request:
{
"conversation_id": "local-uuid",
"title": "My Conversation",
"user_message": "Hello",
"assistant_message": "Hi there!"
}
Response: 200 OK
{ "status": "synced", "conversation_id": "uuid" }
Memory
POST /v1/memory
Store a memory (embed text + insert into VectorDB).
Request:
{
"content": "User prefers dark mode",
"metadata": { "type": "preference" }
}
Response: 201 Created
{ "id": "mem-uuid", "dimensions": 384 }
GET /v1/memory/search
Search memory by vector similarity.
Query params: ?q=dark+mode&limit=10
Response: 200 OK
{
"results": [
{ "id": "mem-uuid", "content": "User prefers dark mode", "score": 0.95, "metadata": {} }
]
}
DELETE /v1/memory/{id}
Delete a memory from VectorDB.
POST /v1/embed
Embed text and return the vector.
Request:
{ "text": "Hello world" }
Response: 200 OK
{ "embedding": [0.1, 0.2, ...], "dimensions": 384 }
Skills
GET /v1/skills
List skills (group-scoped).
Response: 200 OK — Array of PersistedSkill objects.
POST /v1/skills
Create a skill.
Request:
{
"name": "Unit Converter",
"description": "Converts between units",
"definition": { "steps": [...] },
"space_id": "optional-uuid"
}
Response: 201 Created — PersistedSkill object.
GET /v1/skills/{id}
Get a specific skill.
PUT /v1/skills/{id}
Update a skill (name, description, definition, enabled).
DELETE /v1/skills/{id}
Delete a skill.
Search
GET /v1/search
Unified search across conversations, memory, and skills.
Query params: ?q=dark+mode&types=conversations,memory,skills&limit=20
Response: 200 OK
{
"results": [
{ "id": "uuid", "result_type": "memory", "title": "Preference", "content": "User prefers dark mode", "score": 0.95 }
]
}
WebSocket
GET /v1/ws
WebSocket upgrade endpoint. Auth via query param: ?token=<jwt>.
Protocol: JSON messages for process/signal commands. Server pushes EventBus events.
Pipeline
POST /v1/process
Process a query through the Pipeline. Requires auth.