The API channel is a REST API for talking to your AI agents over HTTPS: create a conversation, send one message at a time, and receive the agent's reply synchronously or as a server-sent event stream. Authentication requires an API key, created in Dashboard → Settings → API Keys, sent as Authorization: Bearer be_xxxx. Conversation history is managed server-side, so each request carries only the new message.

API Channel Reference

Download OpenAPI spec (OpenAPI 3.1)

Overview

The API channel lets external systems converse with a company agent over HTTP. The agent behaves exactly as it does on the call, chat, and email channels: same configuration, same system prompt, and its tools execute on the server as part of handling each request.

The API is stateful: conversation history is maintained on the platform. Each request carries only the new message and a conversation ID — the server reconstructs the full context, runs the agent, and returns the reply. Do not include previous messages in requests; history is managed for you.

  • Base URL: https://ai.binaryelements.com
  • All bodies are JSON (Content-Type: application/json).
  • All timestamps are ISO 8601.

Authentication

Every request needs a per-company API key, created in Dashboard → Settings → API Keys. The raw key is shown exactly once at creation; only its SHA-256 hash is stored. Keys can be revoked at any time and revocation takes effect on the next request (no caching).

Authorization: Bearer be_xxxx

The key identifies your company server-side — you never pass a companyId. Requests for agents or conversations belonging to another company fail with 404/403.

Getting your API key

  1. Sign in to the dashboard with your company account.
  2. Go to Settings → API Keys.
  3. Click Create API Key, give the key a name (e.g. "Production integration"), and copy the key immediately — it is shown only once. Only a SHA-256 hash is stored server-side, so it cannot be recovered later.
  4. Pass it on every request as Authorization: Bearer be_xxxx.
  5. Keys can be revoked at any time from the same page; revocation is immediate — any integration using a revoked key stops working on its next request.

Treat API keys like passwords: store them in a secrets manager, never commit them to source control, and create separate keys per integration so you can revoke them independently.

Quickstart

BASE="https://ai.binaryelements.com"
KEY="be_xxxx"   # from Dashboard → Settings → API Keys

# 1. Start a conversation
CONV=$(curl -s -X POST "$BASE/api/v1/conversations" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"agentId":"9f2b6c1e-1111-4111-8111-111111111111"}' | jq -r .conversationId)

# 2. Send a message (single message only — the server holds the history)
curl -s -X POST "$BASE/api/v1/conversations/$CONV/messages" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"message":"Hi, where is my order 42?"}' | jq .

# 3. Continue the conversation — send only the new message
curl -s -X POST "$BASE/api/v1/conversations/$CONV/messages" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"message":"And when will it arrive?"}' | jq .

# 4. Fetch the conversation + history
curl -s "$BASE/api/v1/conversations/$CONV" -H "Authorization: Bearer $KEY" | jq .

# 5. End the conversation
curl -s -X POST "$BASE/api/v1/conversations/$CONV/end" -H "Authorization: Bearer $KEY" | jq .

Create a conversation

POST/api/v1/conversations
FieldTypeRequiredNotes
agentIdstring (UUID)yesMust belong to your company
customSystemMessagestring (1–8000)noApplied to every turn of this conversation; additive to the agent's configured prompt
metadataobjectnoStructured context the agent sees on every turn (see below)

Response 201:

{
  "conversationId": "a1b2c3d4-…",
  "agentId": "9f2b6c1e-…",
  "createdAt": "2026-06-12T08:00:00.000Z"
}

Conversation metadata

Any metadata object you supply is injected into the agent's context as a system message on every turn, so the model can personalise replies and pull values (IDs, account tier, cart state…) straight into tool calls instead of asking the user:

CONVERSATION METADATA:
{
  "username": "john_doe",
  "accountId": "ACC-12345",
  "accountTier": "premium"
}

Keep it reasonably small (≈2 KB) — it is re-sent on every turn. Use PATCH /api/v1/conversations/:id/metadata to update it as your app's state changes.

Send a message

POST/api/v1/conversations/:conversationId/messages
FieldTypeRequiredNotes
messagestring (1–32000)yesThe user's new message — only the new message
customSystemMessagestring (1–8000)noAdded for this turn only, on top of the conversation-level one
customToolsarray (max 10)noExtra tools for this turn, additive to the agent's configured tools (see Custom tools)
streambooleannotrue switches to SSE; default synchronous

Synchronous response 200 (returned after all tool calls have run server-side):

{
  "conversationId": "a1b2c3d4-…",
  "message": { "role": "assistant", "content": "Order 42 shipped yesterday…" },
  "messages": [{ "role": "assistant", "content": "Order 42 shipped yesterday…" }],
  "toolCalls": ["custom_a1b2c3d4-…_lookup_order"],
  "usage": { "promptTokens": 512, "completionTokens": 64, "totalTokens": 576 }
}
  • message.content is the full reply (multiple assistant messages from tool-call continuations are joined with blank lines); messages lists them individually.
  • toolCalls contains the names of tools the agent invoked this turn.

