Converts a natural language question into a SQL query
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
The /v2/generate_sql endpoint converts natural language questions into SQL queries. It allows you to interact with your database using natural language.
Basic Usage
To generate a SQL query, send a request with your question:
// Request
{
"projectId": 1,
"question": "Show me all customers"
}
// Response
{
"id": "1fbc0d64-1c58-45b2-a990-9183bbbcf913",
"sql": "SELECT * FROM \"olist_customers_dataset\"",
"threadId": "9c537507-9cec-46ed-b877-07bfa6322bed"
}Getting Both Wren SQL and Dialect SQL
Use the returnBothSqlDialect parameter to receive both the original Wren SQL and the database-specific dialect SQL:
// Request
{
"projectId": 1,
"question": "Show me top 10 customers with their details",
"returnBothSqlDialect": true
}
// Response
{
"id": "1fbc0d64-1c58-45b2-a990-9183bbbcf913",
"sql": "SELECT \"customer_id\" AS \"Customer_ID\", \"customer_unique_id\" AS \"Customer_Unique_ID\", \"customer_city\" AS \"Customer_City\", \"customer_state\" AS \"Customer_State\" FROM \"olist_customers_dataset\" LIMIT 10",
"dialectSql": "SELECT olist_customers_dataset.customer_id AS `Customer_ID`, olist_customers_dataset.customer_unique_id AS `Customer_Unique_ID`, olist_customers_dataset.customer_city AS `Customer_City`, olist_customers_dataset.customer_state AS `Customer_State` FROM (SELECT __source.customer_city AS customer_city, __source.customer_id AS customer_id, __source.customer_state AS customer_state, __source.customer_unique_id AS customer_unique_id FROM `wrenai-saas-staging`.sample_dataset_ecommerce.olist_customers_dataset AS __source) AS olist_customers_dataset LIMIT 10",
"threadId": "9c537507-9cec-46ed-b877-07bfa6322bed"
}Understanding the Response Fields
sql: Clean, readable Wren SQL that's optimized for understandingdialectSql: Database-specific SQL that will actually be executed, including schema prefixes, table references, and database-specific syntax
When to Use returnBothSqlDialect
returnBothSqlDialect- Debugging: Compare the generated Wren SQL with the actual executed SQL
- Transparency: See exactly what SQL will run against your database
- Integration: Use the
dialectSqldirectly in your database tools if needed
SQL Dialect Compatibility
The returnSqlDialect parameter returns only the dialect SQL:
// Request
{
"projectId": 1,
"question": "Show me all customers",
"returnSqlDialect": true
}
// Response
{
"id": "1fbc0d64-1c58-45b2-a990-9183bbbcf913",
"sql": "SELECT olist_customers_dataset.customer_id, olist_customers_dataset.customer_unique_id FROM `project.dataset.olist_customers_dataset`",
"threadId": "9c537507-9cec-46ed-b877-07bfa6322bed"
}Conversation Context
You can use the threadId returned in the response to ask follow-up questions while maintaining context:
// Follow-up question
{
"projectId": 1,
"question": "list top 10 only",
"threadId": "9c537507-9cec-46ed-b877-07bfa6322bed"
}
// Response
{
"id": "2589615b-abbd-48b0-926f-128faa96a87e",
"sql": "SELECT * FROM \"olist_customers_dataset\" ORDER BY \"customer_id\" ASC LIMIT 10",
"threadId": "9c537507-9cec-46ed-b877-07bfa6322bed"
}Executing Queries
Once you have the SQL, you can:
- Pass the SQL to the
/v2/run_sqlendpoint to execute the query and get results - Use the
returnSqlDialect: trueparameter to get SQL in your database's native dialect and run it directly in your database
Non-SQL Query Handling
If your question can't be converted to SQL, you'll receive an error response with the following fields:
id: A unique identifier for the error responsecode: An error code indicating the type of issue encountered:NON_SQL_QUERY(HTTP 400): The question cannot be translated to SQL because it's unrelated to data queryingNO_DEPLOYMENT_FOUND(HTTP 400): No active deployment was found for the projectPOLLING_TIMEOUT(HTTP 500): The operation timed out while waiting for a response from the AI service
error: A human-readable description explaining why the query couldn't be translated to SQLexplanationQueryId: An identifier you can use to get a more detailed explanation
// Example 1: Asking question "hello"
{
"id": "e593369b-e222-4435-b874-dc10edb12a96",
"code": "NON_SQL_QUERY",
"error": "Vague greeting unrelated to schema, SQL, or user guide; no specific intent identified.",
"explanationQueryId": "475afc1f-7950-4bc7-a248-a7da394d137a"
}
// Example 2: Asking question "what could you do"
{
"id": "75c13d09-6f86-4e79-a00e-a4f85f73f2d7",
"code": "NON_SQL_QUERY",
"error": "User asks about Wren AI's features and capabilities, unrelated to database schema.",
"explanationQueryId": "71b016c5-42bb-4897-82d6-46f9b0bf7d94"
}Use the explanationQueryId with the /v2/stream_explanation endpoint to receive a detailed explanation response streamed as events.
User Guide Controls
Before answering, Wren classifies what a question is asking for. Most questions are about the data and become SQL. Some are not: "Do I need to know SQL?", "How do I get started?" Wren recognises those as product help and answers them from a built-in user guide describing Wren itself.
If you have embedded Wren in your own product that is usually the wrong answer — your users have never heard of Wren. This endpoint never shows you that answer, though: a product-help question fails with NON_SQL_QUERY whichever way these fields are set. What they change here is which non-SQL path ran, and whether a genuine data question phrased as a how-to gets misread as product help in the first place. Two per-request fields control it:
allowUserGuide(boolean, defaulttrue) — setfalseand product help is removed from classification altogether, so a how-to phrased data question is no longer misread as one.userGuidePrompt(string) — supply your own guide and Wren uses it in place of ours, both when classifying the question and when answering it throughexplanationQueryId. Ignored whenallowUserGuideisfalse.
Both default to today's behavior, so omitting them leaves the request unchanged. Both are per-request: re-send them on every turn of a thread. See User Guide Controls for the shared behaviour, including what happens to a question your guide does not cover.
Switch the built-in guide off:
{
"projectId": 1,
"question": "How do I get started?",
"allowUserGuide": false
}Or answer from your own guide instead — same question, your content:
{
"projectId": 1,
"question": "How do I get started?",
"userGuidePrompt": "# Northwind Insights - Help\n\n## Getting started\nOpen **Explore** in the left sidebar and pick a dataset. Type your question in\nthe box at the top; results appear as a table you can switch to a chart.\n\n## Saving a report\nClick **Save** in the top-right of any answer to add it to *My Reports*.\nSaved reports refresh every morning at 06:00 UTC.\n\n## Sharing a report\nOpen a saved report and choose **Share > Copy link**. Links work only for\nteammates in your workspace; external sharing must be enabled by an admin."
}Either way the request fails with NON_SQL_QUERY — what changes is the error prose and the path behind explanationQueryId.
{
"id": "dde3ba13-cffa-4577-a042-16e926f8735a",
"invalidSessionProperties": [],
"code": "NON_SQL_QUERY",
"error": "This is a product usage/setup question, not a data analysis request.",
"explanationQueryId": "f70a16d9-898c-4116-80f2-dd658b39da4c"
}{
"id": "7809befc-7144-49ed-92fa-b3be30800f79",
"invalidSessionProperties": [],
"code": "NON_SQL_QUERY",
"error": "This is a how-to question about using the system, not about database analysis.",
"explanationQueryId": "5baaf959-8b8f-4ce8-aed3-141f63770ad6"
}Stream the explanationQueryId from /v2/stream_explanation to read the answer itself; a supplied userGuidePrompt is used there too.
Their practical value on this endpoint is rescuing a genuine data question that was misread as a how-to:
{
"projectId": 1,
"question": "How do I find orders that were cancelled?"
}{
"id": "330e6140-716a-4e1e-9a1b-0f43d3779f92",
"invalidSessionProperties": [],
"code": "NON_SQL_QUERY",
"error": "User is asking how to query cancelled orders; this is a system usage question.",
"explanationQueryId": "d04001d7-00e1-4818-bdaf-6c95f547e927"
}The same question with product help switched off generates SQL (usage omitted from the body below):
{
"projectId": 1,
"question": "How do I find orders that were cancelled?",
"allowUserGuide": false
}{
"id": "d5ecab42-efe8-40e9-a01e-bc84e19b5afd",
"invalidSessionProperties": [],
"threadId": "6a96edab-7dcd-4242-82e3-d6f7b14ac5bd",
"sql": "SELECT\n order_id,\n customer_id,\n order_status,\n order_purchase_timestamp,\n order_approved_at,\n order_delivered_carrier_date,\n order_delivered_customer_date,\n order_estimated_delivery_date\nFROM `olist_orders_dataset`\nWHERE order_status = 'canceled'\nORDER BY order_purchase_timestamp DESC"
}If your integration only ever asks data questions, sending allowUserGuide: false on every request removes this failure mode for the questions we tested.
