Introduction

Everything you need to make your first request to the Xpectrum API.

Base URL

text
https://cloud.xpectrum.dev/v1

All endpoints in these docs are relative to this base URL. The chat endpoints are OpenAI-compatible, so any OpenAI SDK works by pointing its base_url here.

Authentication

Every request is authenticated with a Bearer token in the Authorization header:

text
Authorization: Bearer xpectrum_XXXXXXXXXXXXXXXX
  • App API key (xpectrum_...) — scoped to a single agent. Used by every endpoint. Create one in the Xpectrum console under your app's API Access page.

Where to keep your key

By default, treat an API key like a password: call this API from your backend and keep the key out of client code. The exception is the chat and voice widgets, which run in the browser by design — before using a key there, limit what it can do in the app's publish settings: switch Conversation history over API off (and Voice calls off where unused). A key restricted this way can hold a conversation but cannot read any transcripts, so exposing it in a widget is safe.

The user identifier

Most endpoints accept a user field — a stable identifier you choose for your end user (for example your own user ID). Conversations (threads) are stored per user, so passing the same value on every request is what makes history and multi-turn memory line up. Chat endpoints take it in the JSON body; thread listing takes it as a query parameter.

How to pick the value:

  • Your app has login — use the logged-in user's id from your own system. Their conversation history follows them across devices.
  • No login (anonymous visitors) — generate a random id once per browser and reuse it (e.g. store it in localStorage). Each visitor then has their own private history, and nobody can see anyone else's conversations.

Quick start

Send your first message with curl:

bash
curl https://cloud.xpectrum.dev/v1/chat/completions \
  -H "Authorization: Bearer xpectrum_XXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{ "role": "user", "content": "Hello!" }],
    "stream": true,
    "user": "user-123"
  }'

The reply streams back as SSE chunks. Streaming works for every app type — Autonomous Agent apps reject non-streaming requests — so it is the right default for a first call.

Or use the official OpenAI SDK — only the base URL and key change:

quickstart.py
from openai import OpenAI

client = OpenAI(
    base_url="https://cloud.xpectrum.dev/v1",
    api_key="xpectrum_XXXXXXXXXXXXXXXX",
)

stream = client.chat.completions.create(
    model="my-app",  # any string; the key already selects the app
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")
quickstart.ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://cloud.xpectrum.dev/v1",
  apiKey: "xpectrum_XXXXXXXXXXXXXXXX",
});

const response = await client.chat.completions.create({
  model: "my-app",
  messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);

Or use the Xpectrum SDK, which speaks this API natively and handles streaming and conversation state for you:

bash
npm install xpectrum
quickstart-sdk.ts
import { XpectrumChat } from "xpectrum";

const chat = new XpectrumChat({
  baseUrl: "https://cloud.xpectrum.dev/v1",
  apiKey: "xpectrum_XXXXXXXXXXXXXXXX",
  user: "user-123",
});

const res = await chat.send("Hello!");
console.log(res.content);

Building a web UI?

The JavaScript Guide walks through both setups step by step — calling the API from the browser only, and the client + server pattern that keeps your key secret — plus how to style your chat UI (fonts, colors, branding).

Endpoints at a glance

MethodEndpointPurpose
POST/chat/completionsTalk to an AI Chatbot, Autonomous Agent, or Agent Flow app (OpenAI-compatible)
GET/modelsThe agent behind your API key — name, greeting, starter questions (OpenAI-compatible)
GET/threadsList a user's threads
GET/threads/{thread_id}/messagesFetch one thread's transcript
GET/messages/{message_id}/suggestionsFollow-up questions for a reply
POST/voice/tokens/generateStart a voice call — exchanges the API key for a LiveKit room token
POST/voice/call-control/end-callEnd an active voice call
POST/runsExecute a Workflow app
POST/runs/{run_id}/cancelStop an in-flight generation or run

App modes

An API key belongs to one app, and the app's type decides which endpoints work: AI Chatbot, Autonomous Agent, and Agent Flow apps use the chat and thread endpoints; Workflow apps use /runs. Calling the wrong one returns a 404 with code model_not_found.