Streaming ("stream": true)

The response is text/event-stream; each event is a data: <json> line:

EventPayloadMeaning
content{ "type": "content", "content": "…" }A chunk of assistant text
new_message{ "type": "new_message" }A new assistant message starts (after a tool run)
tool{ "type": "tool", "name": "…" }The agent is executing a tool (server-side)
done{ "type": "done", "conversationId": "…", "usage": { … } }Turn complete
error{ "type": "error", "error": "…" }An error occurred; the stream ends

Custom tools

Server-executable HTTP tool definitions (the same shape as platform API tools). The server — never your client — calls url with the parameters the LLM chooses:

FieldTypeRequiredNotes
namestring (≤ 20, [a-zA-Z0-9_-])yesExposed to the agent as custom_<conversationId>_<name>
descriptionstring (≤ 1024)yesTells the agent when to use the tool
urlstringyeshttps:// only. Supports {param} path placeholders
methodGET / POST / PUT / DELETEyesGET sends params as query string; POST/PUT as JSON body
authTypenone / basic / apikey / bearerno (default none)How the server authenticates to YOUR endpoint
authConfigobjectno{ username, password } / { headerName, apiKey } / { token } — held in memory for the request only, never persisted or logged
parametersarray (max 20)no{ name (≤64), type, required, description (≤512) }

Update conversation metadata

PATCH/api/v1/conversations/:conversationId/metadata

Replace the conversation's metadata (and, optionally, its conversation-level customSystemMessage). The new metadata fully replaces the previous metadata and is used on every subsequent turn. No AI response is generated.

FieldTypeRequiredNotes
metadataobjectyesReplaces the stored metadata wholesale
customSystemMessagestring (1–8000)noWhen present, replaces the conversation-level custom system message; left untouched when omitted

Response 200:

{
  "conversationId": "a1b2c3d4-…",
  "metadata": { "accountTier": "enterprise", "upgradeDate": "2026-06-22" },
  "updatedAt": "2026-06-12T08:30:00.000Z"
}

Returns 409 if the conversation has ended.

Add a manual message

POST/api/v1/conversations/:conversationId/manual

Append a message from a human operator or external system without triggering an AI response. It is stored as an admin turn, becomes part of the history, and is replayed into the agent's context on the next message (the model sees [ADMIN MESSAGE - <username>] …). No AI credits are consumed.

FieldTypeRequiredNotes
messagestring (1–32000)yesThe note to add
usernamestring (1–120)noWho added it; defaults to admin when blank or omitted
metadataobjectnoStored alongside the message (e.g. department, ticketId)

Response 201:

{
  "conversationId": "a1b2c3d4-…",
  "messageId": "f0e1d2c3-…",
  "addedBy": "Martin",
  "timestamp": "2026-06-12T08:05:00.000Z"
}

Returns 409 if the conversation has ended.

Get a conversation + history

GET/api/v1/conversations/:conversationId
GET/api/v1/conversations/:conversationId?include=all

Response 200:

{
  "conversationId": "a1b2c3d4-…",
  "agentId": "9f2b6c1e-…",
  "status": "active",
  "createdAt": "2026-06-12T08:00:00.000Z",
  "messages": [
    { "role": "user", "content": "Where is my order 42?", "timestamp": "…" },
    { "role": "assistant", "content": "Order 42 shipped yesterday…", "timestamp": "…" },
    { "role": "admin", "content": "Refund approved manually.", "timestamp": "…", "metadata": { "username": "Martin", "source": "manual" } }
  ]
}

messages contains user/assistant turns plus any admin (manual) messages by default; admin entries include a metadata object with username and source. ?include=all additionally adds system/tool entries.

End a conversation

POST/api/v1/conversations/:conversationId/end

Response 200: { "conversationId": "…", "status": "ended" }. Transcripts are retained and remain retrievable; further messages to the conversation return 409.

Errors

StatusWhen
400Invalid body (details in details), e.g. non-https custom tool URL
401Missing, malformed, unknown, or revoked API key
402Company has insufficient AI credits (minCredits / totalBalance included)
403Conversation exists but belongs to a different company
404Unknown conversation/agent, or the session is not an API-channel session
409Conversation has ended / has no agent assigned / agent no longer available
500Unexpected processing failure
504Agent turn exceeded the 120 s timeout

Error shape: { "error": "<message>" } (plus details for validation errors).

Behaviour notes

  • Agent config is intact. The agent's configured system prompt, model, and tools all apply. Custom system messages and custom tools are strictly additive — they can never replace or bypass the agent's configuration.
  • Channel-inapplicable tools are excluded: end_call, barge_in, handoff_to_agent, call_internal_contact, end_session are never offered on this channel even if configured on the agent.
  • Billing: each turn consumes AI credits under the api reference type (same minimum-credit setting as chat). PAYG companies are billed by invoice and are not credit-blocked.
  • Sessions are stored with channel='api' and are not shown in the dashboard chat views in v1.
  • Timeout: synchronous turns are capped at 120 s (long tool chains should use stream: true).