Skip to content

API Reference

Adeel Ijaz edited this page Mar 31, 2026 · 2 revisions

Complete reference for all SQL Query Engine endpoints. The engine exposes two API surfaces: native inference routes (/inference/*) for direct pipeline control, and OpenAI-compatible routes (/v1/*) for integration with standard tooling.

Base URL

Deployment Base URL
Docker Compose http://localhost:5181
Local development http://localhost:8080

Health Check

GET /ping

Returns server status and request metadata. No authentication required.

Response:

{
  "code": 200,
  "status": "[ SQL Query Engine ]: Agent is alive and reachable.",
  "agent": "sqlQueryEngine",
  "scheme": "http",
  "host": "localhost",
  "port": "5181",
  "clientHost": "172.18.0.1",
  "clientPort": 54321
}

Native Inference Endpoints

These endpoints provide direct control over the two-stage pipeline. They accept optional query parameters to override connection settings (see Configuration).

POST /inference/sqlQueryEngine/{chatID}

Runs the full pipeline: Stage 1 (NL β†’ SQL generation) + Stage 2 (execution + repair loop).

Path Parameters:

Parameter Type Description
chatID string Session identifier. Namespaces all Redis context for this conversation.

Request Body:

{
  "basePrompt": "How many orders were placed in the last 30 days?",
  "retryCount": 5,
  "schemaExamples": 5,
  "feedbackExamples": 3,
  "schemaDescriptionKey": "dbSchemaDescription",
  "extraPayload": {"source": "api-call"}
}
Field Type Required Default Description
basePrompt string Yes β€” Natural language question
retryCount int No 5 Max repair loop iterations
schemaExamples int No 5 Sample rows per table for schema introspection
feedbackExamples int No 3 Result rows fed back to LLM during evaluation
schemaDescriptionKey string No "dbSchemaDescription" Redis key for cached schema. Change to force regeneration.
extraPayload object No null Passed through untouched in the response

Success Response (200):

{
  "code": 200,
  "status": "[ test-session-001 | SQL Query Engine ]: Inference executed successfully.",
  "chatID": "test-session-001",
  "agentResponse": {
    "generation": {
      "queryDescription": "Count the number of orders placed in the last 30 days",
      "sqlQuery": "SELECT COUNT(*) AS order_count FROM orders WHERE created_at >= NOW() - INTERVAL '30 days'"
    },
    "evaluation": {
      "currentQuery": "SELECT COUNT(*) AS order_count FROM orders WHERE created_at >= NOW() - INTERVAL '30 days'",
      "currentObservation": "Query executed successfully and returned 1 rows.",
      "results": [{"order_count": 842}]
    }
  },
  "extraPayload": {"source": "api-call"}
}

Error Response (500):

{
  "code": 500,
  "status": "[ SQL Query Engine ]: SQL generation failed: Connection refused",
  "error": "SQL generation failed: Connection refused"
}

POST /inference/sqlQueryGeneration/{chatID}

Runs Stage 1 only: generates SQL from natural language without executing it.

Request Body:

{
  "basePrompt": "List all active users who signed up this year.",
  "schemaExamples": 5,
  "schemaDescriptionKey": "dbSchemaDescription",
  "extraPayload": null
}
Field Type Required Default Description
basePrompt string Yes β€” Natural language question
schemaExamples int No 5 Sample rows per table
schemaDescriptionKey string No "dbSchemaDescription" Redis key for cached schema
extraPayload object No null Passthrough payload

Success Response (200):

{
  "code": 200,
  "status": "[ test-session-001 | SQL Generation ]: Generation executed successfully.",
  "chatID": "test-session-001",
  "agentResponse": {
    "generation": {
      "queryDescription": "List all users with active status who registered in the current year",
      "sqlQuery": "SELECT * FROM users WHERE status = 'active' AND EXTRACT(YEAR FROM created_at) = EXTRACT(YEAR FROM NOW())"
    }
  },
  "extraPayload": null
}

POST /inference/sqlQueryEvaluation/{chatID}

Runs Stage 2 only: executes a provided SQL query and repairs it if it fails.

Request Body:

{
  "basePrompt": "How many orders were placed in the last 30 days?",
  "baseQuery": "SELECT COUNT(*) FROM orders WHERE created_at >= NOW() - INTERVAL '30 days'",
  "baseDescription": "Count orders placed in the last 30 days.",
  "retryCount": 3,
  "schemaExamples": 5,
  "feedbackExamples": 3,
  "schemaDescriptionKey": "dbSchemaDescription",
  "extraPayload": null
}
Field Type Required Default Description
basePrompt string Yes β€” Original natural language question
baseQuery string Yes β€” SQL query to execute and evaluate
baseDescription string Yes β€” Plain-English description of the query
retryCount int No 5 Max repair iterations
schemaExamples int No 5 Sample rows per table
feedbackExamples int No 3 Result rows fed back to LLM
schemaDescriptionKey string No "dbSchemaDescription" Redis key for schema
extraPayload object No null Passthrough payload

Success Response (200):

{
  "code": 200,
  "status": "[ test-session-001 | SQL Evaluation ]: Evaluation executed successfully.",
  "chatID": "test-session-001",
  "agentResponse": {
    "evaluation": {
      "currentQuery": "SELECT COUNT(*) AS order_count FROM orders WHERE created_at >= NOW() - INTERVAL '30 days'",
      "currentObservation": "Query executed successfully and returned 1 rows.",
      "results": [{"order_count": 842}]
    }
  },
  "extraPayload": null
}

OpenAI-Compatible Endpoints

These endpoints implement the OpenAI API specification, allowing the engine to be used as a drop-in backend for OpenAI SDKs, LangChain, OpenWebUI, and any other OpenAI-compatible client.

All /v1/* endpoints require a Bearer token when OPENAI_API_KEY is set.

GET /v1/models

Lists available models.

Headers:

Authorization: Bearer your-api-key

Response:

{
  "object": "list",
  "data": [
    {
      "id": "SQLBot",
      "object": "model",
      "created": 1700000000,
      "owned_by": "sql-query-engine"
    }
  ]
}

The model name is controlled by the COMPLETIONS_MODEL_NAME environment variable (defaults to the value of BOT_NAME, falling back to SQLBot).

POST /v1/chat/completions

OpenAI-compatible chat completion. Supports both streaming (SSE) and non-streaming modes.

Headers:

Content-Type: application/json
Authorization: Bearer your-api-key

Request Body:

{
  "model": "SQLBot",
  "messages": [
    {"role": "user", "content": "How many orders were placed last month?"}
  ],
  "stream": true,
  "chat_id": "my-session-001"
}
Field Type Required Default Description
model string Yes β€” Model identifier (ignored β€” the engine always uses the configured pipeline)
messages array Yes β€” Array of {role, content} message objects. The last user message is used as the SQL prompt.
stream bool No true Enable SSE streaming
chat_id string No MD5 of first user message Session ID for context preservation. Provided automatically by OpenWebUI.
temperature float No β€” Ignored β€” temperature is set via the LLM_TEMPERATURE env var
max_tokens int No β€” Ignored β€” not applicable to the SQL engine

Non-Streaming Response:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1700000000,
  "model": "SQLBot",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "<think>\n...pipeline progress...\n</think>\n\n**Query plan:** Count orders...\n\n```sql\nSELECT COUNT(*)...\n```\n\n**Results** β€” 1 row(s) returned:\n\n| order_count |\n| --- |\n| 842 |"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 0,
    "completion_tokens": 0,
    "total_tokens": 0
  }
}

Streaming Response (SSE):

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"<think>\n"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Analyzing schema..."},"finish_reason":null}]}

...

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"\n</think>\n\n"},"finish_reason":null}]}

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"**Query plan:** ..."},"finish_reason":null}]}

data: [DONE]

Progress messages from the pipeline are wrapped in <think>...</think> tags, which OpenWebUI renders as a collapsible "thinking" section.

POST /v1/completions

Legacy text completions endpoint. Each request gets a fresh chatID (UUID-based).

Request Body:

{
  "model": "SQLBot",
  "prompt": "How many users signed up in the last 7 days?",
  "stream": false
}

Non-Streaming Response:

{
  "id": "cmpl-abc123",
  "object": "text_completion",
  "created": 1700000000,
  "model": "SQLBot",
  "choices": [
    {
      "text": "<think>\n...pipeline progress...\n</think>\n\n**Query plan:** ...",
      "index": 0,
      "logprobs": null,
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 0,
    "completion_tokens": 0,
    "total_tokens": 0
  }
}

OpenAPI / Swagger

The engine auto-generates an OpenAPI specification:

URL Description
/docs Swagger UI (interactive API explorer)
/openapi.json Raw OpenAPI JSON schema
# Download the schema
curl -s http://localhost:5181/openapi.json | jq .

# Open Swagger UI in browser
open http://localhost:5181/docs

Error Responses

Native Endpoints (/inference/*)

{
  "code": 500,
  "status": "[ SQL Query Engine ]: SQL generation failed: Connection refused",
  "error": "SQL generation failed: Connection refused"
}

OpenAI-Compatible Endpoints (/v1/*)

401 β€” Invalid API key:

{
  "detail": {
    "error": {
      "message": "Invalid API key. Provide a valid key in 'Authorization: Bearer <key>'.",
      "type": "invalid_request_error",
      "param": null,
      "code": "invalid_api_key"
    }
  }
}

500 β€” Missing configuration:

{
  "detail": {
    "error": {
      "message": "Required environment variables not configured: LLM_BASE_URL, LLM_MODEL. Set them in docker-compose.yml or the host environment.",
      "type": "server_error",
      "code": "missing_configuration"
    }
  }
}

Common error codes:

Code Cause
401 Missing or invalid Bearer token on /v1/* routes
422 Validation error (missing required fields, wrong types)
500 Internal error (LLM connection failed, database unreachable, Redis timeout, missing env vars)

SQL Query Engine

Design

Setup

API

Internals

Evaluation

Help

Clone this wiki locally