Python integration
Generate reviewable SQL from Python.
Use a short server-side Python request to turn a question into SQL for an existing TTSQL project. Keep credentials out of code and make generation a distinct step in your application.
Try TTSQL freePrepare a project and a server-side API key
Create a TTSQL project, choose its database type and supply the schema context and project rules that generation should use. Create an API key for your account and record the intended project ID. Passing project_id explicitly avoids ambiguity when an account owns several projects.
Store the key in your server's environment or secret manager. Do not put it in source control, a browser bundle or a publicly shared notebook. TTSQL builds schema and policy context from the selected project; this request does not upload a database schema or connect to a database.
Install requests and set the environment
Use Python 3.10 or later in a virtual environment and install requests. Set TTSQL_API_KEY to your real key and TTSQL_PROJECT_ID to the numeric project ID using your deployment's secret configuration. The example intentionally fails early if either value is missing or malformed.
python -m pip install requests
Send one generation request
Save the example as generate_sql.py and run it on the server where the environment variables are available. Its sample prompt assumes orders(id, status, total); replace the question with one that matches your configured project.
The connect timeout is five seconds and the read timeout is sixty seconds. requests uses this pair for connection establishment and waits for response data; it is not a strict sixty-five-second whole-program deadline.
import os
import sys
import requests
def generate_sql(prompt: str) -> str:
api_key = os.environ["TTSQL_API_KEY"]
project_id = int(os.environ["TTSQL_PROJECT_ID"])
if not api_key.strip() or project_id <= 0 or not prompt.strip():
raise ValueError("A key, positive project ID and prompt are required")
response = requests.post(
"https://ttsql.com/api/v1",
headers={"x-api-key": api_key, "Accept": "application/json"},
json={"prompt": prompt, "project_id": project_id},
timeout=(5, 60),
)
if not response.ok:
raise RuntimeError(f"TTSQL returned HTTP {response.status_code}")
data = response.json()
if not isinstance(data, dict) or data.get("status") != "success":
raise RuntimeError("Unexpected generation response")
query = data.get("query")
if not isinstance(query, str) or not query.strip():
raise RuntimeError("Generation returned no SQL")
if data.get("executed") is not False:
raise RuntimeError("Unexpected execution state; review the API contract")
return query
if __name__ == "__main__":
try:
sql = generate_sql(
"List paid order IDs and totals, ordered by ID, limited to 20 rows."
)
print(sql) # Review this SQL; this script does not execute it.
except (KeyError, ValueError, requests.RequestException, RuntimeError) as error:
print(f"Generation failed: {type(error).__name__}", file=sys.stderr)
sys.exit(1)
Treat the response as generated SQL
A successful POST /api/v1 response includes status, query, executed, execution and metadata. This endpoint returns executed: false. Omitting the legacy execute field keeps the request focused on generation; sending execute: true does not enable execution.
The SQL is a candidate to review. Do not wire the returned string directly to a database driver. Manual Run in the TTSQL workspace is a separate action, with its own connection and policy checks.
{
"status": "success",
"query": "SELECT id, total FROM orders WHERE status = 'paid' ORDER BY id;",
"executed": false,
"execution": {"status": "not_requested"},
"metadata": {
"project_id": 123,
"api_key_id": 7,
"timestamp": "2026-09-05T12:00:00Z"
}
}
Connect it to a Python service
Keep the HTTP client in the server layer. A web handler can accept an authorized user's question, choose the project that user is allowed to access, call generation, and return SQL to a review screen. Do not accept an arbitrary project ID as proof of authorization.
requests is synchronous. In an async Python application, use an async HTTP client with the same header, JSON body and validation, or isolate blocking work from the event loop. Test your application's success, timeout and error branches with a local HTTP fixture; production generation calls are not required for those tests.
Handle failures without leaking prompts or credentials
Treat 400 as a request or policy problem to inspect, 401 as an authentication failure and 404 as a project access or identifier problem. A rate limit can produce 429. Generation or service failures can produce a server error. Consult the API reference for the deployed response contract.
The examples use one request and a finite timeout. A client timeout does not prove that server-side generation stopped. Avoid blind retries: a repeated POST can create another generation request. If you add bounded retries for temporary errors, account for rate limits and duplicate work.
Do not log the x-api-key header. Prompts and returned SQL can reveal business information and identifiers, so choose a deliberate logging policy instead of dumping entire requests and responses.
Answers before you connect a database.
Is there a required TTSQL Python SDK?
No SDK is required for this example. It uses the HTTP API through requests, with x-api-key authentication and a JSON body containing prompt and project_id.
Will running the Python example query my database?
No. It requests SQL generation and prints the returned SQL. POST /api/v1 returns executed: false; manual execution in the workspace is a separate step.
Can I put this in a public notebook?
Keep the real API key in a private secret store and avoid printing it. A shared notebook can also expose prompts and generated SQL through saved outputs, so review those before sharing.
Bring your next question to TTSQL.
Start with one PostgreSQL project and 20 free requests a day. Explore your data, build a report, or integrate the API.