API Reference
Complete HTTP and SSE streaming API reference for Botovis endpoints
All Botovis endpoints are prefixed with the configured route prefix (default: /botovis). All routes use the configured middleware (default: ['web', 'auth']).
Authentication
All endpoints require authentication. The widget automatically includes the CSRF token from your Laravel session. For programmatic access, include:
X-CSRF-TOKEN: {csrf_token}
Cookie: {session_cookie}Or use the X-Requested-With: XMLHttpRequest header with your session cookie.
Chat Endpoints
POST /chat
Send a message and receive the complete response (non-streaming).
Request:
{
"message": "How many active users do we have?"
}Response:
{
"message": "You have 1,247 active users.",
"steps": [
{
"step": 1,
"thought": "I need to count active users",
"action": "count_records",
"observation": "Count: 1247"
}
],
"needs_confirmation": false
}POST /stream
Send a message with SSE (Server-Sent Events) streaming. This is the primary endpoint used by the widget.
Request:
{
"message": "Show me the top 5 customers by revenue"
}Response: SSE event stream with the following event types:
SSE Event Types
| Event | Description |
|---|---|
step | An agent reasoning/tool-use step |
message | The final text response (streamed token-by-token) |
token | A single token during streaming |
confirmation | A write operation awaiting user approval |
done | Stream complete |
error | An error occurred |
Step Event
event: step
data: {"step":1,"thought":"I'll search for customers ordered by total revenue","action":"aggregate","observation":"Results: [{\"customer\":\"Acme Corp\",\"total\":52400}...]"}Token Event
event: token
data: {"content":"Based"}
event: token
data: {"content":" on"}
event: token
data: {"content":" the"}Message Event
event: message
data: {"content":"Based on the data, your top 5 customers by revenue are:\n\n1. **Acme Corp** — $52,400\n2. ..."}Confirmation Event
event: confirmation
data: {"tool_call_id":"call_abc123","tool":"create_record","params":{"table":"products","data":{"name":"New Widget","price":29.99}}}Done Event
event: done
data: {}Error Event
event: error
data: {"message":"An error occurred while processing your request"}Confirmation Endpoints
POST /confirm
Confirm a pending write operation (non-streaming).
Request:
{
"tool_call_id": "call_abc123"
}Response:
{
"message": "Done! I created the product 'New Widget' with a price of $29.99.",
"steps": [...]
}POST /stream-confirm
Confirm a pending write operation with SSE streaming. The agent executes the confirmed tool, then may continue reasoning and streaming its response.
Request:
{
"tool_call_id": "call_abc123"
}Response: Same SSE event stream format as /stream.
POST /reject
Reject a pending write operation.
Request:
{
"tool_call_id": "call_abc123"
}Response:
{
"message": "Understood, I've cancelled the operation."
}Utility Endpoints
POST /reset
Reset the current conversation state. Clears the in-memory conversation context.
Request: Empty body.
Response:
{
"message": "Conversation reset."
}GET /schema
Returns the database schema visible to the current user (filtered by permissions).
Response:
{
"tables": [
{
"name": "products",
"label": "Products",
"columns": [
{ "name": "id", "type": "integer", "nullable": false },
{ "name": "name", "type": "string", "nullable": false, "max_length": 255 },
{ "name": "price", "type": "decimal", "nullable": false },
{ "name": "category_id", "type": "integer", "nullable": true }
],
"relations": [
{ "name": "category", "type": "belongsTo", "related_table": "categories" }
]
}
]
}GET /status
Health check endpoint. Returns the current configuration status.
Response:
{
"status": "ok",
"mode": "agent",
"driver": "openai",
"model": "gpt-4o",
"streaming": true,
"models_count": 12,
"conversations_enabled": true
}Conversation Endpoints
These endpoints manage persistent conversation history.
GET /conversations
List the authenticated user's saved conversations.
Response:
{
"conversations": [
{
"id": "uuid-123",
"title": "Revenue analysis",
"message_count": 8,
"created_at": "2025-02-19T10:30:00Z",
"updated_at": "2025-02-19T10:45:00Z"
}
]
}POST /conversations
Save the current conversation to persistent storage.
Request:
{
"title": "Revenue analysis Q1"
}Response:
{
"id": "uuid-456",
"title": "Revenue analysis Q1",
"message_count": 8,
"created_at": "2025-02-19T10:30:00Z"
}GET /conversations/{id}
Load a specific conversation and restore it as the active conversation.
Response:
{
"id": "uuid-123",
"title": "Revenue analysis",
"messages": [
{ "role": "user", "content": "Show me Q1 revenue" },
{ "role": "assistant", "content": "Based on the data..." }
],
"created_at": "2025-02-19T10:30:00Z"
}DELETE /conversations/{id}
Delete a saved conversation.
Response:
{
"message": "Conversation deleted."
}PATCH /conversations/{id}/title
Update a conversation's title.
Request:
{
"title": "Q1 Revenue Analysis 2025"
}Response:
{
"id": "uuid-123",
"title": "Q1 Revenue Analysis 2025"
}Error Responses
All endpoints return consistent error responses:
401 Unauthorized
{
"error": "Unauthenticated."
}403 Forbidden
{
"error": "You do not have permission to perform this action."
}404 Not Found
{
"error": "Conversation not found."
}422 Validation Error
{
"error": "The message field is required.",
"errors": {
"message": ["The message field is required."]
}
}500 Server Error
{
"error": "An internal error occurred while processing your request."
}CSRF Token Handling
The widget automatically reads the CSRF token from:
- The
XSRF-TOKENcookie (set by Laravel'swebmiddleware) - A
<meta name="csrf-token">tag in the HTML head
For programmatic API usage, include the token in the X-CSRF-TOKEN header:
fetch('/botovis/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json',
},
body: JSON.stringify({ message: 'Hello' }),
});API-only Usage
If you're building a custom frontend or using Botovis headless (without the widget), you can use these endpoints directly. Just ensure proper authentication and CSRF handling.