Skip to main content
This page documents the HTTP endpoints exposed by the Aomi backend. All endpoints are relative to your backend URL (e.g., https://api.aomi.dev).

Authentication

Most endpoints take these headers:
HeaderDescription
X-Session-IdUUID identifying the conversation session
AOMI-APP-KEYYour Aomi App key (required for non-default Apps)

Endpoints

Create Session

Create a new chat session.
POST /api/sessions
Headers:
HeaderRequiredValue
X-Session-IdYesUUID for the new session
Request Body (optional):
{
  "public_key": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD68"
}
Response:
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "title": "New chat"
}

Get Session

Fetch one thread by ID.
GET /api/sessions/{id}
Path Parameters:
ParameterTypeDescription
idstringSession UUID
Response:
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "title": "ETH Price Discussion"
}
To list every thread for a wallet, call GET /api/sessions?public_key=.... See List Threads.

Send Message (Chat)

Send a message to the assistant. This returns a JSON snapshot of the updated session, not a stream. The message and its options ride in the query string. To stream the assistant’s work as it happens, open the updates channel and poll session state.
POST /api/chat?message={message}&app={app}
Query Parameters:
ParameterRequiredDescription
messageYesThe user message text
appNoTarget App (defaults to default)
public_keyNoWallet address to bind the session to
user_stateNoJSON-encoded user state (wallet, chain, connection)
client_idNoClient identifier for scoped secrets
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
AOMI-APP-KEYFor non-default AppsYour App key
Response: JSON snapshot of the session.
{
  "messages": [
    { "sender": "user", "content": "What is the current price of ETH?" },
    { "sender": "agent", "content": "The current price of ETH is $3,500.00." }
  ],
  "system_events": [],
  "title": "ETH price check",
  "is_processing": false,
  "user_state": null
}
FieldTypeDescription
messagesarrayConversation messages so far
system_eventsarraySystem events for the session
titlestringConversation title
is_processingbooleanWhether the assistant is still working
user_stateobjectSynced user state (wallet, chain, connection)

Get Session State

Get the current state snapshot for a session. Poll this to watch is_processing and pick up new messages while the assistant works.
GET /api/state
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
Query Parameters:
ParameterRequiredDescription
user_stateNoJSON-encoded user state to reconcile
client_idNoClient identifier for scoped secrets
Response:
{
  "messages": [],
  "system_events": [],
  "title": "ETH price check",
  "is_processing": false,
  "user_state": {
    "connection": { "is_connected": true },
    "evm": { "address": "0x742d...", "chain_id": 1 }
  }
}
Wallet fields are nested under user_state: the EVM address is user_state.evm.address, the chain is user_state.evm.chain_id, and connection status is user_state.connection.is_connected.

Interrupt Generation

Cancel an in-progress response.
POST /api/interrupt
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
Response: the same JSON session snapshot returned by Send Message.

Subscribe to Updates

Open a long-lived Server-Sent Events (SSE) channel for a session. Use it to react to title changes and tool progress in real time. Open it with a header-based fetch and read the stream body, since the session ID travels in a header rather than a query parameter.
GET /api/updates
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
AcceptYestext/event-stream
Response: SSE stream. Each event is a JSON object carrying type and session_id. Event Types:
TypeDescription
title_changedThe conversation title was updated (carries new_title)
tool_updateA tool reported progress
tool_completeA tool finished
system_noticeA system-level notice for the session

List Threads

List every thread bound to a wallet address.
GET /api/sessions?public_key={public_key}
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
Query Parameters:
ParameterRequiredDescription
public_keyYesWallet address
Response: an array of threads.
[
  { "session_id": "550e8400-...", "title": "ETH Trading" },
  { "session_id": "661f9511-...", "title": "Portfolio Review" }
]

Set Model

Set the model (rig) for a session.
POST /api/control/model?rig={rig}
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
AOMI-APP-KEYFor non-default AppsYour App key
Query Parameters:
ParameterRequiredDescription
rigYesModel identifier to switch to
Response:
{
  "success": true,
  "rig": "claude-sonnet",
  "baml": "...",
  "created": false
}

List Available Models

Get the models available for the current session.
GET /api/control/models
Response: an array of model identifiers.
["claude-sonnet", "gpt-4o"]

List Apps

Get the Apps available to this session, each with the secret slots it declares.
GET /api/control/apps
Headers:
HeaderRequiredDescription
X-Session-IdYesSession UUID
AOMI-APP-KEYFor non-default AppsYour App key
Response: an array of App descriptors. secrets is present only for Apps that declare slots.
[
  {
    "name": "mycoindex",
    "secrets": [
      { "name": "API_KEY", "description": "Vendor API key", "required": true }
    ]
  },
  { "name": "default" }
]

Consuming the Updates Stream in JavaScript

The updates channel ships the session ID in a header, so open it with fetch and read the response body. Do not use EventSource with a query parameter.
const response = await fetch("/api/updates", {
  headers: {
    "X-Session-Id": sessionId,
    Accept: "text/event-stream",
  },
});

const reader = response.body!.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const chunk = decoder.decode(value);
  const lines = chunk.split("\n");

  for (const line of lines) {
    if (line.startsWith("data:")) {
      const event = JSON.parse(line.slice(5).trim());

      switch (event.type) {
        case "title_changed":
          setTitle(event.new_title);
          break;
        case "tool_update":
          showToolProgress(event);
          break;
        case "tool_complete":
          markToolDone(event);
          break;
        case "system_notice":
          showNotice(event);
          break;
      }
    }
  }
}

Error Responses

Status CodeMeaning
400Bad request (missing or invalid parameters)
401Unauthorized (invalid or missing App key)
403Forbidden (App key does not authorize this App)
404Not found (session or resource does not exist)
500Internal server error

Next Steps

Last modified on June 4, 2026