Chat history
Reopen an earlier chat: load its messages newest first, page back through older ones, and redraw any answer's table or chart.
Use the same headers as Conversations: X-API-Key, and X-End-User-Id for the person whose chat it is. A chat belongs to the end user who started it. Anyone else gets a 404. Ask-only keys can use every call on this page.
List someone's chats
GET /clients/{client_id}/sessions?limit=50&offset=0 returns {items, total, limit, offset}, newest first. Each item has id, title, created_at, updated_at and message_count. The id is the session_id below.
Open a chat, newest first
Ask for the last 30 messages. They come back oldest first, with has_more when the chat goes back further. To load older messages, send the id of the oldest message you have as before_message_id. Repeat until has_more is false.
curl "https://api.factql.ai/clients/$CLIENT_ID/sessions/$SESSION_ID?message_limit=30" \ -H "X-API-Key: $FACTQL_API_KEY" -H "X-End-User-Id: user-42" curl "https://api.factql.ai/clients/$CLIENT_ID/sessions/$SESSION_ID?message_limit=30&before_message_id=1071" \ -H "X-API-Key: $FACTQL_API_KEY" -H "X-End-User-Id: user-42"
{ "id": "3f7b1c40-2a55-4f9e-8d21-0a6f4b9c1d33", "title": "Revenue by month", "has_more": true, "messages": [ { "id": 1071, "role": "user", "content": "Revenue by month this year", "timestamp": "2026-11-10T09:12:03Z", "metadata": {} }, { "id": 1072, "role": "assistant", "content": "Revenue rose every month from January to July.", "timestamp": "2026-11-10T09:12:09Z", "metadata": { "payload": { "sql": "SELECT month, SUM(revenue) AS revenue FROM orders GROUP BY month ORDER BY month", "data": { "columns": ["month", "revenue"] }, "total_rows": 7, "type": "text2sql" } } } ] }
before_message_id, the N before it: 1 to 100, default 30. Leave out both parameters to get the whole chat.id of the oldest message you already have. It must be a message of this chat.An assistant message's metadata.payload has everything its answer card needs except the rows: the sql, the column names under data.columns, total_rows and, when the answer drew one, chart_config. Fetch the rows with the call below.
Redraw an answer's table or chart
message_id is the assistant message's idfrom the chat above. FactQL runs that answer's saved query again, read-only, and returns one page of rows. Opening the same answer again within five minutes is served without another database query.
curl -X POST "https://api.factql.ai/clients/$CLIENT_ID/sessions/$SESSION_ID/messages/1072/results" \ -H "X-API-Key: $FACTQL_API_KEY" -H "X-End-User-Id: user-42" \ -H "Content-Type: application/json" \ -d '{"page": 1, "page_size": 50}'
total_rows you already have, to skip counting again.steps in a previous response. Leave it out to get the last one.{ "columns": ["product", "revenue"], "rows": [["Kit", 48210.0], ["Scarf", 12034.5]], "page": 1, "page_size": 50, "total_rows": 2, "total_pages": 1, "step_id": "s2", "label": "Top products", "steps": [ { "step_id": "s1", "label": "Revenue by month" }, { "step_id": "s2", "label": "Top products" } ], "chart_config": { "type": "bar", "x": "product", "y": "revenue" } }
before_message_id isn't a message of this chat.step_idisn't one of the answer's steps.message_limit is outside 1 to 100 while paging back.Retry-After seconds.