Skip to main content

Streaming Endpoints

These endpoints use Server-Sent Events (SSE) to stream results incrementally. They're ideal for real-time UIs where you want to show progress as the AI generates responses.

Connection Protocol

Streaming endpoints return text/event-stream responses. Each event is a JSON-encoded data: line:

data: {"state":"UNDERSTANDING","message":"Analyzing your question..."}

data: {"state":"GENERATING","message":"Building SQL query..."}

data: {"state":"FINISHED","sql":"SELECT ...","threadId":"abc-123"}

Event States

Most streaming endpoints emit events with a state field indicating progress:

StateDescription
UNDERSTANDINGAnalyzing the natural language question
SEARCHINGSearching the semantic model
GENERATINGGenerating SQL or summary
FINISHEDComplete — final payload included
FAILEDError occurred — error field included

Stream Generate SQL

Stream SQL generation with progress updates.

POST /api/v1/stream/generate_sql

Request Body

FieldTypeRequiredDescription
questionstringYesNatural language question
languagestringNoLanguage for AI responses
threadIdstringNoThread ID for conversation context

Example Request

curl -N -X POST https://your-host/api/v1/stream/generate_sql \
-H "Authorization: Bearer osk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"question": "What are the top 10 products by sales?"
}'

Event Stream

data: {"state":"UNDERSTANDING"}

data: {"state":"SEARCHING"}

data: {"state":"GENERATING"}

data: {"state":"FINISHED","sql":"SELECT p.name, SUM(s.amount) AS total_sales FROM products p JOIN sales s ON p.id = s.product_id GROUP BY p.name ORDER BY total_sales DESC LIMIT 10","threadId":"9c537507-9cec-46ed-b877-07bfa6322bed"}

The final FINISHED event contains the same fields as the non-streaming /generate_sql response.


Stream Ask

Stream the full ask pipeline — SQL generation, execution, and summary — with progress updates.

POST /api/v1/stream/ask

Request Body

FieldTypeRequiredDescription
questionstringYesNatural language question
sampleSizeintegerNoMax rows for analysis
languagestringNoLanguage for AI responses
threadIdstringNoThread ID for conversation context

Example Request

curl -N -X POST https://your-host/api/v1/stream/ask \
-H "Authorization: Bearer osk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"question": "How did revenue change month over month?"
}'

Event Stream

data: {"state":"UNDERSTANDING"}

data: {"state":"SEARCHING"}

data: {"state":"GENERATING"}

data: {"state":"EXECUTING"}

data: {"state":"SUMMARIZING"}

data: {"state":"FINISHED","sql":"SELECT ...","summary":"Revenue grew 12% in January...","threadId":"abc-123"}


Stream Explanation

Stream a detailed explanation for non-SQL questions. Use the explanationQueryId returned by a NON_SQL_QUERY error from /generate_sql.

GET /api/v1/stream_explanation?queryId=<explanationQueryId>

Query Parameters

ParameterTypeRequiredDescription
queryIdstringYesThe explanationQueryId from a prior NON_SQL_QUERY error

Example Request

curl -N "https://your-host/api/v1/stream_explanation?queryId=71b016c5-42bb-4897-82d6-46f9b0bf7d94" \
-H "Authorization: Bearer osk-your-api-key"

Event Stream

data: {"message":"Legible can help you "}

data: {"message":"analyze your data using "}

data: {"message":"natural language queries. "}

data: {"message":"Try asking about specific "}

data: {"message":"metrics, trends, or comparisons."}

data: {"done":true}

Each event contains a message fragment. Concatenate all fragments for the full explanation. The final event has "done": true.


Client Examples

JavaScript (EventSource)

const response = await fetch('/api/v1/stream/ask', {
method: 'POST',
headers: {
'Authorization': 'Bearer osk-your-api-key',
'Content-Type': 'application/json',
},
body: JSON.stringify({ question: 'Total revenue by month?' }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
const { done, value } = await reader.read();
if (done) break;

const text = decoder.decode(value);
for (const line of text.split('\n')) {
if (line.startsWith('data: ')) {
const event = JSON.parse(line.slice(6));
console.log(event.state, event.message || event.sql || '');
}
}
}

Python

import requests
import json

response = requests.post(
'https://your-host/api/v1/stream/ask',
headers={
'Authorization': 'Bearer osk-your-api-key',
'Content-Type': 'application/json',
},
json={'question': 'Total revenue by month?'},
stream=True,
)

for line in response.iter_lines():
if line and line.startswith(b'data: '):
event = json.loads(line[6:])
print(event.get('state', ''), event.get('sql', ''))