Skip to main content

Overview

A running QiForge oracle exposes a REST + WebSocket surface. Most routes require a UCAN delegation header; some (/health, /docs, plus anything declared in getAuthExcludedRoutes() or authExcludedRoutes) are public. The Swagger UI at /docs is generated from the running app’s controllers — open it in a browser for the live, deployment-specific reference.

Authentication

Protected routes authenticate with a user-signed UCAN invocation, plus an optional delegation for downstream authorization. This is the same model the Identity and auth guide describes.
HeaderRequiredNotes
Authorization: Bearer <invocation>Yes (primary)The user-signed UCAN invocation — proves who is calling. Only read when X-Auth-Type: ucan is also present.
X-Auth-Type: ucanYes (primary)Selector telling the middleware to read the bearer as a UCAN invocation. Without it the bearer is ignored.
x-ucan-delegationFallback / downstream-authzThe user→oracle delegation. Carries the capabilities plugins use to mint downstream invocations. Also accepted as the auth artifact on its own for clients that haven’t migrated to invocation auth.
x-didNoThe user’s IXO DID (informational). The runtime derives the authenticated DID from the invocation/delegation — x-did is not used for authentication.
x-matrix-access-tokenNoMatrix session token (used by Portal/Slack).
x-matrix-homeserverNoMatrix homeserver URL.
x-timezoneNoPropagates to rtCtx.user.timezone.
x-request-idNoCorrelation ID; echoed back as X-Request-Id.
When neither an invocation nor a delegation is present, protected routes return 401:
Missing UCAN authentication: provide Authorization: Bearer <invocation> with X-Auth-Type: ucan, or an x-ucan-delegation header
A malformed or expired invocation returns 401 Invalid UCAN invocation. Public routes ignore auth headers and don’t validate them.

CORS

CORS_ORIGIN controls allowed origins (wildcard * is the default; specific origins enable credentials). Allowed request headers:
Content-Type, Authorization, x-ucan-delegation,
x-matrix-access-token, x-matrix-homeserver,
x-did, x-request-id, x-auth-type, x-timezone
Allowed methods: GET, POST, PUT, DELETE, PATCH, OPTIONS. Exposed response headers: X-Request-Id.

Public routes

RouteMethodAuthPurpose
/GETPublicLanding JSON ({ status, message, timestamp }).
/healthGETPublicLiveness probe ({ status, timestamp }).
/docsGETPublicSwagger UI.
/docs/(.*)GETPublicSwagger static assets.
Plus any route returned by a plugin’s getAuthExcludedRoutes() or by createOracleApp({ authExcludedRoutes }).

Protected routes

All of these require the auth headers above. For the request/response schemas of your specific deployment, hit GET /docs.

Sessions (/sessions)

RouteMethodPurpose
/sessionsPOSTCreate a chat session. Returns the new sessionId.
/sessions?limit&offsetGETList the authenticated user’s sessions (paginated; defaults limit=20, offset=0).
/sessions/:sessionIdDELETEDelete a session.

Messages (/messages)

RouteMethodPurpose
/messages/:sessionIdPOSTSend a message. Set stream: true in the body for an SSE stream instead of a single JSON reply.
/messages/:sessionIdGETList the messages in a session.
/messages/abortPOSTAbort an in-flight stream. Body: { "sessionId": "..." }.
POST /messages/:sessionId body (SendMessageDto):
FieldTypeNotes
messagestringRequired. The user’s message text.
streambooleantrue → SSE stream; otherwise a single JSON reply. Default false.
returnAllMessagesbooleanNon-stream only: also return the full transcript. Testing aid. Default false.
toolsarrayBrowser-tool declarations ({ name, schema, description }).
agActionsarrayAG-UI action declarations ({ name, description, schema, hasRender? }).
attachmentsarrayUp to 10 Matrix attachments (mxcUri or eventId, plus filename, mimetype).
mcpInvocationsobjectMap of MCP tool name → base64 CAR invocation for protected MCP tools.
timezonestringOverrides rtCtx.user.timezone.
homeServerstringThe user’s Matrix homeserver.
metadataobjectFree-form (editorRoomId, spaceId, …).
Streaming is a flag on this single endpoint — there is no separate /stream route.

Delegation (/delegation)

A user→oracle UCAN delegation lets the oracle mint downstream-service invocations on the user’s behalf. The client-sdk re-auth popup POSTs here; a non-React client must implement this to complete the authorization flow.
RouteMethodPurpose
/delegationPOSTStore a freshly-signed delegation. Returns { ok: true, expiration? }.
/delegationGETAuthorization status: { authorized: boolean, expiration? }.
/delegationDELETERevoke the stored delegation. Returns { ok: true }.
POST /delegation body (StoreDelegationDto):
FieldTypeNotes
rawstringRequired. Base64-encoded UCAN delegation CAR (user → oracle).
issuerstringDelegation issuer DID (the user).
audiencestringDelegation audience DID (this oracle).
expirationnumberUnix timestamp, seconds.

Other modules

  • SubscriptionModule — credit/subscription gating middleware (active when the credits plugin is loaded).
  • WsModule — the WebSocket gateway (see below).
Plugins contribute more routes via getNestModules() — e.g. SlackModule (Slack webhooks), UserPreferencesController (/user-preferences), and claim-processing cron endpoints. The Swagger UI at /docs is generated from your app’s controllers — including plugin and host routes — so it’s always the authoritative, deployment-specific list.

WebSocket

The oracle runs a socket.io gateway on namespace /. Plugins emit typed events via rtCtx.emit; the framework forwards them to the client over the session’s room.

Handshake

Connect with a sessionId query param and a UCAN in auth. A handshake with no sessionId, or with no valid UCAN, is disconnected immediately.
import { io } from 'socket.io-client';

const socket = io('https://your-oracle.example', {
  query: { sessionId },
  auth: {
    invocation,      // primary: the user-signed UCAN invocation
    ucanDelegation,  // fallback: a bare delegation (pre-invocation clients)
  },
});
The server validates the invocation (primary) or delegation (fallback) the same way HTTP requests do; the authenticated DID is the validated invoker, never the query value. On success it emits connected.

Server → client events

EventWhen it fires
connectedHandshake accepted.
pongReply to a ping.
statusReply to a status request (connection stats).
subscribedSubscription acknowledged.
available-eventsReply to list-events — the full event catalog.
tool_callA tool is being invoked (or has returned).
action_callAn AG-UI action is being invoked.
render_componentA render-component result is ready for the client.
browser_tool_callA browser-side tool is being invoked on the user’s tab.
router_updateA routing decision between agents/sub-agents.
message_cache_invalidationA cached message should be dropped.

Client → server events

EventPurpose
pingKeep-alive; server replies pong.
statusRequest connection stats; server replies status.
subscribeSubscribe to session events.
list-eventsAsk for the event catalog; server replies available-events.
tool_resultReturn a browser-tool result ({ toolCallId, result, error? }).
action_call_resultReturn an AG-UI action result ({ sessionId, toolCallId, result }).
Event payload types are currently Record<string, unknown> and may be tightened in future runtime versions. The @ixo/oracles-client-sdk React SDK handles this handshake, parses these events, and renders them.

Client SDK

For frontend integration, use @ixo/oracles-client-sdk — it handles the SSE / WebSocket protocol, UCAN delegation, and event parsing. See Client SDK.