AI Chat API¶
Conversational AI chat with streaming responses, conversation history, and real-time voice support.
Base URL: https://api.vell.ai/api/v1
Authentication: Bearer token
Prefix: /aichat (standard) or /airealtimechat (real-time with WebSocket)
Endpoints¶
Send Message (Streaming)¶
Two-phase endpoint: POST creates the message, then GET streams the AI response via Server-Sent Events.
Phase 1: Create Message¶
Request Body:
| Parameter | Type | Required | Description |
|---|---|---|---|
conver_id |
integer | Yes | Conversation ID (from new-chat) |
prompt |
string | Yes | User message text |
Response:
Phase 2: Stream AI Response¶
Response: text/event-stream (SSE)
Tokens are streamed incrementally. The stream terminates with data: [DONE].
import requests
# Phase 1: Create message
resp = requests.post(
"https://api.vell.ai/api/v1/aichat/chat-send",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"conver_id": 31, "prompt": "Explain cloud cost optimization"},
)
data = resp.json()
# Phase 2: Stream response
stream = requests.get(
"https://api.vell.ai/api/v1/aichat/chat-send",
headers={"Authorization": "Bearer YOUR_API_KEY"},
params={"conver_id": data["conver_id"], "message_id": data["message_id"]},
stream=True,
)
for line in stream.iter_lines():
text = line.decode()
if text.startswith("data: ") and text != "data: [DONE]":
print(text[6:], end="")
// Phase 1: Create message
const create = await fetch("https://api.vell.ai/api/v1/aichat/chat-send", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ conver_id: 31, prompt: "Explain cloud cost optimization" }),
});
const { conver_id, message_id } = await create.json();
// Phase 2: Stream response
const stream = await fetch(
`https://api.vell.ai/api/v1/aichat/chat-send?conver_id=${conver_id}&message_id=${message_id}`,
{ headers: { Authorization: "Bearer YOUR_API_KEY" } }
);
const reader = stream.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
process.stdout.write(decoder.decode(value));
}
Error Responses:
| Status | Code | Description |
|---|---|---|
| 412 | PRECONDITION_FAILED |
Missing conver_id or prompt |
| 419 | NO_CREDITS |
Insufficient credit balance |
Start New Chat¶
Request Body:
| Parameter | Type | Required | Description |
|---|---|---|---|
category_id |
integer | Yes | Chat category ID (determines the AI persona) |
Response:
{
"id": 42,
"user_id": 1,
"openai_chat_category_id": 5,
"title": "AI Chat Bot Chat",
"total_credits": 0,
"total_words": 0,
"created_at": "2026-02-26T10:00:00Z",
"updated_at": "2026-02-26T10:00:00Z"
}
Get Chat History¶
| Parameter | Type | Location | Description |
|---|---|---|---|
cat_slug |
string | path | Category slug (e.g., general-assistant) |
Response:
{
"category": {
"id": 5,
"name": "General Assistant",
"slug": "general-assistant"
},
"conversations": [
{
"id": 42,
"title": "Cloud Cost Optimization",
"updated_at": "2026-02-26T10:30:00Z"
}
]
}
Get Conversation Messages¶
| Parameter | Type | Location | Default | Description |
|---|---|---|---|---|
conver_id |
integer | path | — | Conversation ID |
page |
integer | query | 1 |
Page number |
per_page |
integer | query | 10 |
Messages per page |
Response: Paginated list of messages with standard Laravel pagination metadata.
Recent Chats¶
Returns the 20 most recent conversations, ordered by last update.
Rename Chat¶
| Parameter | Type | Required | Description |
|---|---|---|---|
conver_id |
integer | Yes | Conversation ID |
title |
string | Yes | New title |
Delete Chat¶
| Parameter | Type | Required | Description |
|---|---|---|---|
conver_id |
integer | Yes | Conversation ID to delete |
Search Chat History¶
| Parameter | Type | Required | Description |
|---|---|---|---|
category_id |
integer | Yes | Category to search within |
search_word |
string | Yes | Search keyword (matches titles) |
Real-Time Chat (WebSocket)¶
The real-time chat API mirrors all standard chat endpoints under /airealtimechat/ and adds WebSocket support for voice conversations.
Get WebSocket Credentials¶
Response:
{
"key1": "base64EncodedPart1",
"key2": "base64EncodedPart2",
"key3": "base64EncodedPart3",
"model": "gpt-4o-realtime-preview-2024-12-17"
}
Reconstructing the API key
Decode and concatenate key1 + key2 + key3 to get the full WebSocket API key.
Save Voice Conversation¶
| Parameter | Type | Required | Description |
|---|---|---|---|
userMessage |
string | Yes | User's spoken message (transcribed) |
aiResponse |
string | Yes | AI's response text |
chatId |
integer | No | Existing conversation ID to append to |
Use Cases¶
Build a Chat Widget¶
- Call
POST /aichat/new-chatwith a category to start a session - Use the two-phase
chat-sendflow to send messages and stream responses - Display streamed tokens in real-time for a typing effect
- Use
GET /aichat/recent-chatsto show conversation history in a sidebar
Integrate Voice Chat¶
- Get WebSocket credentials via
GET /airealtimechat/websocket-credentials - Connect to OpenAI's real-time API with the reconstructed key
- After each voice exchange, persist with
POST /airealtimechat/save-conversation - Browse past voice chats via
GET /airealtimechat/history/{slug}
Search Across Conversations¶
- Use
POST /aichat/search-historyto find conversations by keyword within a category - Use
POST /aichat/search-recent-chatsfor a global search across all recent conversations