Made Open

Made Open Hub API Reference (Detailed)

Base URL: http://localhost:4101 (development) All authenticated endpoints require Authorization: Bearer <JWT> header. Admin endpoints additionally require role: "admin" or scopes: ["admin"] in the JWT payload.

Audit follow-up (2026-04-12): All documented endpoints below are verified against publisher source in apps/hub/src/api/routes/*.ts and apps/hub/src/api/server.ts. Coverage: 88/88 route modules and ~583 (METHOD, path) pairs — ~100% after the §63–§82 expansion added below covers the life-data tier (observations, entities, intentions sub-children, projects, habits, health, fitness, nutrition, finance, collections, journal, media, knowledge, environment, home, learning, capture, reactions), workflows, ActivityPub public + WebFinger + did.json, WhatsApp webhook, AI routing rules, provider OAuth, Fitbit/Google Fit/Plaid OAuth, IVR flows, email signatures, dashboard widgets, context engine v2, and the unprefixed legacy routes registered directly in server.ts (/contacts, /conversations, /rules, /intentions, /workflows, /audit-log).


Table of Contents

  1. Health and Observability
  2. Core Data
  3. Credential Wallet
  4. Capabilities
  5. Microsoft OAuth
  6. AI and Agents
  7. Federation
  8. Marketplace
  9. Reputation
  10. Resource Coordination
  11. Time Bank
  12. Disputes
  13. Governance
  14. Web3 and Wallets
  15. Calling and Voice
  16. Messaging (SMS)
  17. Twilio Admin
  18. Federated Marketplace
  19. Notifications and Webhooks
  20. Privacy
  21. Search
  22. Location Sync
  23. Sensor Data
  24. Presence and Collaboration
  25. Audit and Compliance
  26. Plugin Registry
  27. Document Intelligence
  28. Scheduler
  29. Rules Advanced
  30. Event Store
  31. SSE Streaming
  32. Agent Streaming
  33. Activity Feed
  34. Organizations
  35. OAuth2 and API Keys
  36. Advanced Search
  37. Recommendations
  38. Data Portability
  39. Preferences
  40. Email Admin
  41. Admin Panel
  42. Billing and Feature Flags
  43. Analytics
  44. Sessions
  45. Lineage and Entity Merge
  46. Tools Processing
  47. Audio Intelligence
  48. Context
  49. Device Commands
  50. Schedules
  51. Knowledge Graph
  52. Wiki
  53. Inventory
  54. Inbox (Deep Comms SP1)
  55. Phone Lines and Voicemail (Deep Comms SP3)
  56. Email Client (Deep Comms SP4)
  57. Email AI (Deep Comms SP4)
  58. Meetings (Deep Comms SP5)
  59. Contact Timeline (Deep Comms SP6)
  60. Push Notifications (Deep Comms SP7)
  61. Dashboard Stats
  62. Webhooks (Inbound)
  63. Legacy Core Routes (server.ts)
  64. Observations
  65. Entity Registry
  66. Context Engine v2
  67. Habits
  68. Health
  69. Fitness
  70. Nutrition
  71. Finance
  72. Projects
  73. Collections
  74. Journal
  75. Media
  76. Knowledge
  77. Environment
  78. Home
  79. Learning
  80. Capture
  81. Reactions
  82. ActivityPub Public + WebFinger
  83. Provider OAuth (Generic + Fitbit + Google Fit + Plaid)
  84. WhatsApp Webhook
  85. IVR Flows
  86. Email Signatures
  87. Dashboard Widgets
  88. AI Routing Rules

1. Health and Observability

GET /health

Basic liveness probe. No auth required.

curl http://localhost:4101/health
{ "status": "ok", "timestamp": "2026-04-07T12:00:00.000Z" }

GET /health/detailed

Detailed health report with service statuses, uptime, memory, and metrics. No auth.

curl http://localhost:4101/health/detailed
{
  "status": "healthy",
  "uptime": 3600,
  "uptimeHuman": "1h 0m 0s",
  "memoryUsageMb": 128.5,
  "nodeVersion": "v20.11.0",
  "environment": "development",
  "version": "1.0.0",
  "services": {
    "nats": "connected",
    "database": "connected",
    "meilisearch": "connected",
    "cache": { "size": 42, "hitRate": 0.85 }
  },
  "metrics": { "totalRequests": 1500, "p95LatencyMs": 45 }
}

GET /api/status

Simplified public status page data. No auth.

curl http://localhost:4101/api/status
{
  "status": "operational",
  "uptime": 3600,
  "uptimeHuman": "1h 0m 0s",
  "services": [
    { "name": "nats", "status": "operational", "description": "NATS JetStream event bus" },
    { "name": "database", "status": "operational", "description": "Supabase PostgreSQL" },
    { "name": "meilisearch", "status": "operational", "description": "Full-text search" },
    { "name": "cache", "status": "operational", "description": "In-memory cache" }
  ],
  "updatedAt": "2026-04-07T12:00:00.000Z"
}

GET /api/version

API version info. No auth.

curl http://localhost:4101/api/version
{
  "version": "2026-01-01",
  "build": "1.0.0",
  "supportedVersions": ["2026-01-01"]
}

GET /metrics

JSON metrics snapshot for monitoring. No auth.

curl http://localhost:4101/metrics

GET /metrics/prometheus

Prometheus text exposition format. No auth.

curl http://localhost:4101/metrics/prometheus

2. Core Data

2026-04-12: Earlier versions of this section pointed only at the prefixed /api/* routes. The hub also exposes a set of unprefixed legacy routes registered directly in apps/hub/src/api/server.ts (/contacts, /conversations, /rules, /intentions, /workflows, /audit-log). They are documented in full in §63 Legacy Core Routes. The richer surfaces — Contact Timeline (§59), Messaging (§16), Rules Advanced (§29), Intentions (/api/intentions, below) — remain the recommended path.

GET /api/contacts/:id/timeline

See §59 Contact Timeline. The canonical contact read path is /api/contacts/:id/timeline, /api/contacts/:id/notes, and /api/contacts/:id/relationship.

GET /api/messaging/conversations

See §16 Messaging. Lists SMS conversations. The unprefixed GET /conversations (§63) returns a generic dataService.query('conversations') dump.

POST /api/messaging/sms

See §16 Messaging — this is the canonical outbound-message path. It creates the conversation and persists the message before sending, per the Design Law.

GET /api/intentions

List intentions for the authenticated user. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/intentions

Response: { "intentions": [{ "id": "int-uuid", "title": "...", "status": "active" }] }

POST /api/intentions

Create an intention. Auth required. Body validated by intentionCreateSchema in apps/hub/src/api/schemas/intention.schemas.ts.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Review quarterly reports"}' \
  http://localhost:4101/api/intentions

Response: { "intention": { ... } } (201).

GET /api/intentions/:id

Get a single intention. Auth required.

PUT /api/intentions/:id

Update an intention. Auth required. Body validated by intentionUpdateSchema.

GET /api/intentions/:id/children

List child intentions (hierarchical). Auth required.

2026-04-12: POST /intentions/:id/complete and POST /intentions/:id/remind are unprefixed legacy routes registered directly in server.ts against the older IntentionsService (note the plural) — see §63 Legacy Core Routes. The new IntentionService (singular) under /api/intentions/* updates state via PUT /api/intentions/:id.

GET /api/events

List calendar events. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/events
{ "events": [{ "id": "evt-uuid", "title": "Team standup", "start_time": "2026-04-07T09:00:00Z" }] }

2026-04-12: A generic POST /api/sensor/events is also registered directly in server.ts (see §63 Legacy Core Routes) and accepts { event_type, data, timestamp }, publishing under sensor.<event_type> and writing an audit-log row. The typed sensors route (apps/hub/src/api/routes/sensors.ts) exposes three specific endpoints — see §23 Sensor Data: POST /api/sensor/location, POST /api/sensor/call-log, POST /api/sensor/activity.


3. Credential Wallet

GET /api/credentials

List user credentials (metadata only, secrets never exposed). Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/credentials
[
  { "credential_type": "twilio", "display_info": "+15551234567", "is_active": true, "created_at": "2026-04-01T10:00:00Z" },
  { "credential_type": "microsoft365", "display_info": "Tenant: abc123", "is_active": true, "created_at": "2026-04-02T10:00:00Z" }
]

POST /api/credentials

Store a new credential. Secrets go to Supabase Vault. Auth required.

Body: { type: string, fields: Record<string, string> }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "twilio",
    "fields": {
      "accountSid": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "authToken": "your_auth_token",
      "phoneNumber": "+15551234567"
    }
  }' \
  http://localhost:4101/api/credentials
{
  "credential_type": "twilio",
  "display_info": "+15551234567",
  "is_active": true,
  "created_at": "2026-04-07T12:00:00Z"
}

DELETE /api/credentials/:type

Remove a credential and its vault secrets. Auth required.

curl -X DELETE -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/credentials/twilio

4. Capabilities

GET /api/capabilities/schema

Public. Returns the full credential schema for rendering setup forms.

curl http://localhost:4101/api/capabilities/schema
{
  "version": "1.0.0",
  "credentialSchema": { ... },
  "integrations": [
    { "id": "twilio", "name": "Twilio", "icon": "phone", "domainCount": 8, "implementedDomainCount": 5 }
  ]
}

GET /api/capabilities

User's active capabilities filtered by their stored credentials. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/capabilities
{
  "version": "1.0.0",
  "credentials": [
    { "type": "twilio", "isActive": true, "displayInfo": "+15551234567", "activatedAt": "2026-04-01T10:00:00Z" }
  ],
  "manifest": { "version": "1.0.0", "domains": [ ... ] }
}

GET /api/capabilities/twilio

Full Twilio manifest with per-domain active flags. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/capabilities/twilio

5. Microsoft OAuth

GET /api/oauth/microsoft/authorize

Redirects browser to Microsoft login. No direct JSON response.

# Open in browser:
open "http://localhost:4101/api/oauth/microsoft/authorize"

GET /api/oauth/microsoft/callback

Receives the authorization code from Microsoft, exchanges for tokens, stores in Vault, redirects to web app. Not called directly.


6. AI and Agents

POST /api/ai/query

Send a natural language query to the AI agent. Auth required.

Body: { text: string, conversationId?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "What meetings do I have today?", "conversationId": "conv-uuid"}' \
  http://localhost:4101/api/ai/query
{
  "answer": "You have 2 meetings today: Team standup at 9 AM and Design review at 2 PM.",
  "sources": ["events"],
  "conversationId": "conv-uuid"
}

GET /api/ai/conversations

List AI conversations. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/ai/conversations

GET /api/ai/conversations/:id

Get a single AI conversation. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/ai/conversations/conv-uuid

POST /api/ai/agent/run

Run the multi-agent orchestrator. Auth required.

Body: { text: string, sessionId?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Draft a reply to Johns email and schedule a follow-up", "sessionId": "session-uuid"}' \
  http://localhost:4101/api/ai/agent/run

POST /api/ai/agent/plan

Create a plan without executing it. Auth required.

Body: { goal: string, sessionId?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal": "Organize all my contacts by company"}' \
  http://localhost:4101/api/ai/agent/plan
{
  "plan": { "steps": [ ... ] },
  "sessionId": "session-uuid"
}

GET /api/ai/agent/sessions/:sid/memory

Retrieve session memory. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/ai/agent/sessions/session-uuid/memory

GET /api/ai/agent/sessions/:sid/tools

Retrieve tool call history for a session. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/ai/agent/sessions/session-uuid/tools

GET /api/ai/tools

List all registered tools. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/ai/tools
{
  "tools": [
    { "name": "search_contacts", "description": "Search contacts by name or email", "parameters": { ... } }
  ]
}

POST /api/ai/tools/:name/execute

Directly execute a named tool. Auth required.

Body: { params: Record<string, unknown>, sessionId?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"params": {"query": "John"}}' \
  http://localhost:4101/api/ai/tools/search_contacts/execute

7. Federation

GET /api/federation/did

Get current user's DID. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/federation/did
{ "did": "did:key:z6MkpTHR8VNs5xhqL3..." }

POST /api/federation/did

Generate a new DID. Auth required. Body: { method: string }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"method": "key"}' \
  http://localhost:4101/api/federation/did

GET /api/federation/credentials

List verifiable credentials. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/federation/credentials

POST /api/federation/follow

Follow a remote ActivityPub actor. Auth required.

Body: { targetActorUrl: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"targetActorUrl": "https://bob.made-open.io/ap/actors/bob"}' \
  http://localhost:4101/api/federation/follow

POST /api/federation/unfollow

Unfollow a remote actor. Auth required. Body: { targetActorUrl }.

GET /api/federation/follows

List following and followers. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/federation/follows
{ "following": ["https://bob.made-open.io/ap/actors/bob"], "followers": [] }

POST /api/federation/notes

Publish a Note to followers. Auth required. Body: { content: string }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "Hello from my Made Open hub!"}' \
  http://localhost:4101/api/federation/notes

GET /api/federation/inbox

Personal inbox. Auth required.

GET /api/federation/outbox

Personal outbox. Auth required.

ActivityPub Endpoints (Public)

MethodPathDescription
GET/.well-known/webfinger?resource=acct:alice@hubWebFinger JRD
GET/.well-known/did.jsondid:web DID Document
GET/ap/actors/:usernameActor JSON
GET/ap/actors/:username/outboxOutbox OrderedCollection
POST/ap/actors/:username/inboxInbound activities (HTTP Sig verified)
GET/ap/actors/:username/followersFollowers collection
GET/ap/actors/:username/followingFollowing collection

8. Marketplace

POST /api/marketplace/listings

Create a listing. Auth required.

Body: { listingType, title, description?, priceAmount?, priceCurrency?, tags?, visibility?, status? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"listingType": "service", "title": "Web Development", "description": "Full-stack development services", "priceAmount": 50, "priceCurrency": "credits", "tags": ["development"], "visibility": "public"}' \
  http://localhost:4101/api/marketplace/listings

GET /api/marketplace/listings

Browse public active listings. No auth required. Query: ?q=&listingType=&tags=.

curl "http://localhost:4101/api/marketplace/listings?q=development&tags=web"

GET /api/marketplace/listings/:id

Get a single listing. No auth required.

PATCH /api/marketplace/listings/:id

Update a listing. Auth required (owner only).

POST /api/marketplace/listings/:id/purchase

Initiate a purchase. Auth required.

GET /api/marketplace/transactions

List transactions. Auth required. Query: ?role=buyer|seller.

GET /api/marketplace/transactions/:id

Get a single transaction. Auth required.

PATCH /api/marketplace/transactions/:id/status

Advance transaction status. Auth required. Body: { status, notes? }.

POST /api/marketplace/data-products

Create a data product. Auth required. Body: { productId, query }.

GET /api/marketplace/data-products

List data products. Auth required.

GET /api/marketplace/data-products/:id/preview

Preview a data product with privacy transforms. Auth required.

GET /api/marketplace/data-products/:id/package

Download a packaged data product. Auth required.

PATCH /api/marketplace/data-products/:id/privacy

Configure privacy policy. Auth required. Body: { privacyPolicy: FieldPrivacyPolicy[] }.


9. Reputation

GET /api/reputation/:userId/scores

All domain scores for a user. No auth required.

curl http://localhost:4101/api/reputation/user-uuid/scores

GET /api/reputation/:userId/scores/:domain

Single domain score. No auth required.

POST /api/reputation/issue

Issue a reputation verifiable credential. Auth required.

Body: { subjectDid, vcType, claims }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subjectDid": "did:key:z6Mk...", "vcType": "marketplace_review", "claims": {"rating": 5, "comment": "Excellent"}}' \
  http://localhost:4101/api/reputation/issue

GET /api/reputation/trust

List trusted users. Auth required.

POST /api/reputation/trust

Add a trust relationship. Auth required. Body: { trustedDid, weight, context? }.

DELETE /api/reputation/trust/:trustedDid

Remove a trust relationship. Auth required.

GET /api/reputation/:userId/contextual/:domain

Contextual score as seen by the authenticated viewer. Auth required.


10. Resource Coordination

POST /api/coordination/declarations

Create a new declaration (offer/need). Auth required.

Body: { declType, category, title, description?, exchangeType?, locationPref?, expiresAt? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"declType": "offer", "category": "skills", "title": "TypeScript tutoring", "exchangeType": "time_swap"}' \
  http://localhost:4101/api/coordination/declarations

GET /api/coordination/declarations

Browse active declarations. No auth required. Query: ?category=&declType=&locationPref=.

GET /api/coordination/declarations/mine

My declarations. Auth required. Query: ?status=.

PATCH /api/coordination/declarations/:id

Update a declaration. Auth required.

DELETE /api/coordination/declarations/:id

Cancel a declaration. Auth required.

GET /api/coordination/matches

Find matches. Auth required.

POST /api/coordination/exchanges

Express interest. Auth required. Body: { offerDeclId, needDeclId }.

GET /api/coordination/exchanges

List my exchanges. Auth required. Query: ?status=.

GET /api/coordination/exchanges/:id

Get a single exchange. Auth required.

PATCH /api/coordination/exchanges/:id/status

Advance exchange status. Auth required. Body: { status, notes? }.

POST /api/coordination/exchanges/:id/message

Send negotiation message. Auth required. Body: { message }.


11. Time Bank

GET /api/timebank/balance

Current time credit balance. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/timebank/balance
{ "balance": 120.5, "ownerId": "user-uuid" }

POST /api/timebank/credit

Credit the account. Auth required. Body: { amount, txType, referenceId?, note? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"amount": 10, "txType": "service_completed", "note": "Web dev session"}' \
  http://localhost:4101/api/timebank/credit

POST /api/timebank/debit

Debit the account. Auth required. Body: { amount, txType, referenceId?, note? }.

POST /api/timebank/transfer

Transfer credits. Auth required. Body: { toOwnerId, amount, referenceId?, note? }.

GET /api/timebank/transactions

List transactions. Auth required. Query: ?limit=.


12. Disputes

POST /api/disputes

Open a dispute. Auth required. Body: { respondentId, subjectType, subjectId, description, evidence? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"respondentId": "other-user-uuid", "subjectType": "listing", "subjectId": "listing-uuid", "description": "Item not as described"}' \
  http://localhost:4101/api/disputes

GET /api/disputes

List disputes. Auth required. Query: ?status=.

GET /api/disputes/:id

Get a dispute. Auth required.

POST /api/disputes/:id/evidence

Add evidence. Auth required. Body: { type, content }.

POST /api/disputes/:id/moderator

Assign moderator. Auth required. Body: { moderatorId? }.

POST /api/disputes/:id/resolve

Resolve a dispute. Auth required. Body: { resolution, outcome }.

POST /api/disputes/:id/escalate

Escalate a dispute. Auth required.

GET /api/disputes/moderator/queue

Moderator queue. Auth required.


13. Governance

POST /api/governance/daos

Create a DAO. Auth required.

Body: { name, description?, slug, daoType, quorumPct?, passThreshold?, votingPeriodH?, isPublic? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Neighborhood Co-op", "slug": "neighborhood-coop", "daoType": "cooperative", "quorumPct": 51}' \
  http://localhost:4101/api/governance/daos

GET /api/governance/daos

List DAOs. No auth required. Query: ?memberId=.

GET /api/governance/daos/:id

Get a DAO. No auth required.

PATCH /api/governance/daos/:id

Update a DAO. Auth required (owner).

POST /api/governance/daos/:id/members

Add a member. Auth required (admin). Body: { userId, role }.

DELETE /api/governance/daos/:id/members/:userId

Remove a member. Auth required (admin).

GET /api/governance/daos/:id/members

List members. Auth required.

POST /api/governance/proposals

Create a proposal. Auth required. Body: { daoId, title, description, proposalType, actionPayload?, votingOpensAt?, votingClosesAt? }.

GET /api/governance/proposals

List proposals. Auth required. Query: ?daoId=&status=.

GET /api/governance/proposals/:id

Get a proposal. Auth required.

POST /api/governance/proposals/:id/activate

Activate a proposal. Auth required.

POST /api/governance/proposals/:id/finalize

Finalize after voting. Auth required.

POST /api/governance/proposals/:id/execute

Execute a passed proposal. Auth required.

POST /api/governance/proposals/:id/votes

Cast a vote. Auth required. Body: { choice: "yes"|"no"|"abstain", weight? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"choice": "yes", "weight": 1}' \
  http://localhost:4101/api/governance/proposals/prop-uuid/votes

GET /api/governance/proposals/:id/votes

List votes. Auth required.

GET /api/governance/proposals/:id/tally

Get vote tally. Auth required.


14. Web3 and Wallets

GET /api/web3/wallets

List connected wallets. Auth required.

POST /api/web3/wallets

Connect a wallet. Auth required. Body: { chain, address, provider, signature?, challenge? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"chain": "ethereum", "address": "0x1234...abcd", "provider": "metamask", "signature": "0xsig...", "challenge": "nonce-123"}' \
  http://localhost:4101/api/web3/wallets

DELETE /api/web3/wallets/:id

Disconnect a wallet. Auth required.

GET /api/web3/bridge

List bridge requests. Auth required.

POST /api/web3/bridge/mint

Mint time credits on-chain. Auth required. Body: { amount, chain, walletAddress }.

POST /api/web3/bridge/burn

Burn on-chain tokens back to credits. Auth required. Body: { amount, chain, walletAddress, txHash }.

GET /api/web3/contracts

List supported contract configs. No auth required.


15. Calling and Voice

POST /api/calling/token

Generate Twilio Voice SDK access token. Auth required.

Body: { identity?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}' \
  http://localhost:4101/api/calling/token
{ "token": "eyJ...", "identity": "user-uuid", "expiresIn": 3600 }

POST /api/calling/place

Place an outbound call. Auth required. Body: { to, from? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to": "+15559876543"}' \
  http://localhost:4101/api/calling/place

GET /api/calling/history

Call history. Auth required. Query: ?limit=.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/calling/history?limit=20

POST /calls/video-token

Generate Twilio Video token. Auth required. Body: { roomName? }.

GET /api/calling/lines

List phone lines. Auth required.

PUT /api/calling/lines/:id

Update phone line settings (label, DND, forwarding). Auth required.

POST /api/calling/transfer

Transfer a call. Auth required. Body: { type: "warm"|"cold", targetNumber, callSid }.

POST /api/calling/park

Park a call. Auth required. Body: { callSid, slot? }.

POST /api/calling/retrieve

Retrieve a parked call. Auth required. Body: { slot }.

GET /api/calling/voicemails

List voicemails. Auth required.

PUT /api/calling/voicemails/:id/listened

Mark voicemail as listened. Auth required.

GET /api/calling/recordings/:id

Get a call recording. Auth required.

GET /api/calling/:id/transcript

Get a call transcript. Auth required.

GET /api/calling/:id/analysis

Get AI call analysis. Auth required.

IVR Flows

MethodPathAuthDescription
POST/api/calling/ivr-flowsYesCreate IVR flow
GET/api/calling/ivr-flowsYesList IVR flows
PUT/api/calling/ivr-flows/:idYesUpdate IVR flow
DELETE/api/calling/ivr-flows/:idYesDelete IVR flow

16. Messaging (SMS)

POST /api/messaging/sms

Send an SMS. Creates or finds the conversation first (Design Law). Auth required.

Body: { to, body, from?, mediaUrl? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to": "+15559876543", "body": "Hey, are you free for lunch?"}' \
  http://localhost:4101/api/messaging/sms
{ "id": "msg-uuid", "conversationId": "conv-uuid", "status": "queued" }

GET /api/messaging/conversations

List SMS conversations. Auth required. Query: ?limit=50&offset=0.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/messaging/conversations
{
  "conversations": [
    { "id": "conv-uuid", "participants": "+15551234567,+15559876543", "last_message_at": "2026-04-07T12:00:00Z" }
  ],
  "total": 1
}

17. Twilio Admin

All routes require active Twilio credentials in Vault. Auth required.

GET /api/twilio/phone-numbers

List owned Twilio phone numbers.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/twilio/phone-numbers
{
  "phoneNumbers": [
    { "sid": "PN...", "phoneNumber": "+15551234567", "friendlyName": "Main Line", "webhooksConfigured": true }
  ]
}

GET /api/twilio/phone-numbers/available

Search available numbers. Query: ?country=US&areaCode=206&voiceEnabled=true&smsEnabled=true.

POST /api/twilio/phone-numbers/buy

Purchase a phone number. Body: { phoneNumber, friendlyName? }.

PUT /api/twilio/phone-numbers/:sid/webhooks

Configure webhooks to point to this hub. Body: { autoConfig?: boolean }.

DELETE /api/twilio/phone-numbers/:sid

Release a phone number.

GET /api/twilio/account

Account info.

GET /api/twilio/account/balance

Account balance.

{ "balance": "25.50", "currency": "USD" }

GET /api/twilio/account/usage

Usage records. Query: ?category=&startDate=&endDate=.


18. Federated Marketplace

GET /ap/marketplace

Public ActivityPub OrderedCollection of listings. No auth.

GET /api/federation/marketplace

Local listings suitable for federation. Auth required.

POST /api/federation/marketplace/announce/:id

Announce a listing to federation. Auth required.

POST /api/federation/hubs/subscribe

Subscribe to a remote hub. Auth required. Body: { hubUrl, hubName? }.

DELETE /api/federation/hubs/:id

Unsubscribe from a hub. Auth required.

GET /api/federation/hubs

List hub subscriptions. Auth required.

POST /api/federation/hubs/:id/sync

Sync listings from a hub. Auth required.

GET /api/federation/marketplace/search

Search across local + federated listings. Auth required. Query: ?q=.


19. Notifications and Webhooks

POST /api/notifications/subscriptions

Register a push subscription. Auth required.

Body: { subscriptionType: "web_push"|"fcm"|"apns", endpoint, authKey?, p256dhKey?, deviceName? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subscriptionType": "web_push", "endpoint": "https://fcm.googleapis.com/fcm/send/...", "deviceName": "Chrome Desktop"}' \
  http://localhost:4101/api/notifications/subscriptions

GET /api/notifications/subscriptions

List subscriptions. Auth required.

DELETE /api/notifications/subscriptions/:id

Remove a subscription. Auth required.

POST /api/notifications/send

Send a push notification. Auth required. Body: { title, body, url?, icon? }.

GET /api/webhooks

List registered outbound webhooks. Auth required.

POST /api/webhooks

Register a webhook. Auth required. Body: { name, url, secret?, eventTypes?, isActive? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Slack notifications", "url": "https://hooks.slack.com/services/...", "eventTypes": ["channel.InboundCall", "messaging.SmsReceived"]}' \
  http://localhost:4101/api/webhooks

PATCH /api/webhooks/:id

Update a webhook. Auth required.

DELETE /api/webhooks/:id

Delete a webhook. Auth required.

GET /api/webhooks/:id/logs

Delivery log for a webhook. Auth required. Query: ?limit=.


20. Privacy

GET /api/privacy/dashboard

Privacy dashboard overview. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/privacy/dashboard

GET /api/privacy/consents

List consents. Auth required.

POST /api/privacy/consents

Grant consent. Auth required. Body: { purpose, expiresInDays? }.

DELETE /api/privacy/consents/:purpose

Revoke consent. Auth required.

GET /api/privacy/retention

List retention policies. Auth required.

POST /api/privacy/retention

Create a retention policy. Auth required. Body: { name, description?, targetTable, retentionDays?, isActive? }.

PATCH /api/privacy/retention/:id

Update a retention policy. Auth required.

DELETE /api/privacy/retention/:id

Delete a retention policy. Auth required.

POST /api/privacy/retention/:id/run

Manually run a retention policy. Auth required.

POST /api/privacy/scan

Scan and log an entity for PII. Auth required. Body: { entityType, entityId, content }.

GET /api/privacy/export

Export all user data (GDPR data portability). Auth required.

DELETE /api/privacy/data

Erase user data (GDPR right to erasure). Auth required. Body: { tables?: string[] }.


GET /api/search

Full-text search across entity types. Auth required.

Query: ?q=<query>&types=persons,messages,events,listings,documents

curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:4101/api/search?q=John&types=persons,messages"
{
  "persons": [{ "id": "p-uuid", "name": "John Doe" }],
  "messages": [{ "id": "m-uuid", "body": "Hi John, ..." }],
  "events": [],
  "listings": [],
  "documents": []
}

GET /api/suggest

Autocomplete. Auth required. Query: ?q=. Returns top 5 per type.

curl -H "Authorization: Bearer $TOKEN" "http://localhost:4101/api/suggest?q=jan"
{
  "persons": [{ "id": "p-uuid", "label": "Jane Smith", "type": "person" }],
  "messages": [],
  "rules": []
}

POST /api/search/semantic

Semantic vector search. Auth required. Body: { query, types?, limit? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "meetings about the budget", "limit": 10}' \
  http://localhost:4101/api/search/semantic

22. Location Sync

POST /api/location/batch

Batch upload location fixes from Android. Auth required.

Body: { locations: [{ lat, lng, accuracy, altitude?, speed?, bearing?, capturedAt }] }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"locations": [{"lat": 47.6062, "lng": -122.3321, "accuracy": 10.0, "capturedAt": 1712476800000}]}' \
  http://localhost:4101/api/location/batch
{ "inserted": 1, "ok": true }

23. Sensor Data

POST /api/sensor/location

Single location update. Auth required. Body: { lat, lon, accuracy?, altitude?, speed?, bearing?, capturedAt? }.

POST /api/sensor/call-log

Sync call log entries from Android. Auth required. Body: { entries: [{ number, type, duration?, date? }] }.

POST /api/sensor/activity

Report activity type. Auth required. Body: { type: "stationary"|"walking"|"driving", timestamp? }.


24. Presence and Collaboration

GET /api/presence/:userId

Get presence for a user. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/presence/user-uuid
{ "userId": "user-uuid", "status": "online", "activity": "editing document", "lastSeenAt": "2026-04-07T12:00:00Z" }

POST /api/presence

Set your presence. Auth required. Body: { status, activity? }.

POST /api/presence/heartbeat

Update last_seen_at. Auth required.

POST /api/presence/bulk

Get presence for multiple users. Auth required. Body: { userIds: string[] }.

POST /api/collaboration/sessions

Create a collaboration session. Auth required. Body: { sessionType, title?, entityId? }.

GET /api/collaboration/sessions/:id

Get a session. Auth required.

POST /api/collaboration/sessions/:id/join

Join a session. Auth required.

POST /api/collaboration/sessions/:id/leave

Leave a session. Auth required.

DELETE /api/collaboration/sessions/:id

End a session (owner only). Auth required.

GET /api/collaboration/sessions/:id/cursors

Get all cursors. Auth required.

PUT /api/collaboration/sessions/:id/cursor

Update cursor position. Auth required. Body: { position, selection?, label? }.


25. Audit and Compliance

GET /api/audit

Query audit log. Auth required. Query: ?start=&end=&action=&type=&limit=50&offset=0.

curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:4101/api/audit?action=write&type=credential&limit=10"

GET /api/audit/summary

Audit summary stats. Auth required. Query: ?days=7.

POST /api/audit/reports

Request a compliance report. Auth required.

Body: { reportType: "gdpr_access"|"gdpr_erasure"|"data_export"|"access_summary"|"consent_history"|"retention_summary", parameters? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"reportType": "gdpr_access"}' \
  http://localhost:4101/api/audit/reports

GET /api/audit/reports

List compliance reports. Auth required.

GET /api/audit/reports/:id

Get a specific report. Auth required.

POST /api/audit/reports/:id/generate

Trigger generation. Auth required.

GET /api/audit/alert-rules

List alert rules. Auth required.

POST /api/audit/alert-rules

Create an alert rule. Auth required. Body: { name, description?, eventType, threshold?, windowMinutes?, isActive? }.

DELETE /api/audit/alert-rules/:id

Delete an alert rule. Auth required.

POST /api/audit/check-alerts

Check which alert rules are triggered. Auth required.


26. Plugin Registry

GET /api/plugins

List all plugins. No auth required. Query: ?type=&search=.

curl "http://localhost:4101/api/plugins?type=connector&search=twilio"

GET /api/plugins/me

Plugins with user-specific install status. Auth required.

GET /api/plugins/:pluginId

Get plugin details. No auth required.

POST /api/plugins/:pluginId/install

Install a plugin. Auth required. Body: { config?: Record<string, unknown> }.

DELETE /api/plugins/:pluginId/install

Uninstall a plugin. Auth required.

POST /api/plugins/:pluginId/enable

Enable a plugin. Auth required.

POST /api/plugins/:pluginId/disable

Disable a plugin. Auth required.

POST /api/plugins/:pluginId/rate

Rate a plugin. Auth required. Body: { rating: number, review?: string }.

GET /api/plugins/:pluginId/ratings

Get plugin ratings. No auth required.

GET /api/plugins/capabilities

Enabled capabilities for the user. Auth required.

GET /api/plugins/capabilities/find

Find plugins that provide a capability. Query: ?capability=.


27. Document Intelligence

POST /api/documents/:id/analyze

Run all analysis jobs on a document. Auth required.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  http://localhost:4101/api/documents/doc-uuid/analyze
{ "jobs": [{ "id": "job-uuid", "type": "entity_extraction", "status": "queued" }] }

POST /api/documents/:id/jobs

Queue a single analysis job. Auth required. Body: { jobType }.

GET /api/documents/:id/jobs

Get job history. Auth required.

GET /api/documents/:id/chunks

Get document chunks. Auth required.

GET /api/documents/:id/entities

Get extracted entities. Auth required.

GET /api/documents/:id/summary

Get intelligence summary. Auth required.

GET /api/documents/entities/search

Search entities across all documents. Auth required. Query: ?entityType=&query=.


28. Scheduler

POST /api/scheduler/retention/run

Manually trigger retention cleanup. Auth required.

POST /api/scheduler/presence/sync

Manually trigger presence sync. Auth required.

POST /api/scheduler/digest/generate

Manually trigger weekly digest generation. Auth required.

GET /api/scheduler/status

List scheduled job timers and next run times. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/scheduler/status
{
  "timers": [
    { "name": "retention_cleanup", "interval": "24h", "nextRunAt": "2026-04-08T02:00:00Z" }
  ]
}

29. Rules Advanced

GET /api/rule-templates

List rule templates. No auth required. Query: ?category=.

curl http://localhost:4101/api/rule-templates?category=communication

GET /api/rule-templates/:id

Get a template. No auth required.

POST /api/rules/from-template/:templateId

Create a rule from a template. Auth required. Body: { name?, description? }.

GET /api/rules/:id/executions

Execution history for a rule. Auth required. Query: ?limit=.

GET /api/rules/:id/stats

Rule statistics. Auth required.

GET /api/rules/analytics/top

Top performing rules. Auth required. Query: ?limit=.


30. Event Store

GET /api/event-store/streams/:streamId

Load events from a stream. No auth required. Query: ?fromVersion=.

curl "http://localhost:4101/api/event-store/streams/order-123?fromVersion=5"

POST /api/event-store/streams/:streamId/events

Append events (optimistic concurrency). No auth required.

Body: { events: StoredEvent[], expectedVersion: number }

curl -X POST -H "Content-Type: application/json" \
  -d '{"events": [{"eventType": "order.ItemAdded", "data": {"itemId": "abc"}}], "expectedVersion": 3}' \
  http://localhost:4101/api/event-store/streams/order-123/events
{ "streamId": "order-123", "newVersion": 4 }

Returns 409 on concurrency conflict.

GET /api/event-store/types/:eventType

Load events by type. Query: ?limit=100.

GET /api/event-store/streams/:streamId/snapshot

Load latest snapshot.

POST /api/event-store/streams/:streamId/snapshot

Save a snapshot. Body: { state, version }.


31. SSE Streaming

GET /api/stream

Server-Sent Events endpoint. Auth via header or ?token=. Query: ?topics=topic1,topic2&token=.

curl -N -H "Authorization: Bearer $TOKEN" \
  "http://localhost:4101/api/stream?topics=inbox,notifications"

Events arrive as:

event: connected
data: {"clientId":"abc","userId":"user-uuid","topics":["inbox","notifications"]}

event: inbox.new_item
data: {"itemId":"item-uuid","channel":"sms"}

GET /api/stream/stats

SSE service statistics. No auth required.


32. Agent Streaming

POST /api/agent/stream

Stream a query via the StreamingAgentService. Auth required.

Body: { text: string, sessionId?: string }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "Summarize my day"}' \
  http://localhost:4101/api/agent/stream
{ "sessionId": "session-uuid", "content": "Here is your day summary...", "tokenCount": 150 }

33. Activity Feed

GET /api/activity

Get recent activity. Auth required. Query: ?limit=.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/activity?limit=20
{
  "items": [
    { "id": "act-uuid", "type": "message_received", "data": { ... }, "isRead": false, "createdAt": "2026-04-07T12:00:00Z" }
  ]
}

POST /api/activity/read

Mark items as read. Auth required. Body: { ids: string[] }.

GET /api/activity/unread-count

Get unread count. Auth required.

{ "count": 5 }

34. Organizations

POST /api/orgs

Create an organization. Auth required. Body: { name, slug }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corp", "slug": "acme-corp"}' \
  http://localhost:4101/api/orgs

GET /api/orgs

List user's organizations. Auth required.

GET /api/orgs/:orgId

Get an org (member only). Auth required.

PUT /api/orgs/:orgId

Update an org (admin/owner). Auth required. Body: { name?, avatarUrl? }.

DELETE /api/orgs/:orgId

Delete an org (owner only). Auth required.

GET /api/orgs/:orgId/members

List members. Auth required.

DELETE /api/orgs/:orgId/members/:targetUserId

Remove a member (admin/owner). Auth required.

PUT /api/orgs/:orgId/members/:targetUserId

Update member role (admin/owner). Auth required. Body: { role: "owner"|"admin"|"member"|"viewer" }.

POST /api/orgs/:orgId/invites

Create invite (admin/owner). Auth required. Body: { email, role }.

GET /api/orgs/:orgId/invites

List invites (admin/owner). Auth required.

DELETE /api/orgs/:orgId/invites/:inviteId

Revoke invite (admin/owner). Auth required.

POST /api/invites/:token/accept

Accept an invite. Auth required.

GET /api/orgs/:orgId/usage

Get usage stats. Auth required.

GET /api/orgs/:orgId/billing

Get billing events (admin/owner). Auth required. Query: ?limit=50.

POST /api/orgs/:orgId/billing/plan

Change plan (owner). Auth required. Body: { plan: "free"|"pro"|"team"|"enterprise" }.


35. OAuth2 and API Keys

GET /oauth/authorize

HTML authorization page for end-users. Query: ?client_id=&redirect_uri=&scope=&state=.

POST /oauth/authorize

User approves/denies. Form body with client_id, redirect_uri, scope, state, approved.

POST /oauth/token

Token endpoint. Body: { grant_type: "authorization_code"|"refresh_token", code?, client_id?, client_secret?, refresh_token? }.

curl -X POST -H "Content-Type: application/json" \
  -d '{"grant_type": "authorization_code", "code": "abc123", "client_id": "app-client-id", "client_secret": "app-secret"}' \
  http://localhost:4101/oauth/token
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJ..."
}

POST /oauth/revoke

Revoke a token. Body: { token }.

GET /oauth/apps

List registered OAuth apps. Auth required.

POST /oauth/apps

Register a new OAuth app. Auth required. Body: { name, description?, redirectUris, scopes, logoUrl?, websiteUrl? }.

DELETE /oauth/apps/:appId

Delete an OAuth app. Auth required.

GET /oauth/apps/:appId/tokens

List active tokens for an app. Auth required.

GET /api/developer/keys

List API keys. Auth required.

POST /api/developer/keys

Create an API key. Auth required. Body: { name, scopes?, expiresAt? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "CI/CD Pipeline", "scopes": ["contacts:read", "messages:read"]}' \
  http://localhost:4101/api/developer/keys
{
  "id": "key-uuid",
  "name": "CI/CD Pipeline",
  "scopes": ["contacts:read", "messages:read"],
  "rawKey": "mo_live_abc123..."
}

DELETE /api/developer/keys/:id

Revoke an API key. Auth required.


POST /api/search/hybrid

Hybrid keyword + semantic search. Auth required. Body: { text, types?, limit? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"text": "budget meeting notes from last week"}' \
  http://localhost:4101/api/search/hybrid

POST /api/search/similar

Find similar entities by embedding vector. Auth required. Body: { embedding: number[], options? }.

GET /api/search/similar/:type/:id

Find entities similar to a given entity. Auth required. Query: ?limit=&minSimilarity=.

GET /api/search/saved

List saved searches. Auth required.

POST /api/search/saved

Create a saved search. Auth required. Body: { name, query: { text, ... } }.

DELETE /api/search/saved/:id

Delete a saved search. Auth required.

PUT /api/search/saved/:id/alert

Toggle alert on a saved search. Auth required. Body: { enabled: boolean }.


37. Recommendations

GET /api/recommendations

Get recommendations. Auth required. Query: ?type=contact|rule_template|capability|content.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/recommendations?type=capability

POST /api/recommendations/generate

Generate fresh recommendations. Auth required.

DELETE /api/recommendations/:id

Dismiss a recommendation. Auth required.


38. Data Portability

GET /api/export

List export jobs. Auth required.

POST /api/export

Create an export job. Auth required. Body: { format: "json"|"csv"|"vcard"|"ical"|"mbox"|"zip", entityTypes?, filters? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"format": "json", "entityTypes": ["persons", "messages"]}' \
  http://localhost:4101/api/export

GET /api/export/:jobId

Get export job status. Auth required.

GET /api/export/:jobId/download

Download export file. Auth required.

GET /api/import

List import jobs. Auth required.

POST /api/import

Submit an import. Auth required. Body: { format: "json"|"csv"|"vcard"|"ical", fileName, content (base64) }.

GET /api/import/:jobId

Get import job status. Auth required.


39. Preferences

GET /api/preferences

Get user preferences. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/preferences

PUT /api/preferences

Update preferences. Auth required. Body: preference fields to update.

POST /api/preferences/reset

Reset to defaults. Auth required.


40. Email Admin

Admin-only unless noted.

GET /api/admin/email/queue

Email queue stats. Admin required.

POST /api/admin/email/process

Process queued emails. Admin required. Body: { limit?: number }.

GET /api/admin/email/history

Email history. Admin required. Query: ?to=user@example.com&limit=50.

POST /api/email/unsubscribe

User unsubscribes from email notifications. Auth required.


41. Admin Panel

All endpoints require admin role.

POST /api/errors

Public error capture (rate-limited 10/min per IP). No auth required.

Body: { message, stack?, context?, severity?: "low"|"medium"|"high"|"critical" }

GET /api/admin/errors/stats

Error statistics. Admin required.

GET /api/admin/errors

List errors. Admin required. Query: ?severity=&resolved=&limit=.

GET /api/admin/errors/:id

Get a specific error. Admin required.

POST /api/admin/errors/:id/resolve

Resolve an error. Admin required.

GET /api/admin/users

List users (stub). Admin required.

GET /api/admin/orgs

List all orgs. Admin required.

GET /api/admin/stats

Aggregate platform stats. Admin required.

{
  "totalUsers": 0,
  "totalOrgs": 3,
  "totalMessages": 150,
  "totalRules": 12,
  "errorStats": { ... },
  "queueStats": { ... }
}

GET /api/admin/infrastructure

Infrastructure health. Admin required. Returns NATS, Meilisearch, cache, memory, and metrics.

GET /api/admin/clients

Connected clients/devices. Admin required.


42. Billing and Feature Flags

GET /api/billing/plans

List billing plans. No auth required.

GET /api/billing/subscription

Current subscription. Auth required. Header: x-org-id.

POST /api/billing/checkout

Create Stripe checkout session. Auth required. Header: x-org-id. Body: { priceId, successUrl, cancelUrl }.

POST /api/billing/portal

Create Stripe portal session. Auth required. Header: x-org-id. Body: { returnUrl? }.

POST /api/billing/cancel

Cancel subscription. Auth required. Header: x-org-id.

POST /webhooks/stripe

Stripe webhook. No auth (signature verified). Header: stripe-signature.

GET /api/billing/payments

List payments. Auth required. Query: ?limit=&starting_after=&created_gte=&created_lte=&status=.

GET /api/billing/payments/:id

Get payment detail. Auth required.

GET /api/billing/invoices

List invoices. Auth required.

GET /api/billing/invoices/:id

Get invoice detail. Auth required.

GET /api/billing/balance

Account balance and revenue summary. Auth required.

GET /api/billing/customers

List customers. Auth required.

GET /api/billing/customers/:id

Get customer detail. Auth required.

GET /api/feature-flags

List all flags. Admin required.

POST /api/feature-flags

Upsert a flag. Admin required.

POST /api/feature-flags/:name/toggle

Toggle a flag. Admin required. Body: { enabled: boolean }.

GET /api/feature-flags/check/:name

Check if a flag is enabled. Auth optional. Headers: x-org-id, x-org-plan.

curl "http://localhost:4101/api/feature-flags/check/dark-mode"
{ "name": "dark-mode", "enabled": true }

43. Analytics

POST /api/analytics/track

Track an event (rate-limited 100/min per user). Auth required.

Body: { eventType, properties?, sessionId? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"eventType": "page_view", "properties": {"page": "/dashboard"}}' \
  http://localhost:4101/api/analytics/track

GET /api/analytics/summary

Per-user usage summary. Auth required. Query: ?days=30.

GET /api/admin/analytics/platform

Platform-wide stats. Admin required. Query: ?days=30.

GET /api/admin/analytics/events

Raw event query. Admin required. Query: ?eventType=&startDate=&endDate=&limit=.


44. Sessions

GET /api/sessions

List active sessions. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/sessions

DELETE /api/sessions/:id

Revoke a specific session. Auth required.

DELETE /api/sessions

Revoke all sessions. Auth required.

POST /api/auth/logout

Logout (revoke current session). Auth required.


45. Lineage and Entity Merge

GET /api/lineage/:entityType/:entityId

Get data lineage. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/lineage/persons/person-uuid

GET /api/lineage/:entityType/:entityId/fields/:field

Get field provenance. Auth required.

GET /api/merge/candidates

Get pending merge candidates. Auth required.

POST /api/merge/detect

Detect duplicate entities. Auth required.

POST /api/merge/candidates/:id/merge

Merge two entities. Auth required.

POST /api/merge/candidates/:id/reject

Reject a merge candidate. Auth required.

GET /api/conflict-rules

List conflict resolution rules. Auth required.

POST /api/conflict-rules

Create/update a conflict resolution rule. Auth required.

Body: { field, strategy: "newest"|"oldest"|"highest_confidence"|"source_priority"|"manual", sourcePriority? }


46. Tools Processing

POST /api/tools/jobs

Create a processing job. Auth required.

Body: { operation, inputPaths: string[], params?, priority?, callbackUrl? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"operation": "pdf_to_text", "inputPaths": ["documents/report.pdf"]}' \
  http://localhost:4101/api/tools/jobs

GET /api/tools/jobs

List jobs. Auth required. Query: ?category=&status=.

GET /api/tools/jobs/:id

Get job status and results. Auth required.

POST /api/tools/jobs/:id/cancel

Cancel a pending job. Auth required.

GET /api/tools/capabilities

List available tool capabilities. No auth required.

GET /api/tools/fonts

List fonts. Auth required.

POST /api/tools/fonts

Upload/register a font. Auth required. Body: { name, family, style?, weight?, storagePath, format, metadata? }.

DELETE /api/tools/fonts/:id

Delete a font. Auth required.


47. Audio Intelligence

POST /api/audio/session/start

Start a recording session. Auth required. Body: { source?: "microphone"|"system"|"both", deviceId?, sessionType? }.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"source": "both", "deviceId": "desktop-001"}' \
  http://localhost:4101/api/audio/session/start
{ "sessionId": "session-uuid" }

POST /api/audio/session/:sessionId/end

End a recording session. Auth required. Body: { durationSeconds?, segmentCount?, endedReason? }.

POST /api/audio/transcript

Submit a transcript chunk. Auth required.

Body: { sessionId, segments: [{ text, confidence?, start?, end? }], model?, pass?, context? }

POST /api/audio/command

Submit a detected voice command. Auth required.

Body: { sessionId, commandText, rawTranscript?, confidence? }

POST /api/audio/session/cleanup

Clean up orphaned sessions. Auth required. Body: { deviceId }.

GET /api/audio/sessions

List audio sessions. Auth required. Query: ?limit=20&status=.

GET /api/audio/commands

List voice commands. Auth required. Query: ?limit=20&intent=.

GET /api/audio/intelligence

List extracted intelligence items. Auth required. Query: ?limit=50&type=&sessionId=.

GET /api/audio/brief/:date

Get daily brief for a date (YYYY-MM-DD). Auth required.


48. Context

GET /api/context/current

Get user's current context (location, activity, calendar, etc.). Auth required. Called by the audio sidecar every ~30s.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/context/current
{
  "context": {
    "location": { "label": "Office", "lat": 47.6, "lng": -122.3 },
    "activity": "stationary",
    "calendar": { "currentEvent": "Team standup" }
  }
}

49. Device Commands

POST /api/device/commands

Queue a command for a Windows device. Auth required.

Body: { module, action, params?, deviceId? }

Modules: filesystem, process, clipboard, display, power, network, registry, notifications, input, shell, agent.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"module": "shell", "action": "execute", "params": {"command": "dir C:\\"}, "deviceId": "desktop-001"}' \
  http://localhost:4101/api/device/commands
{ "commandId": "cmd-uuid", "status": "queued" }

GET /api/device/commands/pending

Get pending commands for a device. Auth required. Query: ?deviceId=&limit=10.

POST /api/device/commands/:commandId/result

Report command result. Auth required. Body: { status: "completed"|"failed"|"rejected", output?, error? }.

POST /api/device/commands/:commandId/progress

Report progress. Auth required.

GET /api/device/commands

List commands. Auth required. Query: ?limit=20&status=&module=.


50. Schedules

GET /api/schedules

List schedules. Auth required. Query: ?source_type=&status=active|paused.

GET /api/schedules/:id

Get a schedule. Auth required.

POST /api/schedules

Create a schedule. Auth required.

Body: { name, description?, schedule_type?, cron_expression?, rrule?, trigger_at?, delay_ms?, payload?, timezone? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Daily backup", "schedule_type": "recurring", "cron_expression": "0 2 * * *", "payload": {"action": "backup"}, "timezone": "America/Los_Angeles"}' \
  http://localhost:4101/api/schedules

PATCH /api/schedules/:id

Update a schedule. Auth required.

DELETE /api/schedules/:id

Cancel a schedule. Auth required.

POST /api/schedules/:id/pause

Pause a schedule. Auth required.

POST /api/schedules/:id/resume

Resume a schedule. Auth required.

POST /api/schedules/:id/trigger

Trigger immediately. Auth required.

GET /api/schedules/:id/runs

List run history. Auth required. Query: ?limit=50.


51. Knowledge Graph

POST /api/graph/query

Query the LightRAG knowledge graph. Auth required.

Body: { query: string, mode?: "local"|"global"|"hybrid"|"mix"|"naive" }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "What are the relationships between my contacts?", "mode": "hybrid"}' \
  http://localhost:4101/api/graph/query

POST /api/graph/index

Index a document into the graph. Auth required. Body: { text, entityType?, entityId? }.

POST /api/graph/backfill

Index all existing entities. Auth required.

GET /api/graph/data

Get full graph data for visualization. Auth required.

GET /api/graph/health

LightRAG health check. No auth required.


52. Wiki

GET /api/wiki/pages

List wiki pages. Auth required. Query: ?pageType=&tag=.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/wiki/pages?tag=project

GET /api/wiki/pages/:slug

Get a wiki page. Auth required.

POST /api/wiki/ingest

Ingest an external source. Auth required.

POST /api/wiki/query

Query the wiki. Auth required.

POST /api/wiki/lint

Run wiki health check. Auth required.

POST /api/wiki/rebuild-index

Regenerate the index page. Auth required.


53. Inventory

POST /api/inventory

Create an item. Auth required.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "MacBook Pro 16", "category": "electronics", "condition": "good", "purchasePrice": 2499, "purchaseDate": "2025-01-15"}' \
  http://localhost:4101/api/inventory

GET /api/inventory

List items with filters. Auth required. Query: ?category=&condition=&location=&limit=&offset=.

GET /api/inventory/:id

Get item detail. Auth required.

PUT /api/inventory/:id

Update item. Auth required.

DELETE /api/inventory/:id

Soft delete item. Auth required.

POST /api/inventory/:id/dispose

Set disposition intent (sell, donate, recycle, trash). Auth required.

POST /api/inventory/:id/maintenance

Add a maintenance record. Auth required.

GET /api/inventory/:id/history

Get event ledger. Auth required.

POST /api/inventory/:id/move

Move item to new location/space. Auth required.

GET /api/inventory/spaces

List spaces. Auth required. Query: ?propertyItemId=.

POST /api/inventory/spaces

Create a space. Auth required.

POST /api/inventory/import

Bulk import items. Auth required.


54. Inbox (Deep Comms SP1)

GET /api/inbox

Unified inbox across all communication channels. Auth required. Query filters available.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/inbox
{
  "items": [
    {
      "id": "item-uuid",
      "channel": "sms",
      "contactId": "person-uuid",
      "contactName": "Jane Smith",
      "snippet": "Hey, are you free...",
      "isRead": false,
      "isStarred": false,
      "receivedAt": "2026-04-07T12:00:00Z"
    }
  ]
}

GET /api/inbox/unread-count

Unread counts. Auth required.

{ "total": 5, "sms": 2, "email": 3, "call": 0 }

PUT /api/inbox/read

Mark items as read. Auth required. Body: { itemIds: string[] }.

PUT /api/inbox/starred

Star/unstar items. Auth required. Body: { itemIds: string[], starred: boolean }.

PUT /api/inbox/archive

Archive items. Auth required. Body: { itemIds: string[] }.


55. Phone Lines and Voicemail (Deep Comms SP3)

See Calling and Voice for the full voice routes including lines, voicemails, recordings, transcripts, and IVR flows.


56. Email Client (Deep Comms SP4)

GET /api/email/folders

List email folders with unread counts. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/email/folders

GET /api/email/threads

Threaded list. Auth required. Filterable by folder, read status, starred.

GET /api/email/threads/:threadId/messages

All messages in a thread. Auth required.

PUT /api/email/threads/read

Bulk mark-as-read. Auth required. Body: { threadIds: string[] }.

PUT /api/email/threads/starred

Bulk star/unstar. Auth required. Body: { threadIds: string[], starred: boolean }.

GET /api/email/messages/:id

Single email with full body. Auth required.

POST /api/email/send

Compose and send. Auth required.

Body: { to: string[], cc?, bcc?, subject, body, isHtml? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"to": ["jane@example.com"], "subject": "Project update", "body": "Hi Jane, here is the update..."}' \
  http://localhost:4101/api/email/send

POST /api/email/reply

Reply to an email. Auth required. Body: { messageId, body, replyAll? }.

POST /api/email/forward

Forward an email. Auth required. Body: { messageId, to, body? }.

PUT /api/email/drafts

Save or auto-save a draft. Auth required.

DELETE /api/email/drafts/:id

Delete a draft. Auth required.

POST /api/email/move

Move messages to a folder. Auth required. Body: { messageIds, folderId }.

DELETE /api/email/:id

Move to trash. Auth required.

GET /api/email/messages/:id/attachments

List attachments. Auth required.

Signatures CRUD

MethodPathDescription
GET/api/email/signaturesList signatures
POST/api/email/signaturesCreate signature
PUT/api/email/signatures/:idUpdate signature
DELETE/api/email/signatures/:idDelete signature

57. Email AI (Deep Comms SP4)

POST /api/email/threads/:threadId/summarize

AI thread summarization. Auth required.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  http://localhost:4101/api/email/threads/thread-uuid/summarize
{
  "summary": {
    "keyPoints": ["Budget was approved", "Next review in Q3"],
    "actionItems": ["Schedule follow-up meeting"],
    "sentiment": "positive"
  }
}

POST /api/email/threads/:threadId/suggest-replies

AI reply suggestions (2-3). Auth required.

GET /api/email/threads/:threadId/priority

AI priority score (0-100) with factors. Auth required.

GET /api/email/threads/:threadId/follow-ups

Detect follow-up commitments. Auth required.


58. Meetings (Deep Comms SP5)

POST /api/video/meetings

Create a meeting. Auth required.

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "Design Review", "scheduledAt": "2026-04-08T14:00:00Z", "durationMinutes": 60}' \
  http://localhost:4101/api/video/meetings

GET /api/video/meetings

List meetings. Auth required. Filterable by status, date range.

GET /api/video/meetings/:id

Meeting detail. Auth required.

POST /api/video/meetings/:id/join

Join meeting (generates Twilio Video token). Auth required. Body: { identity? }.

POST /api/video/meetings/:id/end

End meeting for all. Auth required.

POST /api/video/meetings/:id/invite

Send invites. Auth required.

POST /api/video/meetings/:id/recording/start

Start recording. Auth required.

POST /api/video/meetings/:id/recording/stop

Stop recording. Auth required.

GET /api/video/meetings/:id/recording

Get recording. Auth required.

GET /api/video/meetings/:id/analysis

Get AI analysis. Auth required.

GET /api/video/join/:roomName

Public join info for a meeting room. No auth required.

{ "meetingId": "mtg-uuid", "title": "Design Review", "roomName": "room-abc", "status": "active" }

59. Contact Timeline (Deep Comms SP6)

GET /api/contacts/:id/timeline

Unified timeline for a contact. Auth required. Query: ?types=call,sms,email&startDate=&endDate=&limit=&offset=.

curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:4101/api/contacts/person-uuid/timeline?types=call,sms&limit=20"

GET /api/contacts/:id/notes

List notes for a contact. Auth required.

POST /api/contacts/:id/notes

Create a note. Auth required. Body: { body }.

PUT /api/contacts/notes/:noteId

Update a note. Auth required. Body: { body }.

DELETE /api/contacts/notes/:noteId

Delete a note. Auth required.

POST /api/contacts/merge

Merge two contacts. Auth required. Body: { primaryId, mergedId }.

POST /api/contacts/unmerge/:mergeId

Unmerge contacts. Auth required.

GET /api/contacts/merge-suggestions

Get merge suggestions. Auth required.

GET /api/contacts/:id/merge-history

Merge history for a contact. Auth required.

PUT /api/contacts/:id/relationship

Set relationship label. Auth required. Body: { label: "family"|"friend"|"colleague"|"partner"|... }.

GET /api/contacts/:id/relationship

Get relationship label. Auth required.

Dashboard Widgets

MethodPathAuthDescription
GET/api/dashboard/recent-contactsYesRecently interacted contacts. Query: ?limit=5
GET/api/dashboard/missed-commsYesMissed calls, unread SMS
GET/api/dashboard/comm-statsYesCommunication statistics

60. Push Notifications (Deep Comms SP7)

POST /api/push/register

Register an FCM token. Auth required.

Body: { deviceId, fcmToken, platform?, deviceName? }

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"deviceId": "pixel-7-pro", "fcmToken": "fcm-token-abc...", "platform": "android", "deviceName": "Pixel 7 Pro"}' \
  http://localhost:4101/api/push/register

DELETE /api/push/unregister

Deactivate FCM token. Auth required. Body: { deviceId }.

GET /api/push/tokens

List active tokens. Auth required.


61. Dashboard Stats

GET /api/stats

Aggregated dashboard statistics. Auth required.

curl -H "Authorization: Bearer $TOKEN" http://localhost:4101/api/stats
{
  "contacts": 42,
  "messages": 156,
  "activeRules": 3,
  "activeCredentials": ["twilio", "microsoft365"]
}

62. Webhooks (Inbound)

These are public endpoints called by external services. No auth required.

POST /webhooks/:channelType

Generic inbound webhook. Validated by the channel plugin.

curl -X POST -H "Content-Type: application/json" \
  -d '{"From": "+15559876543", "To": "+15551234567", "Body": "Hello"}' \
  http://localhost:4101/webhooks/twilio
{ "ok": true }

POST /webhooks/calling/inbound

Twilio inbound call webhook. Returns TwiML (XML).

POST /webhooks/calling/status

Twilio call status callback.

POST /webhooks/calling/voicemail

Twilio voicemail recording webhook.

POST /webhooks/stripe

Stripe webhook. Header: stripe-signature.


63. Legacy Core Routes (server.ts)

These routes are registered directly in apps/hub/src/api/server.ts (not in any routes/*.ts module). They are older, mostly thin wrappers over DataService and predate the typed /api/* surfaces. All require auth (Authorization: Bearer <JWT>).

GET /contacts

List persons via dataService.query('persons'). Returns { contacts: Person[] }.

POST /contacts/sync-device

Insert a device-sourced contact. Body: { name, ...person fields, tags? }. Returns the inserted person row (201).

POST /api/sensor/events

Generic sensor event firehose. Body: { event_type: string, data?: object, timestamp?: ISO8601 }. Writes an audit_log row tagged with sensor.<event_type>. Returns { ok: true, subject } (202). Used by Windows/Android agents for events not yet covered by the typed routes (§23).

GET /conversations

List conversations via dataService.query('conversations'). Returns { conversations: Conversation[] }.

GET /conversations/:id

Get a single conversation. Returns { conversation } or 404.

GET /conversations/:id/messages

List messages for a conversation via dataService.query('messages', { conversation_id }). Returns the array directly (no envelope).

POST /conversations/:id/messages

Send a message in a conversation. Body: { channelId?, to?, text? | body? }. Resolves missing channelId/to from the conversation + first participant, sends via ChannelService.sendMessage, persists an outbound message row, and writes an audit entry. Returns { ok: true, message } (201).

GET /rules

List rules via dataService.query('rules'). Returns { rules: Rule[] }. Prefer the typed Rules Advanced routes in §29.

POST /rules

Insert a raw rule via dataService.insert('rules', body). Returns the inserted row (201). No schema validation here — see §29 for the validated path.

DELETE /rules/:id

Delete a rule. Returns 204.

GET /intentions

(Legacy IntentionsService, plural). Lists intentions. Optional query ?status=active|completed|cancelled. Returns { intentions }.

POST /intentions

Body: { title: string, description?: string, dueAt?: ISO8601 }. Returns { intention } (201). This is the older intentions surface; the typed life-data tier uses /api/intentions/* (see §2 / §65 cross-link below).

POST /intentions/:id/complete

Mark a legacy intention complete via IntentionsService.completeIntention. Returns { ok: true }.

POST /intentions/:id/remind

Schedule a reminder. Body: { triggerAt: ISO8601 }. Returns { jobId: string }.

GET /workflows

List workflows for the authenticated user (requires WorkflowService). Returns { workflows }.

POST /workflows

Body: { name: string, definition: WorkflowDefinition }. Returns { workflow } (201). WorkflowDefinition shape lives in @made-open/ai.

GET /workflows/:id

Get a single workflow. Returns { workflow } or 404.

POST /workflows/:id/execute

Execute a workflow. Body: { context?: Record<string, unknown> }. Returns { run: WorkflowState }.

GET /workflows/:id/runs

List historical runs for a workflow. Returns { runs }.

POST /workflow-runs/:id/resume

Resume a paused workflow run. Returns { run: WorkflowState }.

GET /audit-log

Dump the entire audit log via dataService.query('audit_log'). Returns the array directly. No pagination at this commit. Prefer the typed Audit routes in §25 for production use.


64. Observations

Source: apps/hub/src/api/routes/observations.ts. All routes require auth. Body/query schemas live in apps/hub/src/api/schemas/observation.schemas.ts.

POST /api/observations

Record an observation. Body validated by observationCreateSchema. Returns { observation } (201).

GET /api/observations

Query observations. Query string validated by observationFilterSchema (filters by domain, type, entityId, time window, etc.). Returns ObservationService.queryObservations result.

GET /api/observations/time-window

Returns observations within a time window. Query validated by observationTimeWindowSchema.

POST /api/observations/links

Link two observations (e.g., causal/temporal). Body validated by observationLinkCreateSchema. Returns { link } (201).

GET /api/observations/:id

Get a single observation. Returns { observation } or 404.

Get all links attached to an observation. Returns { links }.


65. Entity Registry

Source: apps/hub/src/api/routes/entities.ts. All routes require auth. Schemas in entity-registry.schemas.ts.

POST /api/entities

Register a new entity (stable URI in the registry). Body validated by entityRegistryCreateSchema. Returns { entity } (201).

GET /api/entities

List entities. Query validated by entityRegistryFilterSchema. Returns EntityRegistryService.listEntities result.

POST /api/entities/relationships

Create a relationship between two entities. Body validated by entityRelationshipCreateSchema. Returns { relationship } (201).

GET /api/entities/:id

Get a single entity. Returns { entity } or 404.

PUT /api/entities/:id

Update an entity. Body validated by entityRegistryUpdateSchema. Returns { entity }.

GET /api/entities/:id/relationships

List all relationships for an entity. Returns { relationships }.


66. Context Engine v2

Source: apps/hub/src/api/routes/context.ts. Auth required. The legacy GET /api/context/current (Redis-backed) is documented in §48; these are the v2 (Supabase-backed) endpoints. Returns 503 if ContextEngineV2 is not wired.

GET /api/context

Get current context for an entity. Query validated by contextQuerySchema (entityId?, dimensions? comma-separated, minConfidence?). Returns { context }.

GET /api/context/history

Context history for a (entity, dimension) over a date range. Query validated by contextHistoryQuerySchema (entityId, dimension, fromDate, toDate). Returns { history }.

POST /api/context/snapshots/:id

Capture a context snapshot for entity id. Returns { snapshot } (201).


67. Habits

Source: apps/hub/src/api/routes/habits.ts. Auth required. Schemas in habit.schemas.ts.

POST /api/habits

Create a habit. Body: habitCreateSchema. Returns { habit } (201).

GET /api/habits

List habits. Query: habitFilterSchema. Returns HabitService.listHabits result.

GET /api/habits/:id

Get a single habit. Returns { habit } or 404.

PUT /api/habits/:id

Update a habit. Body: habitUpdateSchema. Returns { habit }.

POST /api/habits/:id/log

Log a completion. Body: habitLogCreateSchema. Returns { log } (201).

GET /api/habits/:id/logs

List completion logs. Query: habitLogFilterSchema. Returns HabitService.getHabitLogs result.


68. Health

Source: apps/hub/src/api/routes/health.ts. Auth required. Schemas in health.schemas.ts. Note: this is /api/health/* for the HealthService, distinct from the unprefixed liveness /health (§1).

POST /api/health/metrics

Record a health metric. Body: healthMetricCreateSchema. Returns { metric } (201).

GET /api/health/metrics

Get metric history. Query: healthMetricFilterSchema (defaults to metricType=heart_rate). Returns HealthService.getMetricHistory result.

POST /api/health/symptoms

Record a symptom. Body: symptomCreateSchema. Returns { symptom } (201).

GET /api/health/symptoms

List symptoms. Query: healthMetricFilterSchema. Returns HealthService.getSymptoms result.

POST /api/health/sleep

Record a sleep session. Body: sleepCreateSchema. Returns { sleep } (201).

GET /api/health/sleep

List sleep records. Query: healthMetricFilterSchema. Returns HealthService.getSleepRecords result.


69. Fitness

Source: apps/hub/src/api/routes/fitness.ts. Auth required. Schemas in fitness.schemas.ts.

POST /api/fitness/activities

Record a fitness activity. Body: fitnessActivityCreateSchema. Returns { activity } (201).

GET /api/fitness/activities

List activities. Query: activityFilterSchema. Returns FitnessService.listActivities result.

GET /api/fitness/activities/:id

Get a single activity. Returns { activity } or 404.

GET /api/fitness/stats

Activity stats over a time range. Query: ?fromDate=&toDate= (defaults to last 30 days). Returns { stats }.


70. Nutrition

Source: apps/hub/src/api/routes/nutrition.ts. Auth required. Schemas in nutrition.schemas.ts.

POST /api/nutrition/meals

Log a meal. Body: mealCreateSchema. Returns { meal } (201).

GET /api/nutrition/meals

List meals. Query: mealFilterSchema. Returns NutritionService.listMeals result.

GET /api/nutrition/meals/:id

Get a single meal. Returns { meal } or 404.

POST /api/nutrition/meals/:id/items

Add an item to a meal. Body: mealItemCreateSchema. Returns { item } (201).

GET /api/nutrition/meals/:id/items

List items in a meal. Returns { items }.

POST /api/nutrition/water

Log water intake. Body: waterCreateSchema. Returns { water } (201).

GET /api/nutrition/daily/:date

Daily nutrition summary for :date (YYYY-MM-DD). Returns { summary }.

POST /api/nutrition/preferences

Set a dietary preference. Body: preferenceCreateSchema. Returns { preference } (201).


71. Finance

Source: apps/hub/src/api/routes/finance.ts. Auth required. Schemas in finance.schemas.ts.

POST /api/finance/accounts

Create a financial account. Body: accountCreateSchema. Returns { account } (201).

GET /api/finance/accounts

List accounts. Returns { accounts }.

POST /api/finance/transactions

Record a transaction. Body: transactionCreateSchema. Returns { transaction } (201).

GET /api/finance/transactions

List transactions. Query: transactionFilterSchema. Returns FinanceService.listTransactions result.

POST /api/finance/budgets

Create a budget. Body: budgetCreateSchema. Returns { budget } (201).

GET /api/finance/budgets/:id/status

Budget status (spent, remaining, on-track flag). Returns { status } or 404.

POST /api/finance/subscriptions

Create a subscription tracker. Body: subscriptionCreateSchema. Returns { subscription } (201).

GET /api/finance/subscriptions

List subscriptions. Returns { subscriptions }.


72. Projects

Source: apps/hub/src/api/routes/projects.ts. Auth required. Schemas in project.schemas.ts.

POST /api/projects

Create a project. Body: projectCreateSchema. Returns { project } (201).

GET /api/projects

List projects. Query: projectFilterSchema. Returns { projects }.

GET /api/projects/:id

Get a single project. Returns { project } or 404.

PUT /api/projects/:id

Update a project. Body: projectUpdateSchema. Returns { project }.

POST /api/projects/:id/milestones

Create a milestone. Body: milestoneCreateSchema. Returns { milestone } (201).

PUT /api/projects/:id/milestones/:milestoneId

Update milestone status. Body: milestoneUpdateSchema ({ status: MilestoneStatus }). Returns { milestone }.

GET /api/projects/:id/tasks

List project tasks. Query: taskFilterSchema. Returns { tasks }.

POST /api/projects/:id/tasks

Create a task. Body: taskCreateSchema. Returns { task } (201).

PUT /api/projects/:id/tasks/:taskId/status

Update task status. Body: taskStatusUpdateSchema ({ statusWorkflow }). Returns { task }.

POST /api/projects/:id/time-entries

Log a time entry against a project. Body: timeEntryCreateSchema. Returns { timeEntry } (201).


73. Collections

Source: apps/hub/src/api/routes/collections.ts. Auth required. Schemas in collection.schemas.ts.

GET /api/collections/templates

List built-in collection-type templates. Returns { templates }.

POST /api/collections/types

Create a custom collection type. Body: collectionTypeCreateSchema. Returns { type } (201).

POST /api/collections

Create a collection. Body: collectionCreateSchema. Returns { collection } (201).

GET /api/collections

List collections. Query: collectionFilterSchema. Returns CollectionService.listCollections result.

GET /api/collections/items/:id

Get a single collection item. Returns { item } or 404. Registered before /:id on purpose.

GET /api/collections/:id

Get a single collection. Returns { collection } or 404.

POST /api/collections/:id/items

Add an item to a collection. Body: collectionItemCreateSchema. Returns { item } (201).

GET /api/collections/:id/items

List items in a collection. Query: collectionItemFilterSchema. Returns CollectionService.listItems result.


74. Journal

Source: apps/hub/src/api/routes/journal.ts. Auth required. Schemas in journal.schemas.ts.

POST /api/journal

Create a journal entry. Body: journalEntryCreateSchema. Returns { entry } (201).

GET /api/journal

List journal entries. Query: journalEntryFilterSchema. Returns JournalService.listEntries result.

GET /api/journal/mood

Mood history over a date range. Query: ?fromDate=&toDate= (defaults to last 30 days). Returns { history }.

GET /api/journal/:id

Get a single journal entry. Returns { entry } or 404.

PUT /api/journal/:id

Update a journal entry. Body: journalEntryUpdateSchema. Returns { entry }.


75. Media

Source: apps/hub/src/api/routes/media.ts. Auth required. Schemas in media.schemas.ts.

POST /api/media

Track a piece of media (book, film, podcast, etc.). Body: mediaCreateSchema. Returns { media } (201).

GET /api/media

List media. Query: mediaFilterSchema. Returns MediaService.listMedia result.

GET /api/media/:id

Get a single media item. Returns { media } or 404.

PUT /api/media/:id

Update progress. Body: mediaUpdateSchema (progressPct, progressDetail). Returns { media }.

POST /api/media/:id/complete

Mark media complete. Body: mediaUpdateSchema (rating, review). Returns { media }.


76. Knowledge

Source: apps/hub/src/api/routes/knowledge.ts. Auth required. Schemas in knowledge.schemas.ts.

POST /api/knowledge

Create a knowledge capture (highlight, note, quote, etc.). Body: knowledgeCaptureCreateSchema. Returns { capture } (201).

GET /api/knowledge

List captures. Query: knowledgeCaptureFilterSchema. Returns KnowledgeService.listCaptures result.

GET /api/knowledge/media/:mediaId

List captures linked to a media item. Returns { captures }.

GET /api/knowledge/:id

Get a single capture. Returns { capture } or 404.


77. Environment

Source: apps/hub/src/api/routes/environment.ts. Auth required. Schemas in environment.schemas.ts.

POST /api/environment

Record an environment reading (temperature, humidity, AQI, etc.). Body: envReadingCreateSchema. Returns { reading } (201).

GET /api/environment

List readings. Query: envReadingFilterSchema. Returns EnvironmentService.listReadings result.

GET /api/environment/current

Get the latest reading per type. Returns { readings }.

GET /api/environment/history

History for a single reading type. Query: ?readingType=&fromDate=&toDate= (defaults: last 7 days, temperature). Returns { history }.


78. Home

Source: apps/hub/src/api/routes/home.ts. Auth required. Schemas in home.schemas.ts.

POST /api/home/readings

Record a home reading (meter, sensor, etc.). Body: homeReadingCreateSchema. Returns { reading } (201).

GET /api/home/readings

List home readings. Query: homeReadingFilterSchema. Returns HomeService.listReadings result.

POST /api/home/bills

Record a utility bill. Body: utilityBillCreateSchema. Returns { bill } (201).

GET /api/home/bills

List utility bills. Query: homeReadingFilterSchema (reused). Returns HomeService.listUtilityBills result.

GET /api/home/energy-stats

Energy stats over a window. Query: ?fromDate=&toDate= (defaults to last 30 days). Returns { stats }.


79. Learning

Source: apps/hub/src/api/routes/learning.ts. Auth required. Schemas in learning.schemas.ts.

POST /api/learning/subjects

Create a learning subject. Body: learningSubjectCreateSchema. Returns { subject } (201).

GET /api/learning/subjects

List subjects. Query: learningSubjectFilterSchema. Returns LearningService.listSubjects result.

POST /api/learning/sessions

Log a study session. Body: studySessionCreateSchema. Returns { session } (201).

POST /api/learning/certifications

Add a certification. Body: certificationCreateSchema. Returns { cert } (201).

GET /api/learning/subjects/:id

Get a single subject. Returns { subject } or 404.

GET /api/learning/subjects/:id/sessions

List study sessions for a subject. Query: studySessionFilterSchema. Returns LearningService.getStudySessions result.

GET /api/learning/subjects/:id/progress

Subject progress summary. Returns { progress }.


80. Capture

Source: apps/hub/src/api/routes/capture.ts. Auth required. Schemas in capture.schemas.ts. Used by the Windows agent and similar capture clients.

POST /api/capture/rules

Create a capture rule. Body: captureRuleCreateSchema. Returns { rule } (201).

GET /api/capture/rules

List capture rules. Returns { rules }.

PUT /api/capture/rules/:id

Update a capture rule. Body: captureRuleUpdateSchema. Returns { rule }.

POST /api/capture/activity

Record an activity capture. Body: activityCaptureCreateSchema. Returns { capture } (201).

POST /api/capture/screen

Record a screen capture. Body: screenCaptureCreateSchema. Returns { capture } (201).

POST /api/capture/clipboard

Record a clipboard event. Body: clipboardCreateSchema. Returns { capture } (201).

POST /api/capture/input

Record input activity (keystrokes/mouse counters; no content). Body: inputActivityCreateSchema. Returns { capture } (201).

GET /api/capture/activity

List activity captures. Query: captureActivityFilterSchema. Returns CaptureService.listCaptures result.


81. Reactions

Source: apps/hub/src/api/routes/reactions.ts. Auth required.

GET /api/reactions

Query the reaction log. Query: reactionLogFilterSchema. Returns ReactionLogService.queryReactions result.


82. ActivityPub Public + WebFinger

Source: apps/hub/src/api/routes/federation.ts. These routes form the public ActivityPub surface used by remote Fediverse servers and are not auth-gated (the inbox uses HTTP Signatures instead). Authenticated /api/federation/* routes are documented in §7.

GET /.well-known/webfinger

WebFinger lookup. Query: ?resource=acct:<username>@<host>. Returns a JRD (Content-Type: application/jrd+json) pointing at /ap/actors/<username>.

GET /.well-known/did.json

did:web DID Document for the hub. Returns the DID Document with verificationMethod, authentication, assertionMethod, and an ActivityPubActor service entry.

GET /ap/actors/:username

Returns the ActivityPub Actor JSON. Content-Type: application/activity+json. 404 if :username does not match the configured local username.

GET /ap/actors/:username/outbox

Outbox OrderedCollection. Content-Type: application/activity+json.

POST /ap/actors/:username/inbox

Inbound activity from a remote server. Verifies HTTP Signature on the request before calling ActivityPubService.handleInboundActivity. Returns { ok: true } (202) on success, 401 on invalid signature, 404 if :username is unknown.

GET /ap/actors/:username/followers

Followers OrderedCollection. Content-Type: application/activity+json.

GET /ap/actors/:username/following

Following OrderedCollection. Content-Type: application/activity+json.


83. Provider OAuth (Generic + Fitbit + Google Fit + Plaid)

Sources: providerOAuth.ts, fitbitOAuth.ts, googleFitOAuth.ts, plaidOAuth.ts. The authorize/callback redirects are not auth-gated at the framework level (they rely on session cookies / state), but each handler still calls getAuthenticatedUserId and aborts if unset.

GET /api/oauth/:providerId/authorize

Generic provider authorize. Looks up an OAuthManager registered via registerOAuthManager(providerId, manager). Optional ?scopes=a,b,c. Redirects to the provider's auth URL. 404 if no manager is registered.

GET /api/oauth/:providerId/callback

Generic provider callback. Exchanges ?code= for tokens via the registered manager, then calls ProviderLifecycleService.handleCredentialAdded(userId, providerId, { accessToken, refreshToken, expiresIn }). Returns { ok: true, providerId }.

GET /api/oauth/fitbit/authorize

Redirects the browser to https://www.fitbit.com/oauth2/authorize with scopes activity heartrate sleep weight profile settings. Requires FITBIT_CLIENT_ID env.

GET /api/oauth/fitbit/callback

Exchanges ?code= for tokens at https://api.fitbit.com/oauth2/token (Basic auth = base64(clientId:clientSecret)), stores access/refresh/clientId/clientSecret in Supabase Vault under <userId>:fitbit:*, upserts a user_credentials row (credential_type='fitbit'), writes an audit entry, and redirects to ${WEB_URL}/settings?connected=fitbit.

GET /api/oauth/google-fit/authorize

Redirects to Google's OAuth2 endpoint with five fitness scopes (activity/blood_pressure/body/heart_rate/sleep), access_type=offline, prompt=consent. Requires GOOGLE_FIT_CLIENT_ID.

GET /api/oauth/google-fit/callback

Exchanges ?code= at https://oauth2.googleapis.com/token, stores tokens in Vault under <userId>:google_fit:*, upserts user_credentials, writes audit, redirects to ${WEB_URL}/settings?connected=google_fit.

GET /api/oauth/plaid/authorize

Redirect to ${WEB_URL}/settings/plaid (the actual flow uses link-token + exchange below; this exists for capability-registry compatibility).

Creates a Plaid Link token by POSTing to <plaid base>/link/token/create (sandbox/development/production based on PLAID_ENV). Returns { link_token }. Auth required.

POST /api/oauth/plaid/exchange

Body: { public_token: string } (validated by plaidExchangeBodySchema). Exchanges the public token at <plaid base>/item/public_token/exchange, stores access_token + item_id + clientId + secret in Vault under <userId>:plaid:*, upserts user_credentials, writes audit. Returns { connected: true } (201). Auth required.


84. WhatsApp Webhook

Source: apps/hub/src/api/routes/whatsappWebhook.ts. Public (no auth).

GET /webhooks/whatsapp

Meta verification handshake. Query: hub.mode, hub.verify_token, hub.challenge. If mode === 'subscribe' and hub.verify_token matches the configured verifyToken, returns the challenge string with status 200; otherwise 403.

POST /webhooks/whatsapp

Inbound messages and status updates from Meta. Body is the raw Meta payload. The handler calls ChannelService.routeInbound('whatsapp', body). Returns { ok: true } (200).


85. IVR Flows

Source: apps/hub/src/api/routes/voice.ts. Auth required. Stub implementation at this commit — full delegation to an IvrFlowService is pending.

POST /api/calling/ivr-flows

Create an IVR flow. Body validated by ivrFlowCreateSchema. Returns { flow } (201) — stub returns id: 'ivr-flow-stub'.

GET /api/calling/ivr-flows

List IVR flows. Returns { flows: [] } (stub — always empty at this commit). // TODO(verify): replace with real list once IvrFlowService lands.

PUT /api/calling/ivr-flows/:id

Update an IVR flow. Body: ivrFlowUpdateSchema. Returns { flow } (stub echoes the body).

DELETE /api/calling/ivr-flows/:id

Delete an IVR flow. Returns 204 (stub).


86. Email Signatures

Source: apps/hub/src/api/routes/emailClient.ts. Auth required. Schemas in email.schemas.ts. (The bulk of the email-client routes are documented in §56.)

GET /api/email/signatures

List signatures for the authenticated user. Returns { signatures }.

POST /api/email/signatures

Create a signature. Body: emailSignatureCreateSchema. Returns { signature } (201).

PUT /api/email/signatures/:id

Update a signature. Body: emailSignatureUpdateSchema. Returns { signature }.

DELETE /api/email/signatures/:id

Delete a signature. Returns 204.


87. Dashboard Widgets

Source: apps/hub/src/api/routes/contactTimeline.ts. Auth required. These power the home-screen dashboard widgets and live alongside the contact-timeline routes documented in §59.

GET /api/dashboard/recent-contacts

Recent contacts the user has interacted with. Query: ?limit= (default 5). Returns { contacts }.

GET /api/dashboard/missed-comms

Missed communications across channels. Returns the ContactTimelineService.getMissedComms result directly (no envelope).

GET /api/dashboard/comm-stats

Aggregate communication statistics for the current user. Returns the ContactTimelineService.getCommStats result directly (no envelope).


88. AI Routing Rules

Source: registered directly in apps/hub/src/api/server.ts (not in a routes/*.ts module). Auth required. These persist to the llm_routing_rules table and configure which LLM provider/model handles which data domain or query type.

GET /api/ai/routing-rules

List routing rules for the authenticated user via dataService.query('llm_routing_rules', { owner_id }). Returns { rules }.

POST /api/ai/routing-rules

Create a routing rule. Body: { name: string, provider: string, model?: string, data_domains?: string[], query_types?: string[], priority?: number, reason?: string }. priority defaults to 100. Returns { rule } (201). 400 if name or provider missing.

DELETE /api/ai/routing-rules/:id

Delete a routing rule. Returns 204.


Authentication

All authenticated endpoints accept a JWT in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

The JWT is issued by Supabase Auth. The hub extracts the user ID from the sub claim.

API Key Authentication

API keys created via /api/developer/keys can be used as Bearer tokens:

Authorization: Bearer mo_live_abc123...

Admin Access

Admin endpoints check for role: "admin" or scopes: ["admin"] in the JWT payload.


Error Responses

All errors follow a consistent format:

{ "error": "Human-readable error message" }

Common status codes:

CodeMeaning
400Bad request / validation error
401Missing or invalid authentication
403Forbidden (insufficient permissions)
404Resource not found
409Conflict (e.g., optimistic concurrency)
429Rate limit exceeded
500Internal server error
503Service unavailable (dependency not configured)

API Versioning

All responses include an X-API-Version header. The current version can be queried at GET /api/version.

Clients can request a specific version via the X-API-Version request header.


GraphQL

A GraphQL endpoint is available at POST /graphql. See the interactive schema explorer when the hub is running.


OpenAPI / Swagger

Interactive API documentation is served at:

  • Swagger UI: http://localhost:4101/api/docs
  • OpenAPI JSON: http://localhost:4101/api/openapi.json