Orby Assistant API
Orby is Orbit’s in-dashboard operator assistant. These endpoints power the Orby chat panel: you send a message, Orby streams back a response over Server-Sent Events (SSE), and — when a turn proposes an action that changes data (such as sending an SMS or reassigning a conversation) — it pauses for an explicit approval before running it. Orby is operator-facing. Every endpoint runs in the context of the signed-in dashboard user, scoped to that user’s organization and tenant. There is no server-to-server API-key path for Orby. Base path:/api/v1/orby
Using the SDKs
Prefer the typed client, but this page’s endpoint has no helper yet — the genericrequest() keeps auth/retries and the { data, meta } envelope identical:
client.request() escape hatch above. See the Python SDK for install.
Go, Ruby, and PHP ship the same untyped request method — call it the same way you would any untyped endpoint:
Authentication
Orby uses the dashboard user (Bearer token) method, not an API key. Send the signed-in operator’s JWT:X-API-Key or as a dv_* Bearer token — is rejected with 403 ORBY_SESSION_REQUIRED. There is no server-to-server path. When any ORBY_* code comes back, use Troubleshooting: Orby operator errors for the cause table and fix path per code.
Every Orby endpoint requires one of these operator roles: owner, admin, developer, viewer, or billing. Two knowledge-base maintenance endpoints (POST /kb/reindex and GET /kb/status) additionally require super-admin and return 403 INSUFFICIENT_PERMISSIONS otherwise.
A thread belongs to the operator who created it. You can only list, read, and post turns to your own threads — requesting another operator’s thread returns 404.
Rate limits
When you exceed the turn limit,
POST /assistant returns 429 ORBY_RATE_LIMITED with a Retry-After header (seconds).
Run a turn
POST /api/v1/orby/assistant
Start a new Orby conversation or continue an existing thread. The response is an SSE stream (Content-Type: text/event-stream), one event per token and per lifecycle step, terminated by a done event.
string
required
The operator’s message. 1–8000 characters.
string
Continue an existing thread. Omit to start a new one — the response stream reports the new
thread_id in the final response event, and the thread is auto-titled from your first message.object
Optional context describing the dashboard page the operator is on, so Orby can ground its answer. All fields are optional.
Idempotency-Key header to make a retried turn safe against double-execution of any tool it runs.
Stream events
Each SSE frame has anevent: name and a JSON data: payload. Read them in order until you receive done (success) or error (failure); the connection then closes.
When Orby pauses on a
tool_pending event, you can resume the same turn either by redeeming the pending action through the tool-actions endpoints, or by sending a follow-up turn on the same thread whose message is a plain confirm / yes / cancel. The chat reply and the explicit approve/reject button resolve through the same path, so the audit trail is identical.Consume the stream (worked example)
A turn consumer does three jobs: open the connection, dispatch each named event, and handletool_pending by holding the pending_action_id for approval or rejection. Register a listener per named event — the events listed above arrive as event: router, event: token, and so on, so a generic onmessage / message handler never sees them.
State you track while the stream runs:
text— concatenate everytokenpayload’scontentin order. Theresponseevent then reports the full assembled answer, so you never have to re-assemble it client-side.- Pending actions — on
tool_pending, store thepending_action_idwith the tool name, input, and cost estimate, then render an approve/reject control (see Redeem a pending action below). Atool_endpayload that arrives after approval reports the tool’s result. - Thread handle — hold the operator JWT in a variable; every request on this page carries it as
Authorization: Bearer.
- Node (eventsource)
- Python (sseclient)
Redeem a pending action
Ontool_pending, hold the pending_action_id and redeem it through the tool-actions endpoints. The approve call can race a second click or arrive after the 5-minute expiry window, so retry 409 responses whose error_code is PENDING_ACTION_RACE or PENDING_ACTION_EXPIRED after refreshing the action state.
/tool-actions/{id}/reject; the same pattern applies.
Poll the pending action and render the countdown
While an approval control is on screen, pollGET /tool-actions/{id} (120 requests per minute per tenant — once every few seconds is enough) and count down to expires_at. When the window elapses, disable the control: the next poll reports the action as cancelled with error_code: PENDING_ACTION_EXPIRED.
Threads
List threads
GET /api/v1/orby/threads
Return the operator’s most recent threads (up to 50, newest first) for the “Past chats” panel.
- Error envelope (bash + TypeScript + Python)
403 ORBY_SESSION_REQUIRED
Create a thread
POST /api/v1/orby/threads
Pre-allocate an empty thread before the first message (the chat panel uses this to reserve a thread id up front). You can also let POST /assistant create the thread implicitly by omitting thread_id.
string
Optional thread title (max 200 chars). Left empty, the thread is auto-titled from the first message.
object
Optional page context stored on the thread.
- Error envelope (bash + TypeScript + Python)
422 Validate — missing search text
Get thread messages
GET /api/v1/orby/threads/{id}/messages
Replay a thread’s persisted messages (oldest-first) to re-render history on reload.
string
required
Thread id.
- Error envelope (bash + TypeScript + Python)
404 THREAD_NOT_FOUND
Tool confirmations
When a turn proposes an action that changes data, Orby does not run it immediately. It emits atool_pending event carrying a pending_action_id and waits. Approve to execute, or reject to cancel. A pending action expires 5 minutes after it is created; an expired action returns 409 PENDING_ACTION_EXPIRED.
Approve an action
POST /api/v1/orby/tool-actions/{id}/approve
Execute the pending action. Returns the tool’s result once it runs.
string
required
The
pending_action_id from the tool_pending event.- Error envelope (bash + TypeScript + Python)
409 PENDING_ACTION_NOT_APPROVABLE
Reject an action
POST /api/v1/orby/tool-actions/{id}/reject
Cancel the pending action without running it.
string
required
The
pending_action_id.- Error envelope (bash + TypeScript + Python)
409 PENDING_ACTION_EXPIRED
Poll an action
GET /api/v1/orby/tool-actions/{id}
Read the current state of a pending action, including its expires_at so you can render a countdown. A pending action whose window has elapsed is reported as cancelled with error_code: PENDING_ACTION_EXPIRED.
string
required
The
pending_action_id.- Error envelope (bash + TypeScript + Python)
404 NOT_FOUND
Action states are
pending, executing, done, undone, failed, and cancelled. Only a pending action can be approved or rejected — acting on any other state returns 409 PENDING_ACTION_NOT_APPROVABLE, and a concurrent second approve returns 409 PENDING_ACTION_RACE. Both approve and reject are idempotent in effect: the action runs (or cancels) exactly once. A done action moves to undone when the operator reverses it within the tool’s undo window — for example, a sent message rolled back inside its 30-second grace period. Treat undone as a terminal state whose side effect has been undone; it differs from cancelled, which marks an action that was rejected (or expired) before it ever ran.Knowledge-base search
Orby can search the Orbit product documentation so operators can answer “where do I configure X” without leaving the dashboard. These endpoints sit under/api/v1/orby/kb.
Search docs
GET /api/v1/orby/kb/search
Hybrid search over the Orbit docs index. Available to any authenticated operator role.
string
required
Search text. 1–500 characters.
integer
default:"10"
Results to return (max 50).
string
Restrict to a docs section.
string
Restrict to a docs category.
- Error envelope (bash + TypeScript + Python)
422 VALIDATION_ERROR
Find a setting
POST /api/v1/orby/kb/find-setting
Map a plain-language description to the dashboard route where the setting lives. Available to any authenticated operator role.
string
required
What the operator wants to configure. 1–500 characters.
integer
default:"10"
Matches to return (max 20).
- Error envelope (bash + TypeScript + Python)
422 VALIDATION_ERROR
Reindex and status (super-admin)
POST /api/v1/orby/kb/reindex triggers a rebuild of the docs index and returns immediately with { "scheduled": true } (or { "ran_inline": true } when the corpus is available in-process). GET /api/v1/orby/kb/status returns a health snapshot: total and stale chunk counts, the last run timestamp, the current version, and cache hit rate. Both require the super-admin role and return 403 INSUFFICIENT_PERMISSIONS otherwise.
- Error envelope (bash + TypeScript + Python)
403 INSUFFICIENT_PERMISSIONS