documentation
06 api reference

Chat completions

The /api/v1/chat/completions endpoint speaks the OpenAI shape, so most existing OpenAI client libraries work against an Exolvra bot by just changing base_url and api_key.

POST /api/v1/chat/completions

Accepts the standard OpenAI request body; returns the standard OpenAI response body with an additional exolvra extension object for bot-specific metadata.

Request body

FieldTypeRequiredNotes
modelstringnoIgnored in favour of the bot’s configured model. Send "exolvra-bot" as a placeholder.
messagesarrayyesOnly role: "user" messages are used; assistant and system messages from prior turns are ignored (the server reconstructs history from the session).
streamboolnoDefault false. When true, responses are streamed as Server-Sent Events in the OpenAI chat.completion.chunk format.
userstringnoStrongly recommended. Stable identifier for the end-user conversation — used to thread multi-turn history into the same Exolvra session. Clients that don’t send this get a fresh session per request.

Example — non-streaming

curl -X POST https://your-exolvra.example/api/v1/chat/completions \
  -H "Authorization: Bearer exo_a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "exolvra-bot",
    "messages": [
      {"role": "user", "content": "How do I reset my password?"}
    ],
    "user": "end-user-42",
    "stream": false
  }'

Response

{
  "id": "chatcmpl-abc123...",
  "object": "chat.completion",
  "created": 1712700000,
  "model": "claude-sonnet-4-6",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "To reset your password, go to Settings → Security → Reset Password..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 150,
    "completion_tokens": 85,
    "total_tokens": 235
  },
  "exolvra": {
    "bot_id": "support-bot-abc123",
    "session_id": "sess_xyz",
    "cost_usd": 0.0032,
    "conversation_starters": [
      "How do I reset my password?",
      "Where is my billing history?"
    ]
  }
}

The exolvra.conversation_starters field is only populated on the first turn of a session — subsequent turns return an empty array so your client can stop rendering the chip row.

Streaming

curl -N -X POST https://your-exolvra.example/api/v1/chat/completions \
  -H "Authorization: Bearer exo_..." \
  -H "Content-Type: application/json" \
  -d '{"model":"exolvra-bot","messages":[{"role":"user","content":"Hello"}],"stream":true}'

The server responds with SSE chunks matching chat.completion.chunk, terminated by data: [DONE].

GET /api/v1/bots/me

Returns metadata for the bot the calling API key is bound to. The embeddable widget calls this on load to render the header and starter chips.

curl https://your-exolvra.example/api/v1/bots/me \
  -H "Authorization: Bearer exo_..."

Response:

{
  "id": "support-bot-abc123",
  "name": "Support Assistant",
  "description": "Friendly customer support bot",
  "icon": "🛠",
  "conversationStarters": [
    "How do I reset my password?",
    "I'm having trouble logging in"
  ],
  "hasKnowledge": true,
  "model": "claude-sonnet-4-6"
}

hasKnowledge indicates whether the bot has a RAG-backed document collection attached.

Sessions

GET /api/v1/sessions

Lists sessions started by this API key. Useful for building a “recent conversations” UI on a customer dashboard.

curl https://your-exolvra.example/api/v1/sessions \
  -H "Authorization: Bearer exo_..."
{
  "sessions": [
    {
      "id": "sess_abc",
      "channelId": "bot-api:key-id:end-user-42",
      "createdAt": "2026-04-10T14:32:00Z",
      "lastActivityAt": "2026-04-10T14:35:21Z"
    }
  ]
}

Sessions are filtered to only those owned by the calling key — keys cannot see each other’s conversations.

GET /api/v1/sessions/{id}

Fetch a specific session by id. Returns 404 if the session doesn’t exist or belongs to a different key.

DELETE /api/v1/sessions/{id}

Terminate a session. Useful when a customer wants to “start over” — the next message with the same user field will land in a fresh session.

Using OpenAI SDKs

Python

from openai import OpenAI

client = OpenAI(
    api_key="exo_a1b2c3d4e5f6...",
    base_url="https://your-exolvra.example/api/v1",
)

response = client.chat.completions.create(
    model="exolvra-bot",
    messages=[{"role": "user", "content": "How do I reset my password?"}],
    user="end-user-42",
)
print(response.choices[0].message.content)

TypeScript

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "exo_a1b2c3d4e5f6...",
  baseURL: "https://your-exolvra.example/api/v1",
});

const response = await client.chat.completions.create({
  model: "exolvra-bot",
  messages: [{ role: "user", content: "How do I reset my password?" }],
  user: "end-user-42",
});
console.log(response.choices[0].message.content);

Vercel AI SDK

import { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";

const exolvra = createOpenAI({
  apiKey: process.env.EXOLVRA_KEY!,
  baseURL: "https://your-exolvra.example/api/v1",
});

const { text } = await generateText({
  model: exolvra("exolvra-bot"),
  prompt: "How do I reset my password?",
});

LangChain (Python)

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="exolvra-bot",
    openai_api_key="exo_...",
    openai_api_base="https://your-exolvra.example/api/v1",
)
result = llm.invoke("How do I reset my password?")
print(result.content)