Ask API
The Ask API allows you to send questions to your chatbot and receive streaming responses. This endpoint supports real-time interaction with your database through natural language queries.
Endpoint
POST /api/ask
Authentication
Requires API Key authentication. See API Authentication for details.
Request Format
Headers
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
Request Body
Parameter | Type | Required | Description |
---|---|---|---|
question | string | ✅ | The natural language question to ask |
botid | string | ✅ | Your chatbot ID |
chatid | string | ✅ | The chat session ID |
debug | boolean | ❌ | Enable debug mode (default: false) |
properties | object | ❌ | Custom properties for the chat session |
config | object | ❌ | Configuration overrides |
databaseConfig | object | ❌ | Dynamic database configuration |
fileUrls | string[] | ❌ | URLs of files to analyze |
Example Request
curl -X POST https://your-domain.com/api/ask \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_api_key_here" \
-d '{
"question": "Show me total sales by month for the last year",
"botid": "bot_123456",
"chatid": "chat_789012",
"debug": true,
"properties": {
"user_id": "user_123",
"department": "sales"
}
}'
Response Format
The API returns a Server-Sent Events (SSE) stream with Content-Type: text/event-stream
. Each event is formatted as:
data: {"event_type": "value", ...additional_fields}
Event Types
1. Text Content Events
Event Type: isText: true
Streams the AI's text response in real-time.
{
"isText": true,
"content": "Based on your sales data, here are the monthly totals..."
}
2. SQL Execution Events
Event Type: isSQL: true
Shows the generated SQL query and its results (when debug mode is enabled).
{
"id": "executeSQL_1234567890",
"isSQL": true,
"sql": "SELECT DATE_TRUNC('month', order_date) as month, SUM(total_amount) as total_sales FROM orders WHERE order_date >= CURRENT_DATE - INTERVAL '1 year' GROUP BY month ORDER BY month",
"result": {
"result": [
{"month": "2024-01-01", "total_sales": 125000},
{"month": "2024-02-01", "total_sales": 138000}
],
"viewLink": "https://your-domain.com/api/data-response?hashid=abc123"
}
}
3. Function Execution Status Events
Event Type: isExecutionStatus: true
Indicates when functions (SQL execution, Python code, etc.) start and complete.
Function Started
{
"isExecutionStatus": true,
"status": "started",
"functionName": "executeSQL",
"id": "executeSQL_1234567890"
}
Function Completed
{
"isExecutionStatus": true,
"status": "completed",
"functionName": "executeSQL",
"id": "executeSQL_1234567890"
}
4. Image Generation Events
Event Type: isImage: true
When Python code generates charts or visualizations.
{
"isImage": true,
"url": "https://your-domain.com/api/generated-image/chart_abc123.png"
}
5. Thinking Events (Claude Models)
Event Type: isThinking: true
Shows the AI's reasoning process (when thinking mode is enabled).
{
"isThinking": true,
"content": "I need to analyze the sales data by grouping it by month..."
}
6. Reasoning Events (DeepSeek-R1)
Event Type: Function execution with functionName: "Reasoning"
Shows the model's internal reasoning process.
{
"isExecutionStatus": true,
"status": "started",
"functionName": "Reasoning"
}
Error Handling
Authentication Errors
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "Authentication failed"
}
Validation Errors
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "chatid is required in API mode"
}
Stream Errors
Error messages are sent as text events within the stream:
{
"isText": true,
"content": "An error occurred: Database connection failed. Please try again later."
}
JavaScript Example
const response = await fetch('/api/ask', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your_api_key_here'
},
body: JSON.stringify({
question: 'Show me top 10 customers by revenue',
botid: 'bot_123456',
chatid: 'chat_789012',
debug: true
})
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
try {
const data = JSON.parse(line.slice(6));
if (data.isText) {
console.log('AI Response:', data.content);
} else if (data.isSQL) {
console.log('SQL Query:', data.sql);
console.log('Results:', data.result);
} else if (data.isExecutionStatus) {
console.log(`Function ${data.functionName} ${data.status}`);
}
} catch (e) {
console.error('Failed to parse SSE data:', e);
}
}
}
}
Python Example
import requests
import json
url = "https://your-domain.com/api/ask"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer your_api_key_here"
}
data = {
"question": "What are our top selling products?",
"botid": "bot_123456",
"chatid": "chat_789012",
"debug": True
}
response = requests.post(url, headers=headers, json=data, stream=True)
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('data: '):
try:
event_data = json.loads(line[6:])
if event_data.get('isText'):
print(f"AI: {event_data['content']}")
elif event_data.get('isSQL'):
print(f"SQL: {event_data['sql']}")
print(f"Results: {event_data['result']}")
elif event_data.get('isExecutionStatus'):
status = event_data['status']
func_name = event_data['functionName']
print(f"Function {func_name} {status}")
except json.JSONDecodeError:
print(f"Failed to parse: {line}")
Rate Limits
- API requests are subject to your subscription plan's quotas
- Streaming responses may take 30-300 seconds depending on query complexity
- Maximum concurrent streams: 5 per API key
Best Practices
- Handle Stream Interruption: Always implement proper error handling for stream disconnections
- Parse Events Incrementally: Don't wait for the entire stream to complete before processing events
- Store Chat IDs: Reuse chat IDs to maintain conversation context
- Monitor Function Status: Use execution status events to show loading states in your UI
- Handle Large Results: Use the
viewLink
for large dataset results instead of processing them directly