REST API
REST API Developer-facing API for programmatic access to app skills and focus modes. For full request/response schemas, see the OpenAPI docs. Why This Exists...
REST API
Developer-facing API for programmatic access to app skills and focus modes. For full request/response schemas, see the OpenAPI docs.
Why This Exists
Provides programmatic access to OpenMates app skills for automation, integrations, and the CLI package. The REST API cannot decrypt/encrypt chats (zero-knowledge architecture) – use the CLI/SDK package for chat operations. See CLI Package.
How It Works
Base URL and Authentication
https://api.openmates.org/v1
Authorization: Bearer YOUR_API_TOKEN
API keys can be scoped to specific apps/skills. Write operations via API do not require user confirmation (unlike the web app) – security comes from key scopes, rate limiting, and logging. See Action Confirmation.
Unified Endpoint Pattern
All app skill endpoints follow:
POST /v1/apps/{app_id}/skills/{skill_id}
Examples: POST /v1/apps/web/skills/search, POST /v1/apps/videos/skills/get_transcript, POST /v1/apps/images/skills/generate
Auto-Registration
REST routes are auto-registered per discovered app at api startup by register_app_and_skill_routes() in apps_api.py. There is no manual registration step and no hardcoded app/hostname map.
Discovery flow (in-process since OPE-342):
discover_apps()in main.py delegates tobuild_skill_registry()in skill_registry.py.build_skill_registry()filesystem-scansbackend/apps/*/app.yml, applies feature availability filtering, and instantiates aBaseApp(register_http_routes=False)per app. EachBaseAppresolves every skillclass_pathviaimportlib.- The result is published as
app.state.skill_registry(and as a process-global singleton for code paths without FastAPI app context). register_app_and_skill_routes()registersGET /v1/apps/{id},GET /v1/apps/{id}/skills/{skill_id}, andPOST /v1/apps/{id}/skills/{skill_id}for every loaded app.call_app_skill()dispatches viaSkillRegistry.dispatch_skill()— directly in-process, no HTTP to sibling containers.
To add a new app: drop a folder under backend/apps/, restart api. There is no docker-compose.yml edit step. If a skill’s class_path import fails at startup, BaseApp._resolve_skill_classes logs an ERROR and the skill returns 404 — the rest of the app and the api itself stay up.
Request Format
{ "requests": [{ /* skill-specific parameters */ }] }
Up to 5 parallel requests per call. Each spawns a separate Celery task. Rate limits tracked per provider/skill/model via Dragonfly cache counters.
Response Patterns
Quick-executing skills (e.g., web search): returns results directly with previews array.
Long-running skills (e.g., image generation): returns task_id + embed_id. Poll via GET /v1/tasks/{task_id}. Download files via GET /v1/embeds/{embed_id}/file?format=preview|full|original.
Focus Modes
Activated via the chats endpoint (chat IDs in body, never URL, for privacy):
POST /v1/chats
{ "chat_id": "chat_abc123", "focus_mode_on": "web.research" }
Deactivate: { "chat_id": "chat_abc123", "focus_mode_off": true }
Error Handling
Standard HTTP status codes (200, 400, 401, 403, 404, 429, 500, 503). Error response:
{ "error": { "code": "INVALID_PARAMETER", "message": "...", "details": {} } }
Rate Limiting
- Per-user limits based on subscription tier
- Max 5 parallel requests per skill call
- Provider API rate limits tracked per provider/skill/model
- Tasks queued (not rejected) when limits reached, auto-retry on reset
- Headers:
X-RateLimit-Remaining,X-RateLimit-Reset
Privacy
- Chat IDs always in body, never URLs
- Minimal data transfer
- Client-side encryption (REST API cannot decrypt chats)
- No tracking or profiling
Related Docs
- Function Calling – LLM tool integration
- CLI Package – SDK with chat encryption support
- Action Confirmation – confirmation flow differences
- OpenAPI Docs – auto-generated interactive reference