Skip to content

REST API

The aeqi platform exposes a REST API for Company management, authentication, billing, integrations, and the catch-all proxy that forwards /api/* into a Company runtime. The canonical runtime selector is the X-Company header (fallback X-Entity) and the company_id query parameter (legacy alias trust_id). Some on-chain and protocol-level fields still carry the trust term.

Use the REST API when software needs to operate aeqi over HTTP: account flows, Company launch, runtime provisioning, integrations, billing, public profiles, inference, and proxied runtime operations. Use MCP when an AI client should operate Company memory, quests, agents, events, and code intelligence as tools.

Base URL

Environment URL Notes
Hosted https://app.aeqi.ai/api Platform control plane.
Self-hosted http://127.0.0.1:8443/api Default platform port.
Tenant runtime http://127.0.0.1:8400+/api Per-Company runtime; reached through the platform proxy, not directly.

/api/* routes are served by the platform binary (aeqi-platform.service). Anything not registered explicitly is forwarded through routes::proxy::catch_all_proxy_handler to the tenant runtime selected by the X-Company header (fallback X-Entity) or a company_id / trust_id query parameter.

Authentication

Most endpoints require a JWT bearer token. The token is obtained from one of several login flows (email + code, password, wallet/SIWE, passkey). The header is:

Authorization: Bearer <jwt>

The X-Company header selects which Company runtime a proxied call routes to (the platform still accepts X-Entity as a fallback). Proxied runtime calls return 400 { "error": "X-Company header required" } if no runtime is supplied. Non-tenant platform routes such as login, billing, API keys, and /api/companies do not need it.

A small number of endpoints use other auth modes:

  • MCP key auth/api/mcp and /api/mcp/validate require Authorization: Bearer sk_…; X-Api-Key: ak_… is optional but recommended so the platform can bind the call to the same user account.
  • Signed OAuth state/api/integrations/{provider}/callback is reached by the user's browser after an OAuth provider redirect; the signed state token authenticates the call.
  • Admin secret/api/admin/* requires the platform admin token, not a user JWT.

Full request/response details for the login flows live in Authentication.

Public Endpoints

No auth required.

Health

GET /api/health
GET /api/diagnostics/runtime-health

/api/health is the liveness check and returns { "status": "ok" }. /api/diagnostics/runtime-health exposes the runtime health summary used by operator and status surfaces.

Authentication entry points

GET  /api/auth/mode
POST /api/auth/login
POST /api/auth/login/email
POST /api/auth/signup
POST /api/auth/verify
POST /api/auth/resend-code

Wallet auth (SIWE):

POST /api/auth/wallet/nonce
POST /api/auth/wallet/login
POST /api/auth/wallet/signup

Passkey auth:

POST /api/auth/passkey/register-begin
POST /api/auth/passkey/register-finish
POST /api/auth/passkey/login-begin
POST /api/auth/passkey/login-finish

Passwordless email sign-in (single login-codes row, three consume paths):

POST /api/auth/login/code/request
POST /api/auth/login/code/consume
POST /api/auth/login/magic/consume

TOTP login step:

POST /api/auth/totp/login

Password recovery:

POST /api/auth/forgot-password
POST /api/auth/reset-password

Invites and waitlist:

POST /api/auth/invite/check
POST /api/auth/waitlist
GET  /api/auth/waitlist/confirm

Email unsubscribe:

GET  /unsubscribe
POST /unsubscribe

The signed token in the unsubscribe URL is the credential for that endpoint.

Solana welcome flow

Mounted only when AEQI_SOLANA_RPC is configured. Used by the /welcome onboarding shell, which provisions a Solana custodial signer alongside the platform identity.

POST /api/auth/welcome/email-start
GET  /api/auth/welcome/email-verify
POST /api/auth/welcome/email-verify-code
POST /api/auth/welcome/wallet-start
POST /api/auth/welcome/wallet-verify
POST /api/auth/welcome/passkey-register-start
POST /api/auth/welcome/passkey-register-finish
POST /api/auth/welcome/passkey-assert-start
POST /api/auth/welcome/passkey-assert-finish
GET  /api/auth/welcome/google/start
GET  /api/auth/welcome/google/callback
GET  /api/auth/welcome/github/start
GET  /api/auth/welcome/github/callback

OAuth provider callbacks

GET /api/integrations/google/callback
GET /api/integrations/github/callback
GET /api/integrations/etsy/callback

Reached by the user's browser after the OAuth provider redirects back. The signed state token resolves the owning agent + entity. The matching authenticated start/status endpoints are under Authenticated Endpoints → Integrations.

Webhooks

Inbound webhook handlers for external services:

POST /api/webhooks/stripe
POST /api/webhooks/deploy
POST /api/webhooks/telegram/{token}
POST /api/webhooks/whatsapp

Template catalog

GET /api/templates
GET /api/templates/default
GET /api/templates/{slug}

Public, no X-Company required. The catalog is platform-shared static content.

/api/templates is the company-launch catalog the /launch flow reads before any Company runtime exists; it returns the two shipped company templates (new-company, existing-company). /api/templates/default resolves to the default launch template (new-company); /api/templates/{slug} returns one template's full JSON. See Template schema.

Spawn (proxied)

POST /api/templates/spawn
POST /api/templates/spawn-into

Registered in the public router so they shadow /api/templates/{slug} (which would otherwise intercept the path and reject the POST); the catch-all proxy forwards them to the per-Company orchestrator selected by X-Company.

Economy + public profiles

GET /api/economy/list
GET /api/public/entities/{slug}
GET /api/public/company/{address}
GET /api/public/company/{address}/assets
GET /api/public/company/{address}/incorporation
GET /api/public/status/walks

/api/economy/list returns every Company whose placement has public=true, with on-chain address — drives /economy. /api/public/entities/{slug} returns the public profile JSON for a Company that has public=true; returns 404 for private workspaces (indistinguishable from non-existent). /api/public/company/{address} returns the public composite viewer payload (on-chain + IPFS + indexer) for an on-chain address when the linked workspace is public. The /assets and /incorporation subresources expose public document bundles for a public Company address when those modules are present. /api/public/status/walks returns recent public walk status rows for the landing status surface.

Public launch-site forms

POST /api/public/website/waitlist
POST /api/public/website/support-checkout
POST /api/public/slot/waitlist

Public, resolved from the Host header of the Company subdomain serving the form. /api/public/website/waitlist joins the per-Company launch-site waitlist. /api/public/website/support-checkout opens a day-one support purchase as a destination charge via the Company's Express account. /api/public/slot/waitlist is the anonymous "launching soon" placeholder waitlist for a bare <slug> subdomain with no placement yet; it keys on the slug rather than a Company.

Role invitations

GET /api/invitations/{token}

Resolves a role-invitation token to its details. Public so an unauth recipient can see what they're being invited to before accepting.

MCP

POST /api/mcp
POST /api/mcp/validate

POST /api/mcp accepts an MCP JSON-RPC request and returns its response. /api/mcp/validate echoes back which actor and Company a key resolves to. Auth is Authorization: Bearer sk_…; pass X-Api-Key: ak_… as well when binding the call to a user account. GET and DELETE are not callable MCP transports on the hosted platform today.

See MCP for the tool surface.

LLM proxy

ANY /api/llm/v1/{*path}

Forwards OpenAI-compatible chat traffic to the upstream LLM provider configured for the active Company. Use Inference (/v1/*) for end-user inference; this proxy is for internal runtime traffic.

Authenticated Endpoints

Require a valid JWT bearer. Proxied runtime endpoints additionally require a Company runtime context via X-Company (fallback X-Entity) or the company_id / trust_id query parameter.

Account

GET  /api/auth/me
POST /api/auth/phishing-code
POST /api/auth/totp/setup
POST /api/auth/totp/verify
POST /api/auth/totp/disable
GET  /api/auth/activity
GET  /api/auth/sessions
POST /api/auth/sessions/revoke
POST /api/auth/sessions/revoke-others
GET  /api/auth/invite-codes
POST /api/auth/invite-codes
GET  /api/admin/overview
GET  /api/admin/llm-provider
POST /api/admin/llm-provider
GET  /api/account/notifications
POST /api/account/notifications/stop
POST /api/account/notifications/resume

/api/admin/overview is the user-facing admin view (returns 200 only if the caller is a platform admin); it is not part of the admin secret-guarded surface below. /api/admin/llm-provider reads or updates the active hosted inference provider configuration for platform admins. The notification routes expose and update the user's channel suppression state.

Email change

POST /api/me/email/change/begin
POST /api/me/email/change/finish

Wallets

POST   /api/me/wallets/link
PUT    /api/me/wallets/{id}/primary
DELETE /api/me/wallets/{id}

Passkeys

POST /api/me/passkeys/add/begin
POST /api/me/passkeys/add/finish
POST /api/account/enroll-passkey
POST /api/wallet/upgrade-to-passkey

The last two return 501 Not Implemented until WS-4e ships.

Billing

POST /api/billing/checkout
GET  /api/billing/subscription
POST /api/billing/portal
GET  /api/billing/overview
POST /api/billing/credit-addon
POST /api/billing/top-up
POST /api/billing/plan-change/preview
POST /api/billing/plan-change/confirm
POST /api/billing/annual/confirm
POST /api/billing/plan-cancel

Subscription and payment management via Stripe. checkout opens a subscription checkout; subscription and overview read current plan + balance state; portal opens the Stripe customer portal. credit-addon and its alias top-up purchase one-time credit. plan-change/preview returns the proration preview for a plan switch and plan-change/confirm applies it; annual/confirm confirms an annual upgrade. plan-cancel cancels the active subscription.

Companies

GET    /api/companies
POST   /api/companies
DELETE /api/companies/{company_id}
PUT    /api/companies/{company_id}
GET    /api/companies/{company_id}/assets
GET    /api/companies/{company_id}/incorporation
GET    /api/companies/{company_id}/email/messages
GET    /api/companies/{company_id}/email/stats
POST   /api/companies/{company_id}/email/test
GET    /api/companies/{company_id}/website/analytics
GET    /api/companies/{company_id}/payments
POST   /api/companies/{company_id}/payouts/connect
POST   /api/companies/{company_id}/runtime/restart

/api/companies is the user-owned Company collection. It is registered platform-side (before the catch-all proxy) so it returns the caller's cross-runtime list rather than whatever single runtime the scoped Company header currently points at. POST creates a Company, GET lists; the {company_id} routes update or delete one. The assets, incorporation, email, and website/analytics subroutes back the Company document, incorporation, inbox, and analytics panels for a selected runtime (email/stats returns inbox counters for the panel header). payments lists the Company's payment records; payouts/connect opens Stripe Express onboarding so the Company can receive payouts. runtime/restart reboots the Company's VPS in place (data and IP preserved; owner-only, same auth as the Company DELETE).

/start launch

POST /api/start/launch
POST /api/start/check-name
POST /api/start/suggest-idea
POST /api/start/suggest-name
GET  /api/start/launch/status/{trust_id}
GET  /api/start/launch/stream/{trust_id}
GET  /api/start/share/{trust_id}
POST /api/start/share/{trust_id}/verify
GET  /api/start/share/{trust_id}/weekly
POST /api/start/share/{trust_id}/weekly/verify

launch provisions a personal Company via the /start experience. Gated by subscription status (subscription_required HTTP 402 if missing) and a workspace cap of 10 companies per user (workspace_cap_exceeded HTTP 402; admins exempt).

launch/status/{trust_id} polls provisioning progress for a launched Company; launch/stream/{trust_id} is the SSE variant streaming the same progress live. suggest-idea and suggest-name back the /start flow's LLM suggestions for a company idea and an available display name. share/{trust_id} returns the launch-announcement share code and prefilled post; share/{trust_id}/verify runs platform-side post verification and awards a one-time flat credit bonus (the platform checks the post, never the tenant runtime). The weekly pair is the weekly progress-post share loop: same platform-side post verification, but the reward is a bounded top-up of the monthly operating-credit grant, claimable once per ISO week.

Request:

{
  "template": "default",
  "display_name": "My Company",
  "mission": "optional one-line mission statement",
  "plan": "growth"
}

name is accepted as a fallback alias for display_name. If template is omitted, the configured default blueprint is used.

Response (200):

{
  "ok": true,
  "trust_id": "company-id",
  "display_name": "My Company",
  "website_domain": "my-company.aeqi.ai",
  "website_url": "https://my-company.aeqi.ai",
  "email_address": null
}

The trust_id field carries the new Company's id. Placement provisioning (sandbox / host / VPS) proceeds async; poll GET /api/start/launch/status/{trust_id} until its status flips from pending to ready. check-name returns whether a display name is available for the caller.

Runtime provisioning

POST /api/runtime/provision
POST /api/runtime/provision-treasury
GET  /api/runtime/status

Provision attaches managed runtime capacity to a Company. The Stripe and treasury paths converge on the same placement lifecycle; status reads the live placement and service state.

Solana and protocol routes

Mounted only when the relevant Solana services are configured.

POST /api/companies/create
POST /api/solana/companies/create
POST /api/solana/first-buy
POST /api/solana/curve-sell
POST /api/solana/token-mint
POST /api/solana/token-burn
POST /api/solana/token-transfer
POST /api/solana/vesting-create
POST /api/solana/budget-module-init
POST /api/solana/budget-create
POST /api/solana/funding-module-init
POST /api/solana/funding-request-create
GET  /api/curves/{trust_id}/state

These authenticated routes back staged protocol modules: genesis, first-buy, curves, token operations, vesting, budgets, and funding requests. Treat them as deployment-dependent protocol surfaces, not baseline hosted-app requirements. Normal hosted users create Companies through /api/companies or /api/start/launch; protocol genesis is for Solana-enabled deployments.

Architect deploy

POST /api/architect/deploy

Same provisioning path as /start/launch, but the Blueprint is the architect-generated inline JSON rather than a static catalog slug. Earlier verbs (architect.draft, architect.refine) live on the runtime and are reached via the proxy.

Integrations

Company app OAuth and per-agent OAuth.

Company-scoped app connections:

GET /api/trust/{trust_ref}/apps/google/start
GET /api/trust/{trust_ref}/apps/google/status
GET /api/trust/{trust_ref}/apps/etsy/start
GET /api/trust/{trust_ref}/apps/etsy/status

Telegram gateway for a Company (the trust_ref path segment is the lower-level runtime selector behind the Company):

POST   /api/trust/{trust_ref}/apps/telegram/link-code
GET    /api/trust/{trust_ref}/apps/telegram/status
GET    /api/trust/{trust_ref}/apps/telegram/bindings
DELETE /api/trust/{trust_ref}/apps/telegram/bindings/{binding_id}

link-code mints a /start link code that binds a Telegram chat to the Company's CEO via the shared central bot; status reports the gateway state. bindings lists the Telegram accounts connected to this Company, and the {binding_id} route revokes one. Both are scoped so a Company only ever sees and revokes its own bindings.

Per-agent OAuth, one start/status pair per provider:

GET /api/agents/{agent_id}/integrations/google/start
GET /api/agents/{agent_id}/integrations/google/status
GET /api/agents/{agent_id}/integrations/github/start
GET /api/agents/{agent_id}/integrations/github/status

start returns a signed redirect to the provider. The matching callbacks /api/integrations/google/callback, /api/integrations/github/callback, and /api/integrations/etsy/callback are listed above as public routes; providers redirect there without our auth header.

API keys

POST /api/keys
GET  /api/keys
DELETE /api/keys/{id}
POST /api/account/api-key

/api/account/api-key mints a single personal API key (older surface). /api/keys is the labelled, multi-key collection.

Hosting

GET    /api/hosting/domains
POST   /api/hosting/domains
DELETE /api/hosting/domains/{domain}
GET    /api/hosting/waitlist
POST   /api/hosting/deploy

Manage custom domains for Company runtimes. /api/hosting/waitlist lists the launch-site waitlist signups for a Company the caller owns (the public join form is POST /api/public/website/waitlist). /api/hosting/deploy is the entrypoint for the runtime apps.deploy tool: it builds the Company's seeded site and flips the Company domain from the launch page to the built site (owner-authenticated).

Role invitations

POST /api/companies/{company_id}/roles/{role_id}/invitations
GET  /api/companies/{company_id}/invitations
POST /api/invitations/{token}/accept
POST /api/invitations/{token}/decline
GET  /api/me/directed-entities

Invite users to roles within a Company; accept or decline. Creating an invitation is scoped to a {company_id} and {role_id}; the token-based accept/decline routes pair with the public GET /api/invitations/{token} resolver. /api/me/directed-entities lists every Company the caller has been granted directed access to.

Identity resolver

GET /api/identity/resolve

Authenticated batch lookup for public keys into known identity records. The batch size is capped by the platform resolver.

Proxied Runtime Endpoints

Everything under /api/* that is not explicitly listed above is forwarded by catch_all_proxy_handler to the runtime selected by X-Company (fallback X-Entity) or the company_id / trust_id query parameter. Examples handled this way:

GET    /api/agents
POST   /api/agents/spawn
GET    /api/quests
POST   /api/quests
GET    /api/ideas
POST   /api/ideas
GET    /api/sessions
POST   /api/chat

A few proxied paths have platform-side specialisation registered explicitly so the response can be patched before being returned:

  • GET /api/ws — WebSocket proxy.
  • GET /api/chat/stream — server-sent events / WebSocket stream proxy.
  • GET /api/ideas/{id}/comments — proxies the runtime reply but injects user display names from the platform user table.
  • GET /api/roles, GET /api/roles/{id} — proxies and patches occupant_name for human occupants.

Runtime ideas surface

The runtime registers the following routes under /api/ideas/*. Use them through the platform proxy with X-Company set, not directly against the per-tenant runtime port.

GET    /api/ideas                       List visible ideas (query: agent_id?)
POST   /api/ideas                       Create or supersede an idea
POST   /api/ideas/files                 Upload a root file-backed Idea
GET    /api/ideas/search                Hybrid BM25 + vector search
GET    /api/ideas/prefix                Prefix-match for autocomplete
POST   /api/ideas/by-ids                Batch fetch by id list
GET    /api/ideas/profile               Profile-scoped catalog read
GET    /api/ideas/graph                 Adjacency view for the graph renderer
POST   /api/ideas/seed                  Bulk insert seed ideas (blueprint apply)
PUT    /api/ideas/{id}                  Update name / content / tags
DELETE /api/ideas/{id}                  Delete (fails 409 if a quest still references it)
POST   /api/ideas/{id}/files            Upload a file-backed child Idea
GET    /api/ideas/{id}/edges            Edges incident to one idea
POST   /api/ideas/{id}/edges            Add a typed edge
DELETE /api/ideas/{id}/edges            Remove a typed edge
GET    /api/ideas/{id}/activity         Activity feed (system events on this idea)
GET    /api/ideas/{id}/comments         Comment thread (specialised at the platform)
POST   /api/ideas/{id}/subscribe        Subscribe the caller to comment notifications
GET    /api/ideas/{id}/children         List children (Tables Phase 2)
PUT    /api/ideas/{id}/properties       Update typed properties bag

File uploads use multipart/form-data. The required fields are agent_id and file; optional fields are scope and, for root uploads, the parentless route /api/ideas/files. The child route sets parent_idea_id from the path and forwards both forms to the runtime files_upload IPC verb, which creates an Idea wrapper for the artifact.

link, feedback, and walk are MCP-only verbs — there are no REST routes for them. The MCP dispatcher rewrites them into IPC commands (link_idea, feedback_idea, walk_ideas).

Admin Endpoints

Require the platform admin secret (header), not a user JWT.

GET  /api/admin/containers
POST /api/admin/containers/{id}/restart
GET  /api/admin/roots
POST /api/admin/roots/{name}/promote-host
POST /api/admin/roots/{name}/seed
POST /api/admin/update
GET  /api/admin/stats
GET  /api/admin/template-packs
POST /api/admin/template-packs
GET  /api/admin/template-packs/{slug}
POST /api/admin/template-packs/{slug}/templates
POST /api/admin/vps/spawn-test

Response Format

Responses are not wrapped in a uniform envelope — different handlers return different shapes. Common patterns:

{ "ok": true, "id": "..." }
{ "items": [ ... ], "next_cursor": null }

Errors return a 4xx or 5xx status with a body of one of:

{ "ok": false, "error": "code", "message": "human-readable description" }
{ "error": "code", "message": "..." }

Inference and MCP have their own error shapes — see those references.

Rate Limiting

Platform-side: no per-endpoint quotas are published. The tenant runtime applies tower_governor with SmartIpKeyExtractor — abuse can trigger 429 responses. The runtime-bound proxy always injects X-Forwarded-For: 127.0.0.1 from inside the platform binary so internal calls survive the key extractor.

Next Steps

  • Authentication — JWT lifecycle, signup, login flows.
  • Inference/v1/* OpenAI-compatible chat.
  • MCP — operate the same surface programmatically.
  • Concepts — the four primitives.

Cookies for sign-in and analytics. No third-party tracking.