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:
| Header | Description |
|---|
X-Session-Id | UUID identifying the conversation session |
AOMI-APP-KEY | Your Aomi App key (required for non-default Apps) |
Endpoints
Create Session
Create a new chat session.
Headers:
| Header | Required | Value |
|---|
X-Session-Id | Yes | UUID 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.
Path Parameters:
| Parameter | Type | Description |
|---|
id | string | Session 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:
| Parameter | Required | Description |
|---|
message | Yes | The user message text |
app | No | Target App (defaults to default) |
public_key | No | Wallet address to bind the session to |
user_state | No | JSON-encoded user state (wallet, chain, connection) |
client_id | No | Client identifier for scoped secrets |
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
AOMI-APP-KEY | For non-default Apps | Your 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
}
| Field | Type | Description |
|---|
messages | array | Conversation messages so far |
system_events | array | System events for the session |
title | string | Conversation title |
is_processing | boolean | Whether the assistant is still working |
user_state | object | Synced 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.
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
Query Parameters:
| Parameter | Required | Description |
|---|
user_state | No | JSON-encoded user state to reconcile |
client_id | No | Client 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.
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session 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.
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
Accept | Yes | text/event-stream |
Response: SSE stream. Each event is a JSON object carrying type and session_id.
Event Types:
| Type | Description |
|---|
title_changed | The conversation title was updated (carries new_title) |
tool_update | A tool reported progress |
tool_complete | A tool finished |
system_notice | A system-level notice for the session |
List Threads
List every thread bound to a wallet address.
GET /api/sessions?public_key={public_key}
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
Query Parameters:
| Parameter | Required | Description |
|---|
public_key | Yes | Wallet 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:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
AOMI-APP-KEY | For non-default Apps | Your App key |
Query Parameters:
| Parameter | Required | Description |
|---|
rig | Yes | Model identifier to switch to |
Response:
{
"success": true,
"rig": "claude-sonnet",
"baml": "...",
"created": false
}
List Available Models
Get the models available for the current session.
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.
Headers:
| Header | Required | Description |
|---|
X-Session-Id | Yes | Session UUID |
AOMI-APP-KEY | For non-default Apps | Your 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 Code | Meaning |
|---|
400 | Bad request (missing or invalid parameters) |
401 | Unauthorized (invalid or missing App key) |
403 | Forbidden (App key does not authorize this App) |
404 | Not found (session or resource does not exist) |
500 | Internal server error |
Next Steps
Last modified on June 4, 2026