Chat API
The Chat API provides an interactive conversational interface for data analysis. Users can ask questions in natural language, and Querri generates and executes data queries, returning results in a streaming format.
Base URL
Section titled “Base URL”https://api.querri.com/apiAuthentication
Section titled “Authentication”All Chat API endpoints require JWT authentication. See Authentication for details.
Endpoints
Section titled “Endpoints”Send Chat Message
Section titled “Send Chat Message”Send a message to the chat interface for a specific project. The API responds with streaming Server-Sent Events (SSE) containing steps, execution updates, and results.
POST /api/projects/{uuid}/chatHeaders:
Authorization: Bearer {JWT_TOKEN}Content-Type: application/jsonAccept: text/event-streamPath Parameters:
| Parameter | Type | Description |
|---|---|---|
uuid | string | Project UUID to provide context for the chat |
Request Body:
{ "message": "Show me the top 10 customers by revenue in Q4", "model": "gpt-4o", "context": { "previous_message_id": "msg_01ABCDEF", "include_history": true }, "parameters": { "temperature": 0.7, "max_tokens": 2000 }}Request Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | User’s natural language query |
model | string | No | LLM model to use (default: gpt-4o) |
context.previous_message_id | string | No | ID of previous message for conversation continuity |
context.include_history | boolean | No | Include full conversation history (default: true) |
parameters.temperature | float | No | LLM temperature 0.0-2.0 (default: 0.7) |
parameters.max_tokens | integer | No | Maximum response tokens (default: 2000) |
Streaming Responses
Section titled “Streaming Responses”The Chat API uses Server-Sent Events (SSE) to stream responses in real-time. Each event contains a JSON payload with the current state.
Event Types
Section titled “Event Types”1. Message Acknowledgment
Section titled “1. Message Acknowledgment”First event confirming message received:
event: message_receiveddata: {"message_id": "msg_01ABCDEF", "timestamp": "2025-01-15T10:00:00Z"}2. Thinking/Analysis
Section titled “2. Thinking/Analysis”AI is analyzing the request:
event: thinkingdata: {"status": "analyzing", "message": "Analyzing your request..."}3. Step Created
Section titled “3. Step Created”A new execution step was created:
event: step_createddata: { "step_id": "step_01ABCDEF", "type": "sql_query", "name": "Extract top customers by revenue", "order": 1}4. Step Executing
Section titled “4. Step Executing”Step execution started:
event: step_executingdata: { "step_id": "step_01ABCDEF", "status": "running", "started_at": "2025-01-15T10:00:05Z"}5. Step Progress
Section titled “5. Step Progress”Progress updates during execution:
event: step_progressdata: { "step_id": "step_01ABCDEF", "progress": { "percentage": 45, "rows_processed": 4500, "estimated_total": 10000 }}6. Step Completed
Section titled “6. Step Completed”Step finished successfully:
event: step_completeddata: { "step_id": "step_01ABCDEF", "status": "completed", "completed_at": "2025-01-15T10:00:15Z", "duration_seconds": 10, "result_summary": { "rows": 10, "columns": 3, "data_url": "/api/projects/proj_01ABCDEF/steps/step_01ABCDEF/data" }}7. Step Failed
Section titled “7. Step Failed”Step execution failed:
event: step_faileddata: { "step_id": "step_01ABCDEF", "status": "failed", "error": { "code": "sql_execution_error", "message": "Table 'customers' does not exist", "details": "Check your database schema" }}8. Response Token
Section titled “8. Response Token”LLM generating response text (streamed token by token):
event: response_tokendata: {"token": "Based", "position": 0}
event: response_tokendata: {"token": " on", "position": 1}
event: response_tokendata: {"token": " the", "position": 2}9. Response Complete
Section titled “9. Response Complete”Full response finished:
event: response_completedata: { "message_id": "msg_01GHIJKL", "response": "Based on the data, here are the top 10 customers by revenue in Q4:\n\n1. Acme Corp - $125,000\n2. TechStart Inc - $98,500\n...", "steps": ["step_01ABCDEF"], "execution_time_seconds": 12}10. Error
Section titled “10. Error”Error during processing:
event: errordata: { "error": "execution_failed", "message": "Failed to execute query", "step_id": "step_01ABCDEF", "recoverable": true}11. Done
Section titled “11. Done”Stream complete:
event: donedata: {"timestamp": "2025-01-15T10:00:20Z"}Complete Example
Section titled “Complete Example”Request
Section titled “Request”curl -N -X POST "https://api.querri.com/api/projects/proj_01ABCDEF/chat" \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "message": "Show me the top 10 customers by revenue in Q4", "model": "gpt-4o", "context": { "include_history": true } }'Response Stream
Section titled “Response Stream”event: message_receiveddata: {"message_id": "msg_01ABCDEF", "timestamp": "2025-01-15T10:00:00Z"}
event: thinkingdata: {"status": "analyzing", "message": "Analyzing your request..."}
event: step_createddata: {"step_id": "step_01ABCDEF", "type": "sql_query", "name": "Extract top customers", "order": 1}
event: step_executingdata: {"step_id": "step_01ABCDEF", "status": "running", "started_at": "2025-01-15T10:00:05Z"}
event: step_progressdata: {"step_id": "step_01ABCDEF", "progress": {"percentage": 50, "rows_processed": 5000}}
event: step_completeddata: { "step_id": "step_01ABCDEF", "status": "completed", "completed_at": "2025-01-15T10:00:15Z", "duration_seconds": 10, "result_summary": { "rows": 10, "columns": 3, "data_url": "/api/projects/proj_01ABCDEF/steps/step_01ABCDEF/data" }}
event: response_tokendata: {"token": "Based on the Q4 data, here are the top 10 customers:\n\n"}
event: response_tokendata: {"token": "1. **Acme Corp** - $125,000\n"}
event: response_tokendata: {"token": "2. **TechStart Inc** - $98,500\n"}
event: response_completedata: { "message_id": "msg_01GHIJKL", "response": "Based on the Q4 data, here are the top 10 customers:\n\n1. **Acme Corp** - $125,000\n2. **TechStart Inc** - $98,500\n...", "steps": ["step_01ABCDEF"], "execution_time_seconds": 12}
event: donedata: {"timestamp": "2025-01-15T10:00:20Z"}Response Format
Section titled “Response Format”Data Structure
Section titled “Data Structure”Each SSE event follows this structure:
event: {event_type}data: {json_payload}Events are separated by blank lines. The data field always contains valid JSON.
Context Handling
Section titled “Context Handling”The Chat API maintains conversation context across multiple messages.
Continuing a Conversation
Section titled “Continuing a Conversation”# First messagecurl -X POST "https://api.querri.com/api/projects/proj_01ABCDEF/chat" \ -H "Authorization: Bearer ${JWT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"message": "Show me total revenue by month"}'
# Follow-up message (using previous message_id)curl -X POST "https://api.querri.com/api/projects/proj_01ABCDEF/chat" \ -H "Authorization: Bearer ${JWT_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "message": "Now break that down by product category", "context": { "previous_message_id": "msg_01ABCDEF", "include_history": true } }'Context Window
Section titled “Context Window”- Chat history is automatically managed
- Last 10 messages are included by default
- Context includes previous queries, results, and generated steps
- Long contexts are automatically summarized
Model Selection
Section titled “Model Selection”Available Models
Section titled “Available Models”| Model | Description | Best For |
|---|---|---|
gpt-4o | GPT-4 Omni (default) | Complex analysis, multi-step queries |
gpt-4-turbo | Fast GPT-4 | Quick queries, simple aggregations |
claude-3-5-sonnet | Claude Sonnet | Code generation, detailed explanations |
claude-3-5-haiku | Claude Haiku | Simple queries, fast responses |
Model-Specific Parameters
Section titled “Model-Specific Parameters”{ "message": "Analyze sales trends", "model": "gpt-4o", "parameters": { "temperature": 0.7, "max_tokens": 2000, "top_p": 0.9, "frequency_penalty": 0.0, "presence_penalty": 0.0 }}Error Handling
Section titled “Error Handling”Common Errors
Section titled “Common Errors”Invalid Project
Section titled “Invalid Project”{ "error": "not_found", "message": "Project not found or access denied", "project_uuid": "proj_01INVALID"}HTTP Status: 404 Not Found
Invalid Message
Section titled “Invalid Message”{ "error": "validation_error", "message": "Message is required and cannot be empty", "field": "message"}HTTP Status: 400 Bad Request
Connector Not Available
Section titled “Connector Not Available”event: errordata: { "error": "connector_unavailable", "message": "Database connector is not accessible", "connector_uuid": "conn_01ABCDEF", "recoverable": false}Query Execution Failed
Section titled “Query Execution Failed”event: step_faileddata: { "step_id": "step_01ABCDEF", "error": { "code": "sql_execution_error", "message": "Syntax error in SQL query", "query": "SELECT * FORM customers", "details": "Did you mean 'FROM' instead of 'FORM'?" }}Client Implementation Examples
Section titled “Client Implementation Examples”JavaScript (Browser)
Section titled “JavaScript (Browser)”const eventSource = new EventSource( 'https://api.querri.com/api/projects/proj_01ABCDEF/chat', { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, method: 'POST', body: JSON.stringify({ message: 'Show me top customers', model: 'gpt-4o' }) });
eventSource.addEventListener('step_created', (e) => { const data = JSON.parse(e.data); console.log('Step created:', data.step_id);});
eventSource.addEventListener('response_token', (e) => { const data = JSON.parse(e.data); document.getElementById('response').innerHTML += data.token;});
eventSource.addEventListener('done', (e) => { console.log('Stream complete'); eventSource.close();});
eventSource.addEventListener('error', (e) => { console.error('Stream error:', e); eventSource.close();});Python
Section titled “Python”import requestsimport json
url = "https://api.querri.com/api/projects/proj_01ABCDEF/chat"headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", "Accept": "text/event-stream"}payload = { "message": "Show me top customers", "model": "gpt-4o"}
response = requests.post(url, headers=headers, json=payload, stream=True)
for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('event:'): event_type = line.split(':', 1)[1].strip() elif line.startswith('data:'): data = json.loads(line.split(':', 1)[1].strip()) print(f"{event_type}: {data}")cURL (with line-by-line output)
Section titled “cURL (with line-by-line output)”curl -N -X POST "https://api.querri.com/api/projects/proj_01ABCDEF/chat" \ -H "Authorization: Bearer ${JWT_TOKEN}" \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{ "message": "Show me top customers", "model": "gpt-4o" }'Rate Limiting
Section titled “Rate Limiting”Chat API has specific rate limits:
| Limit Type | Value | Window |
|---|---|---|
| Messages per user | 100 | 1 hour |
| Concurrent streams | 3 | Per user |
| Token generation rate | 10,000 | Per minute |
When rate limited:
event: errordata: { "error": "rate_limit_exceeded", "message": "Too many concurrent chat streams", "retry_after": 60}HTTP Status: 429 Too Many Requests
Best Practices
Section titled “Best Practices”- Handle Reconnection - Implement exponential backoff for connection failures
- Process Events Incrementally - Update UI as events arrive, don’t wait for completion
- Store Message IDs - Track conversation history using message IDs
- Handle Errors Gracefully - Display user-friendly error messages
- Implement Timeouts - Close connections after reasonable timeout (e.g., 5 minutes)
- Buffer Response Tokens - Batch token updates to avoid excessive DOM updates
- Cancel Long-Running Queries - Provide user option to cancel execution
Conversation Flow Example
Section titled “Conversation Flow Example”User: "Show me revenue by month" → step_created: SQL query to aggregate revenue → step_executing: Running query → step_completed: 12 rows returned → response: "Here's the monthly revenue..." [with data]
User: "Now show only Q4" → [Using context from previous message] → step_created: SQL query with WHERE clause for Q4 → step_executing: Running filtered query → step_completed: 3 rows returned → response: "Q4 revenue breakdown..." [with filtered data]
User: "Create a chart" → step_created: Visualization step → step_executing: Generating chart → step_completed: Chart generated → response: "Here's the chart..." [with image URL]HTTP Status Codes
Section titled “HTTP Status Codes”| Code | Description |
|---|---|
| 200 | Success - stream started |
| 400 | Bad Request - invalid message or parameters |
| 401 | Unauthorized - missing/invalid token |
| 403 | Forbidden - no access to project |
| 404 | Not Found - project doesn’t exist |
| 429 | Too Many Requests - rate limited |
| 500 | Internal Server Error |