Botovis

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

EventDescription
stepAn agent reasoning/tool-use step
messageThe final text response (streamed token-by-token)
tokenA single token during streaming
confirmationA write operation awaiting user approval
doneStream complete
errorAn 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:

  1. The XSRF-TOKEN cookie (set by Laravel's web middleware)
  2. 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.

On this page