DEV PORTAL

Developer Portal

Build on Orva Eon — the privacy-first AI Agent Phone platform.

Overview

Orva Eon exposes a FastAPI REST backend. All endpoints return JSON. The three-lane compute model is the core abstraction: every request is routed through Lane A (on-device), Lane B (private cloud), or Lane C (external model).

A — On-Device (Ollama)
B — Private Cloud (Claude)
C — External (GPT-4o)

Base URL

http://localhost:8000

Authentication

Set DEMO_TOKEN in .env to gate all endpoints. Pass the token as a request header:

X-Demo-Token: your-token-here

Leave DEMO_TOKEN empty to run in open mode (development).

Compute Lanes

GET /api/lanes Lane status + capabilities
{
  "lane_a": { "status": "available", "privacy_level": "MAXIMUM", "requires_internet": false },
  "lane_b": { "status": "available", "privacy_level": "HIGH",    "requires_internet": true  },
  "lane_c": { "status": "not_configured", "consent_required": true }
}

Tasks

Rate limited: 30 requests/minute per IP.
POST /api/task Submit a task to an agent

Request

{
  "task":      "Book a table for two Friday evening, Italian restaurant",
  "lane":      "B",          // "A" | "B" | "C"
  "user_id":   "demo-user",
  "thread_id": null          // optional conversation thread
}

Response

{
  "result":          "I found three Italian restaurants...",
  "lane_used":       "B",
  "agent_trace":     ["[Router] Semantic classification → Travel...", "..."],
  "memories_updated": [{ "type": "travel", "content": "Book a table..." }],
  "permission_prompts": [],
  "used_crew":       true,
  "privacy_budget":  { "score": 80, "label": "GOOD", "total_tasks": 5 }
}
POST /api/compare Run same task on all 3 lanes in parallel
// Request
{ "task": "What is the weather today?", "user_id": "demo-user" }

// Response
{
  "task": "What is the weather today?",
  "results": [
    { "lane": "A", "result": "...", "elapsed_ms": 1200, "error": null },
    { "lane": "B", "result": "...", "elapsed_ms": 800 },
    { "lane": "C", "result": "...", "elapsed_ms": 650 }
  ]
}

Memory

GET/api/memory/{uid}List all memories
GET/api/memory/{uid}/search?q=query&n=5Semantic search
DELETE/api/memory/{uid}/{mid}Delete a single memory
All memories are Fernet-encrypted at rest. Semantic search uses a plaintext index for real embeddings; the payload store is opaque without the server secret.

Privacy

GET/api/privacy-budget/{uid}Current privacy score (0–100)
{ "score": 85, "label": "EXCELLENT", "total_tasks": 20, "on_device_tasks": 14, "cloud_tasks": 5, "external_tasks": 1 }
GET/api/privacy-report/{uid}Full privacy report with data destinations
GET/api/audit/{uid}?limit=50Append-only audit log

Voice

POST/api/transcribeLocal Whisper STT (Lane A — never leaves device)
// Multipart form: audio file (webm, wav, mp3) + user_id field
// Returns: { "text": "transcribed text here" }
POST/api/speakOpenAI TTS — returns audio/mpeg
{ "text": "Your agent response here.", "voice": "alloy" }

Push Notifications

GET/api/push/public-keyVAPID public key for subscription setup
POST/api/push/subscribeRegister browser push subscription
{ "user_id": "demo-user", "endpoint": "https://...", "p256dh": "...", "auth": "..." }

API Key Management

Users can store their own API keys (Anthropic, OpenAI, etc.) encrypted server-side. Never stored in plaintext.

POST/api/keysStore encrypted API key
{ "user_id": "demo-user", "key_name": "anthropic", "key_value": "sk-ant-..." }
GET/api/keys/{uid}List key names (values never returned)
DELETE/api/keys/{uid}/{key_name}Delete a key

Enterprise Mode

Requires ENTERPRISE_MODE=true in .env
POST/api/enterprise/team/memberAdd team member
{ "team_id": "acme-corp", "user_id": "alice", "role": "admin" }
GET/api/enterprise/team/{team_id}/privacy-reportAggregate team privacy dashboard
GET/api/enterprise/team/{team_id}/exportFull compliance export (all members)

GDPR

GET/api/export/{uid}Full data export
DELETE/api/delete-account/{uid}Right to erasure — wipes all data

Agent SDK

Register custom agents into the Orva marketplace. Each agent must declare its privacy lane and data policy upfront.

POST/api/agents/registerRegister a custom agent
{
  "id":           "my-recipe-agent",
  "name":         "Recipe & Nutrition Agent",
  "description":  "Finds recipes and computes nutrition info.",
  "icon":         "🍳",
  "category":     "health",
  "privacy_lane": "A",          // A = never leaves device
  "version":      "1.0.0",
  "capabilities": ["recipe_search", "nutrition_calc"],
  "data_policy":  "No personal data stored. All processing on-device.",
  "system_prompt": "You are a recipe expert..."
}

See agents/template_agent.py for the full reference implementation with CrewAI integration.

JSON Schema — TaskRequest

FieldTypeRequiredDescription
taskstringYESThe user's natural language request
lane"A"|"B"|"C"no (default B)Compute lane
user_idstringno (default demo-user)User identifier for memory + audit scoping
thread_idstring|nullnoConversation thread for context continuity