PrismSQL — Schema-bound NL-to-SQL compiler

Product identity

PrismSQL is Schema-bound NL-to-SQL compiler. Insight IT Solutions LLC (Insight ITS) makes it. Category: Research — schema-bound NL-to-SQL compiler. Problem: Teams want agents to generate SQL against their own database without leaking a live DSN to a vendor or allowing unconstrained generation. It is for Developers and B2B teams that need agents to compile SQL against an allowlisted customer schema. It competes with Text-to-SQL that executes inside the vendor cloud. Difference: PrismGuard + VectorPrism + Query IR + compiler-owned ranges and ORDER BY + PrismManifest + dialect printer from the contract you upload. Does not query InsightITS CRM and does not connect to your warehouse on the hosted API. Not a pip library. Log in, upload a schema contract at /dashboard.html#prismsql, then POST /api/prismsql/v1/query/execute with a JWT. Source: Product and compile API live on insightits.com. Schema example: /docs/prismsql-schema.example.json..

What is it?
Schema-bound NL-to-SQL compiler.
Who made it?
Insight IT Solutions LLC (Insight ITS), Mission Viejo, California.
What category is it?
Research — schema-bound NL-to-SQL compiler
What problem does it solve?
Teams want agents to generate SQL against their own database without leaking a live DSN to a vendor or allowing unconstrained generation.
Who is it for?
Developers and B2B teams that need agents to compile SQL against an allowlisted customer schema
What does it compete with?
Text-to-SQL that executes inside the vendor cloud
How is it different?
PrismGuard + VectorPrism + Query IR + compiler-owned ranges and ORDER BY + PrismManifest + dialect printer from the contract you upload. Does not query InsightITS CRM and does not connect to your warehouse on the hosted API
Where can I install it?
Not a pip library. Log in, upload a schema contract at /dashboard.html#prismsql, then POST /api/prismsql/v1/query/execute with a JWT.
Where is the source?
Product and compile API live on insightits.com. Schema example: /docs/prismsql-schema.example.json.

Canonical machine identity: https://www.insightits.com/catalog/prismsql.json

Upload your schema. Get parameterized SQL you run — the model never writes it. Sandbox free, Developer $49/mo, Pro $399/mo.

Compile-only API: JWT user → stored schema contract → PrismGuard → VectorPrism → Query IR → PrismManifest → dialect printer. You run sql_template + params in your environment.

PrismGuard → VectorPrism subgraph → IR → PrismManifest → compiler → dialect printer. Isolation injected by the compiler. Hosted API is compile-only. ChorusGraph and PrismCortex are not on this path.

Compile SQL from your schema — not ours

Ask about tables on the contract you uploaded. The compiler owns ranges (last 30 days, next 14 days, over 500, between X and Y, named qty vs unit_amount), prompt ORDER BY (recent / last / order by last name), and tenancy. Query IR 1.1 compiles declared columns, AND filters, and allow-listed COUNT/SUM. Unknown tables are refused. The model never writes the statement, we never connect to your warehouse, and we never return InsightITS CRM rows.

You keep the DSN. You run sql_template + params in your environment. Isolation is injected from the logged-in account, not from the prompt. If your application needs a special compiler or contract adjustment, contact us and we add it for your integration.

Log in, open the dashboard PrismSQL tab, upload your schema JSON, then call POST /api/prismsql/v1/query/execute with a JWT. Example contract: prismsql-schema.example.json. API docs: prismsql-api.md and #api-docs. Dashboard: dashboard.html#prismsql.

Why most Text-to-SQL projects fail

DSN in the vendor cloud. Model-written SELECT. Hallucinated joins. A silent guess when the English is incomplete. Senior engineers have already been burned by those approaches. PrismSQL is a compiler: closed IR, declared join_paths, JWT isolation, parameterized SQL you run where the data lives.

What it is

What it is not

Why teams use it instead of letting the model write SQL

Your schema stays yours

Upload a JSON contract in the dashboard: tables, columns, types, isolation, allowed joins, plus optional indexes, enums, timezone, and cardinality. Validate marks required vs recommended fields. We store that file on your InsightITS account. Compile uses that contract — not a private InsightITS catalog. We never invent a column the file omitted.

Ranges and sort are compiler-owned

“Last 30 days,” “next 14 days,” “over 500,” “between 100 and 500,” and “order them by recent time” are detected before the model writes IR. Prompt ORDER BY overwrites schema default_order. Window digits are not amount binds. One date column on the table is assumed; several dates ask which one. One numeric column is assumed; if you name qty, that column is used; several unnamed numeric columns clarify instead of picking the first or guessing from the size of the number. Hygiene over 500 still clarifies — that table has no amount column.

The model cannot invent SQL

PrismGuard checks the prompt. VectorPrism scores it against embeddings stored when you saved the schema. The model outputs a closed IR. PrismManifest validates that IR against the full contract. Only then does the compiler print SQL.

Tenancy is not a prompt suggestion

Isolation predicates are INJECTED_BY_COMPILER from the JWT email. A body field named tenant_id, userProfile, or mode does not choose the principal. Bind values never appear interpolated in sql_template.

You run it where the data lives

The hosted API is compile-only. You bind params in Postgres, Snowflake, SQL Server, or whichever dialect your plan includes. We will not pretend to return your rows from our Postgres.

Custom integration work

If your application needs a special adjustment — a prompt pattern, a declared operator, a join-path shape, or help wiring the compile API into your agent — contact us. We add it for your integration. We still compile against your contract; we do not open unconstrained SQL generation.

ChorusGraph and PrismCortex are not invoked on this hosted compile path. The schema pin is the contract stored in InsightITS Postgres for your login. Live EXPLAIN against your warehouse is not part of the public API.

How it works

01. Log in

Use your InsightITS website account. Open Dashboard → PrismSQL. Sandbox is provisioned on first visit.

02. Upload the contract

JSON: schema_id, dialect, tables keyed as schema.table, allow_columns, isolation, join_paths. Validate shows required vs recommended warehouse facts (indexes, timezone, enums). The tab lists all ten databases; printers outside your plan stay disabled.

03. We validate and embed

Invalid contracts are refused. Valid ones are stored for your login. Each table and join path is VectorPrism-embedded; a new upload replaces those chunks.

04. Call the compile API

POST /api/prismsql/v1/query/execute with a Bearer JWT and a prompt. You get sql_template + params. You run that statement in your database.

Incomplete English does not become guessed SQL

Harbor invoice_lines has qty and unit_amount. “invoice line items over 5” cannot bind honestly, so the API returns status: clarify and candidates[]. Your app can render those as chips. Naming the column compiles. invoices over 5 would assume amount — that table has one numeric column.

Prompt: invoice line items over 5

{
  "status": "clarify",
  "reason_code": "SEMANTIC_AMBIGUOUS",
  "matched_table": "public.invoice_lines",
  "missing": "numeric_column_choice",
  "candidates": [
    {
      "table": "public.invoice_lines",
      "column": "qty"
    },
    {
      "table": "public.invoice_lines",
      "column": "unit_amount"
    }
  ],
  "message": "Matched public.invoice_lines. 'over 5' matches more than one numeric column (qty, unit_amount). This prompt is incomplete. Name the column and retry."
}

Choose column: qty or unit_amount, then retry with that name in the prompt.

Auth, POST, bind — that is the whole compile path

No SDK. No warehouse credential in our cloud. Three steps in your codebase: send the InsightITS JWT, POST the prompt, bind the returned params in the driver you already use.

01. Auth

Authorization: Bearer <InsightITS JWT>. Isolation is that email. Body tenant_id / userProfile cannot override it.

02. POST

POST /api/prismsql/v1/query/execute with prompt and schema_id. Success is sql_template + params. Clarify is HTTP 422 — do not execute.

03. Bind

Run the template in your warehouse with the params list. Hosted rows is always []. You keep the DSN.

import requests

r = requests.post(
    "https://www.insightits.com/api/prismsql/v1/query/execute",
    headers={"Authorization": f"Bearer {jwt}"},
    json={"prompt": prompt, "schema_id": schema_id},
)
body = r.json()
if body.get("status") == "clarify":
    raise SystemExit(body["message"])  # name a candidate column and retry
cur.execute(body["sql_template"], body["params"])  # your database, not ours

Upload the schema JSON in the dashboard first. This snippet is the hosted compile API, not a pip package. Handle clarify before you execute.

Edge-case playground

Documented compiles from harbor_clinic_v1 and acme_orders_v1 — the same statements tests lock. Isolation is a bound parameter. rows is always empty. This is not a warehouse result and not your schema until you sign in and compile live.

line items over 5

Prompt: invoice line items over 5 (harbor_clinic_v1)

qty and unit_amount are both numeric. The compiler lists them. It does not pick the first or prefer money.

{
  "status": "clarify",
  "reason_code": "SEMANTIC_AMBIGUOUS",
  "matched_table": "public.invoice_lines",
  "missing": "numeric_column_choice",
  "candidates": [
    {
      "table": "public.invoice_lines",
      "column": "qty"
    },
    {
      "table": "public.invoice_lines",
      "column": "unit_amount"
    }
  ],
  "message": "Matched public.invoice_lines. 'over 5' matches more than one numeric column (qty, unit_amount). This prompt is incomplete. Name the column and retry."
}

qty over 5

Prompt: invoice line items qty over 5 (harbor_clinic_v1)

Named column wins. Isolation is the JWT email placeholder used in docs.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoice_lines\".\"qty\", \"public\".\"invoice_lines\".\"unit_amount\" FROM \"public\".\"invoice_lines\" INNER JOIN \"public\".\"invoices\" ON \"public\".\"invoice_lines\".\"invoice_id\" = \"public\".\"invoices\".\"id\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoice_lines\".\"qty\" > %s LIMIT %s",
  "params": [
    "you@company.com",
    5,
    100
  ],
  "rows": [],
  "execution_result": null
}

unit_amount over 5

Prompt: invoice line items unit_amount over 5 (harbor_clinic_v1)

Named unit_amount. qty is still selected; the compare is on unit_amount.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoice_lines\".\"qty\", \"public\".\"invoice_lines\".\"unit_amount\" FROM \"public\".\"invoice_lines\" INNER JOIN \"public\".\"invoices\" ON \"public\".\"invoice_lines\".\"invoice_id\" = \"public\".\"invoices\".\"id\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoice_lines\".\"unit_amount\" > %s LIMIT %s",
  "params": [
    "you@company.com",
    5,
    100
  ],
  "rows": [],
  "execution_result": null
}

invoices last 30 days

Prompt: invoices last 30 days (harbor_clinic_v1)

Compiler injects INTERVAL on due_date. 30 is not a bound parameter. Timezone comes from the Harbor contract.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoices\".\"amount\", \"public\".\"invoices\".\"due_date\" FROM \"public\".\"invoices\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoices\".\"due_date\" >= (CURRENT_TIMESTAMP AT TIME ZONE 'America/Los_Angeles') - INTERVAL '30 days' ORDER BY \"public\".\"invoices\".\"due_date\" DESC LIMIT %s",
  "params": [
    "you@company.com",
    100
  ],
  "rows": [],
  "execution_result": null
}

invoices over 500 last 30 days

Prompt: invoices over 500 last 30 days (harbor_clinic_v1)

Amount bind is 500. Window digit 30 is not money.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoices\".\"id\", \"public\".\"invoices\".\"amount\", \"public\".\"invoices\".\"due_date\" FROM \"public\".\"invoices\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoices\".\"due_date\" >= (CURRENT_TIMESTAMP AT TIME ZONE 'America/Los_Angeles') - INTERVAL '30 days' AND \"public\".\"invoices\".\"amount\" > %s ORDER BY \"public\".\"invoices\".\"due_date\" DESC LIMIT %s",
  "params": [
    "you@company.com",
    500,
    100
  ],
  "rows": [],
  "execution_result": null
}

orders last 30 days

Prompt: orders last 30 days (acme_orders_v1)

created_at window. deleted_at is soft-delete (IS NULL), not the business date.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"orders\".\"amount\", \"public\".\"orders\".\"created_at\" FROM \"public\".\"orders\" WHERE \"public\".\"orders\".\"tenant_email\" = %s AND \"public\".\"orders\".\"created_at\" >= CURRENT_TIMESTAMP - INTERVAL '30 days' AND \"public\".\"orders\".\"deleted_at\" IS NULL ORDER BY \"public\".\"orders\".\"created_at\" DESC LIMIT %s",
  "params": [
    "you@company.com",
    50
  ],
  "rows": [],
  "execution_result": null
}

hygiene over 500

Prompt: hygiene over 500 (harbor_clinic_v1)

hygiene is an alias of appointments. No numeric column. Not remapped to invoice_lines.

{
  "status": "clarify",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "matched_table": "public.appointments",
  "missing": "numeric",
  "message": "Matched public.appointments. 'over 500' needs a numeric column (amount, qty, or similar) on that table. None is declared. This prompt is incomplete. Name the table that holds that number, or add that column to this table on your schema contract."
}

support tickets

Prompt: list my support tickets (harbor_clinic_v1)

tickets is not on Harbor. Not remapped to patients.

{
  "status": "refused",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "message": "That question does not match tables on your saved schema."
}

Sample compiles

Documented compiles from Harbor and acme_orders_v1. Isolation is a bound parameter. rows is always empty. These are not live warehouse results.

Last hygiene visits, recent first

Prompt: give me the last appointments for the hygiene and order them by recent time (harbor_clinic_v1)

Prompt ORDER BY overwrites the schema default (starts_at ASC). Isolation is the JWT email. visit_type binds hygiene.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"appointments\".\"starts_at\", \"public\".\"appointments\".\"visit_type\" FROM \"public\".\"appointments\" INNER JOIN \"public\".\"patients\" ON \"public\".\"appointments\".\"patient_id\" = \"public\".\"patients\".\"id\" WHERE \"public\".\"patients\".\"clinic_owner_email\" = %s AND \"public\".\"appointments\".\"visit_type\" = %s ORDER BY \"public\".\"appointments\".\"starts_at\" DESC LIMIT %s",
  "params": ["you@company.com", "hygiene", 100],
  "rows": [],
  "execution_result": null
}

Amount range + last 30 days

Prompt: invoices over 500 last 30 days (harbor_clinic_v1)

Compiler injects amount > 500 and a rolling 30-day window. The 30 is not bound as money. Timezone comes from the contract (America/Los_Angeles).

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoices\".\"id\", \"public\".\"invoices\".\"amount\", \"public\".\"invoices\".\"due_date\" FROM \"public\".\"invoices\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoices\".\"due_date\" >= (CURRENT_TIMESTAMP AT TIME ZONE 'America/Los_Angeles') - INTERVAL '30 days' AND \"public\".\"invoices\".\"amount\" > %s ORDER BY \"public\".\"invoices\".\"due_date\" DESC LIMIT %s",
  "params": ["you@company.com", 500.0, 100],
  "rows": [],
  "execution_result": null
}

Open invoices (default sort)

Prompt: list my open invoices (harbor_clinic_v1)

No sort language, so default_order (due_date DESC) applies. Status binds open. Tenant email is compiler-injected.

{
  "compile_only": true,
  "dialect": "postgresql",
  "sql_template": "SELECT \"public\".\"invoices\".\"id\", \"public\".\"invoices\".\"status\", \"public\".\"invoices\".\"amount\", \"public\".\"invoices\".\"due_date\" FROM \"public\".\"invoices\" WHERE \"public\".\"invoices\".\"clinic_owner_email\" = %s AND \"public\".\"invoices\".\"status\" = %s ORDER BY \"public\".\"invoices\".\"due_date\" DESC LIMIT %s",
  "params": ["you@company.com", "open", 100],
  "rows": [],
  "execution_result": null
}

Off-contract table — refused

Prompt: list my support tickets (harbor_clinic_v1)

Harbor has patients, appointments, and invoices. tickets is not remapped. The compiler refuses instead of inventing a join.

{
  "status": "refused",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "message": "That question does not match tables on your saved schema."
}

Matched table, missing column type — clarify

Prompt: hygiene appointments over 500 (harbor_clinic_v1)

hygiene is an alias of appointments. The compiler matched that table. over 500 needs a numeric column; appointments have none. It asks you to complete the prompt instead of inventing an amount or remapping to invoices.

{
  "status": "clarify",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "matched_table": "public.appointments",
  "missing": "numeric",
  "message": "Matched public.appointments. 'over 500' needs a numeric column (amount, qty, or similar) on that table. None is declared. Name the table that holds that number, or add that column to this table on your schema contract."
}

Matched table, no date — clarify

Prompt: invoice line items last 30 days (harbor_clinic_v1)

invoice_lines matched. last 30 days needs a date column. None is declared. The compiler does not borrow invoices.due_date unless the prompt names invoices (or a required join already supplies it).

{
  "status": "clarify",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "matched_table": "public.invoice_lines",
  "missing": "date",
  "message": "Matched public.invoice_lines. 'last 30 days' needs a date or timestamp column on that table. None is declared. Name a table that has a date, or add that column to this table on your schema contract."
}

Several numeric columns — name one

Prompt: invoice line items over 5 (harbor_clinic_v1)

qty and unit_amount are both numeric. The compiler lists them. It does not pick the first or prefer money.

{
  "status": "clarify",
  "reason_code": "SEMANTIC_AMBIGUOUS",
  "matched_table": "public.invoice_lines",
  "missing": "numeric_column_choice",
  "candidates": [
    {"table": "public.invoice_lines", "column": "qty"},
    {"table": "public.invoice_lines", "column": "unit_amount"}
  ],
  "message": "Matched public.invoice_lines. 'over 5' matches more than one numeric column (qty, unit_amount). Name the column and retry."
}

API documentation

Compile-only. JWT in, parameterized SQL out. rows is always empty. When a prompt cannot compile honestly, the API asks back with the table it matched and a list of candidate columns. It does not invent a column, pick the first of many, guess qty vs amount from the size of a number, or remap tickets onto patients.

Full reference (routes, reason codes, dialect matrix, improvers) is also a downloadable markdown file. File: /docs/prismsql-api.md.

Routes

MethodPathNotes
POST/query/executeCompile. Alias: /query/compile
POST/query/validateSame path without counting a paid compile when execute is false
GET/mePlan, quota, saved schemas, format.example, dialectMatrix, stripeReady
POST/schemas/validateValidate only. Returns required vs recommended checklist
GET/schemasList saved contracts
POST/schemasSave a contract
DELETE/schemas/<schema_id>Remove a saved contract
POST/checkoutStripe Checkout for Developer / Pro
POST/checkout/confirmAfter Stripe returns; writes subscriber plan

Response shapes

Success (HTTP 200)

compile_only: true. Isolation is a bound JWT email, never interpolated. Hosted rows is always [].

{
  "status": "success",
  "compile_only": true,
  "sql_template": "SELECT ... WHERE ... = %s LIMIT %s",
  "params": ["you@company.com", "open", 100],
  "rows": [],
  "execution_result": null
}

Clarify — name a column (HTTP 422)

status: clarify. candidates[] lists columns (or tables). Retry by naming one in the prompt.

{
  "status": "clarify",
  "reason_code": "SEMANTIC_AMBIGUOUS",
  "matched_table": "public.invoice_lines",
  "missing": "numeric_column_choice",
  "candidates": [
    {"table": "public.invoice_lines", "column": "qty"},
    {"table": "public.invoice_lines", "column": "unit_amount"}
  ],
  "message": "Matched public.invoice_lines. 'over 5' matches more than one numeric column (qty, unit_amount). Name the column and retry."
}

Clarify — matched table, missing type (HTTP 422)

hygiene is an alias of appointments. The table matched. over 500 has nowhere to bind. Not “unknown table.”

{
  "status": "clarify",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "matched_table": "public.appointments",
  "missing": "numeric",
  "message": "Matched public.appointments. 'over 500' needs a numeric column (amount, qty, or similar) on that table. None is declared."
}

Refused — unknown table (HTTP 422)

tickets is not remapped to patients or invoices.

{
  "status": "refused",
  "reason_code": "SEMANTIC_UNSUPPORTED",
  "message": "That question does not match tables on your saved schema."
}

Date columns

SituationResult
Exactly one date on the FROM tableAssume it (appointments → starts_at, invoices → due_date). soft_delete timestamps such as deleted_at are excluded.
Prompt names a date or a declared aliasUse that column (starts_at last 30 days, overdue → due_date when aliased).
Several dates, unnamedclarify + candidates[] (starts_at, created_at). Do not pick the first.
Window language, no date columnclarify, matched_table, missing: date (invoice line items last 30 days).

Numeric columns

SituationResult
Exactly one numeric (ids excluded)Assume it (invoices.amount, order_items.qty).
Prompt names a numericUse that column (qty over 5).
Several named comparesBind each (qty over 5 and unit_amount over 10).
Several numerics, unnamedclarify + candidates[] (qty, unit_amount). Do not pick the first or prefer money.
Several unbound amounts and several columnsclarify: name each column. We do not know which number belongs where.
Two compares, one numericBoth AND on that column (invoices over 500 under 1000).
between / from–toOne range (two digits, one clause). last 30 days digits are not amounts.
Number range, no numeric columnclarify, matched_table, missing: numeric (hygiene over 500).
Value magnitudeNever used. over 5 can be qty or a $5 unit_amount. We have no warehouse min/max.

Range language

PromptCompiler inject
this week / last 7 days / past weekgte_days_ago 7
last N days|weeks|months|years, last month, last yeargte_days_ago N (month=30, year=365, rolling)
next N days / next weekgte_now + lte_days_ahead
upcoming / bare nextgte_now
overdue / past duelte_now on the named or unique date
over / above / greater than / more thangt
under / below / less thanlt
at least / at mostgte / lte
between X and Y / from X to Ygte + lte

Edge cases

PromptResultWhy
list my support tickets (harbor_clinic_v1)refused SEMANTIC_UNSUPPORTEDtickets is not on the contract. Not remapped to patients.
hygiene appointments over 500 (harbor_clinic_v1)clarify SEMANTIC_UNSUPPORTED · matched public.appointments · missing numerichygiene is an alias of appointments. The table matched. No amount/qty column. Not “unknown table.”
invoice line items last 30 days (harbor_clinic_v1)clarify SEMANTIC_UNSUPPORTED · matched public.invoice_lines · missing dateinvoice_lines has qty and unit_amount, no date.
invoice line items qty over 5 last 30 days (harbor_clinic_v1)clarify · missing dateNamed qty would bind, but the time window still needs a date on that table.
invoices over 500 last 30 days (harbor_clinic_v1)compile amount > 500 and due_date last 30 daysOne numeric, one date. Window digit 30 is not an amount bind.
order items over 5 (acme_orders_v1)compile qty > 5Only eligible numeric on order_items.
invoice line items over 5 (harbor_clinic_v1)clarify SEMANTIC_AMBIGUOUS · candidates qty, unit_amountDo not pick the first column. Name qty or unit_amount.
invoice line items qty over 5 (harbor_clinic_v1)compile qty > 5Named column wins.
invoice line items qty over 5 and unit_amount over 10 (harbor_clinic_v1)compile both filtersEach compare names its column.
invoices over 500 under 1000 (harbor_clinic_v1)compile amount > 500 AND amount < 1000Two compares, one numeric column.
invoice line items over 5 under 10 (harbor_clinic_v1)clarify · more than one amount, more than one columnWe do not know which number belongs to qty vs unit_amount.
hygiene appointments last 30 days (harbor_clinic_v1)compile starts_at windowOne date column. Unique date is assumed.
open orders over 100 last 7 days (acme_orders_v1)compile created_at window, not deleted_atsoft_delete timestamps are not the business date.
last 30 days (starts_at and created_at both declared) (two-date appointments)clarify · candidates starts_at, created_atDo not prefer starts_at. Name the column.
starts_at last 30 days (same two-date table) (two-date appointments)compile starts_at windowNamed date wins.
from January to March (any)not compiledNo numbers in the prompt. We do not invent calendar dates.
IR names secrets (table not in retrieved subgraph) (any)SCHEMA_UNKNOWN_TABLESubgraph check runs before range inject, so a leaked table is not labeled “no amount column.”

Reason codes

CodeHTTPstatusMeaning
SEMANTIC_UNSUPPORTED422refused or clarifyUnknown table, or matched table missing date/numeric (then matched_table + missing).
SEMANTIC_AMBIGUOUS422clarifyTwo tables, or several unnamed date/numeric columns (candidates[]).
SCHEMA_UNKNOWN_TABLE422refusedTable not on the eligible subgraph or contract.
SCHEMA_UNKNOWN_COLUMN422refusedColumn not on the saved schema, including unknown ORDER BY.
SCHEMA_UNKNOWN_JOIN_PATH422refusedJoin is not a declared path_id.
SCHEMA_NOT_CONFIGURED409refusedSave a schema in the dashboard first.
SCHEMA_INVALID422refusedUploaded JSON failed validation.
QUOTA_EXCEEDED429refusedMonthly compile quota used.
TIER_LIMIT403refusedDialect or action not on this plan.
AUTH_USER_DENIED401/403refusedMissing or invalid JWT.
TYPE_BIND_MISMATCH422refusedBind did not match the prompt span or type.
SYSTEM_LLM_UNAVAILABLE503refusedIR model unreachable.

What this API does not do

Prompt to SQL

PrismGuard

Ingress check on the natural-language prompt. Fail closed on injection / exfil.

VectorPrism

Scores the prompt against chunks stored for your schema. The model sees an eligible subgraph, not the whole catalog.

Query IR 1.1

Closed JSON: declared columns, path_id joins, AND filters, relative time, allow-listed count/sum, limit. No SQL, no ON, no raw expressions.

PrismManifest

Hostile-IR validation against the full saved contract: schema, types, policy, isolation.

Compiler

Deterministic binds, quoted identifiers, compiler-injected isolation, required LIMIT, prompt ORDER BY, rolling date windows, and numeric over/under/between on declared columns.

Dialect printer

Final layer: PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, Oracle, Snowflake, Redshift, BigQuery, Databricks SQL — gated by plan.

How PrismSQL differs from text-to-SQL and NL2SQL products

Buyers search text to SQL, NL2SQL, natural language to SQL, and schema-aware generation. Most tools in that market generate SQL and then execute it. PrismSQL compiles parameterized SQL from the schema contract you uploaded. We do not take a DSN, we do not return your rows, and the model never writes the statement.

Market patternTypical productPrismSQL
LLM writes the SQLChatGPT, Copilot, and most “AI SQL” plugins emit SELECT text. Joins, literals, and tenancy live in the prompt.The model outputs a closed Query IR (tables, filters, join path_ids). The compiler is the only component that writes SQL. Raw SQL keys and freeform ON clauses are refused.
Vendor-cloud text-to-SQLConnect a DSN. The vendor generates SQL, runs it, and returns rows. Your warehouse credential sits in their cloud.Hosted API is compile-only: sql_template + params, rows: [], execution_result: null. You keep the DSN. We do not connect to your warehouse and we do not return InsightITS CRM rows.
RAG NL2SQL that executesSchema metadata in a vector store, then generated SQL against a live database. Accuracy is a chat feature.You upload a JSON schema contract. We store and embed that contract on your InsightITS login (HashingEncoder 768d — not a trained finance adapter). Compile uses that contract only. You run the statement.
MCP / agent database serversThe tool connects the model to the warehouse so the agent can “query the database.”An MCP client or local agent calls our compile API. No warehouse credential is required or accepted. Isolation is injected from the JWT email, not from body tenant_id / userProfile / mode.
Generic ANSI SQLOne LIMIT / ? template swapped across engines. Oracle and SQL Server get invalid syntax.Shared IR, then a dialect printer: quoting, placeholders, LIMIT vs FETCH. Oracle emits FETCH FIRST. SQL Server emits OFFSET/FETCH. BigQuery uses @pN. Ten printers, gated by plan.

Search terms this page is written for

These are buyer terms from the 2026 NL2SQL / text-to-SQL market that match what PrismSQL actually ships. We do not rank for “chat with any database,” Spider/BIRD leaderboards, or SOC 2.

Dialect printers by plan

Dialect is a final compiler layer after the shared IR, Manifest check, and isolation inject. Sandbox and Developer print PostgreSQL. Pro adds MySQL, MariaDB, SQLite, Snowflake, and Redshift. Enterprise adds SQL Server, Oracle, BigQuery, and Databricks SQL. Oracle emits FETCH FIRST, not LIMIT. SQL Server emits OFFSET/FETCH, not LIMIT.

DatabaseSandbox / DeveloperProEnterprise
PostgreSQLYesYesYes
MySQLYesYes
MariaDBYesYes
SQLiteYesYes
SnowflakeYesYes
Amazon RedshiftYesYes
Microsoft SQL ServerYes
Oracle DatabaseYes
Google BigQueryYes
Databricks SQLYes

Need an adjustment for your application?

If your product needs a compiler or contract change we do not ship yet — a named range, an extra declared operator, a join path shape, a dialect detail, or wiring into your agent/MCP runtime — contact us. We add it for your integration. The hosted API stays compile-only: you keep the DSN, we still do not invent SQL, and we still do not connect to your warehouse.

Contact us about your integration

Pricing

Sandbox is free. Developer is $49/month at the same 1-schema / 5,000-compile PostgreSQL envelope, billed with Stripe in the dashboard. Pro is $399/month (listed in the $299–$499 range) with 3 schemas, 50,000 compiles, $8 per extra 1,000 compiles, and six dialects. Enterprise starts at $2,000/month ($24k–$60k+/year), invoiced, with unlimited schemas and all ten dialect printers. We do not claim SOC 2 on this page.

Sandbox — Free

1 schema · 5,000 compiles / month. PostgreSQL only. Provisioned on first dashboard visit. Upload one contract and compile parameterized SQL. Stripe is not required to start.

Developer — $49 / mo

1 schema · 5,000 compiles / month. PostgreSQL only · Stripe. Paid plan at the same envelope as Sandbox. Stripe Checkout on the PrismSQL dashboard tab. After payment succeeds, your subscriber plan is Developer and the compile API keeps the 5,000/month quota.

Pro / Team — $399 / mo

3 schemas · 50,000 compiles / month. Overage $8 per 1,000 compiles. Stripe Checkout on the dashboard tab. After payment succeeds, the compile API uses the Pro quota (50,000/month) and six dialect printers: PostgreSQL, MySQL, MariaDB, SQLite, Snowflake, Redshift.

Enterprise — From $2,000 / mo

$24k–$60k+ / year · unlimited schemas. Invoice · all ten dialects. SQL Server, Oracle, BigQuery, and Databricks SQL printers, volume, and VPC/on-prem compile options. Contact sales — we do not claim SOC 2 on this page.

FAQ

Does PrismSQL query InsightITS’s database when I call the API?

No. After you log in, upload your schema contract in the dashboard PrismSQL tab. The API authenticates you, loads that stored contract, and compiles parameterized SQL for your tables. We do not return InsightITS CRM rows and we do not connect to your warehouse.

Why not let ChatGPT write the SQL?

A model that emits SQL can invent joins, interpolate values, and skip tenancy. PrismSQL forces a closed Query IR (no SQL, no ON clauses), validates it against your contract, injects isolation from the JWT, and prints parameterized SQL. The compiler is the only component that writes the statement.

How does a prompt become SQL?

PrismGuard checks the prompt. VectorPrism scores it against embeddings stored when you saved the schema (tables and join paths; a new upload replaces those chunks). Eligible path_ids go to a closed Query IR. PrismManifest validates that IR against the full contract. A deterministic compiler emits parameterized SQL and injects isolation. A dialect printer emits quoting, placeholders, and LIMIT/FETCH for the contract dialect. You run sql_template + params in your environment.

What do I upload?

A JSON schema contract: schema_id, dialect (one of the ten printers, gated by plan), tables keyed as schema.table with allow_columns, column_types, and isolation, plus join_paths for every allowed join. Recommended warehouse facts — timezone, indexes, column_values, operators, default_order, soft_delete, cardinality — appear on the Validate checklist. Missing recommended fields do not block save; the matching improver is a no-op. We never invent a column. The dashboard shows the exact format and an example.

What is isolation?

A compiler-injected predicate so generated SQL cannot scan another tenant. jwt_email binds the logged-in InsightITS email into the column you name. via_join requires a declared join path. none means you will enforce tenancy in your own database. constant injects a value you stored on the contract.

How is PrismSQL priced?

Sandbox is free (1 schema, 5,000 compiles/month, PostgreSQL). Developer is $49/month at that same envelope, billed with Stripe in the dashboard. Pro/Team is $399/month (listed in the $299–$499 range) with 3 schemas, 50,000 compiles, $8 per extra 1,000 compiles, and PostgreSQL, MySQL, MariaDB, SQLite, Snowflake, and Redshift. After Stripe Checkout succeeds, the dashboard confirms the session and writes your subscriber plan — the next compile uses that quota (5,000 on Developer, 50,000 on Pro, unlimited on Enterprise). Enterprise starts at $2,000/month ($24k/year), invoiced, and adds SQL Server, Oracle, BigQuery, and Databricks SQL plus volume and VPC/on-prem options.

Do you run the SQL against my database?

Not on the hosted API. The response is sql_template plus params. You run that statement in your environment. Live EXPLAIN cost guardrails against your warehouse and VPC/on-prem execution are Enterprise options — contact sales. We will not pretend to return your rows from our Postgres.

Where do I see my license and payments?

Log into insightits.com, open the dashboard, then the PrismSQL tab. Sandbox is provisioned on first visit. Developer and Pro checkout use Stripe from that tab. When Checkout returns, the tab confirms the session and shows the new plan, compile quota, and dialect printers. Super-admins can also set plan and inspect compiles, payments, and schemas from the admin PrismSQL tab. Enterprise is invoiced.

Is PrismSQL the same as text-to-SQL or NL2SQL?

It is in that market: natural-language questions become SQL. It is not “chat with any database,” not arbitrary English → SQL, and it is not a vendor that runs the query. The compiler owns last/next N days, over/under/between on a declared amount column, and prompt ORDER BY (recent / last / order by) so those facts do not depend on the model writing SQL. Unknown tables refuse with SEMANTIC_UNSUPPORTED. The API returns parameterized SQL you run.

How is this different from ChatGPT or a RAG SQL library that executes queries?

Those products either let the model write SQL or they take a live DSN and return rows. PrismSQL does neither. Joins must be declared join_paths. Isolation is compiler-injected from the JWT. The hosted response is sql_template + params with an empty row set. We do not publish Spider or BIRD scores and we do not claim SOC 2.

Can an MCP client or agent use PrismSQL?

Yes, as a compile boundary: the agent sends a prompt and JWT, receives parameterized SQL, and runs that statement in the environment that already holds the warehouse credential. PrismSQL is not an MCP server that connects to your database.

What happens if I ask about tables that are not on my contract?

The compiler refuses with SEMANTIC_UNSUPPORTED (HTTP 422) when the English does not match any table on your contract — “support tickets” on a dental schema is not remapped to patients. If the table did match but the filter cannot bind (hygiene over 500 on appointments, which has no amount column; line items last 30 days, which has no date), the API returns status: clarify, names matched_table, and explains the missing column type. If several numeric or date columns could match, it returns candidates[] and asks which column. See the API docs on this page and /docs/prismsql-api.md.

Which SQL dialects do you compile?

Sandbox and Developer print PostgreSQL. Pro adds MySQL, MariaDB, SQLite, Snowflake, and Redshift. Enterprise adds SQL Server, Oracle, BigQuery, and Databricks SQL. Dialect is a final printer after the shared IR — Oracle does not emit LIMIT, SQL Server does not emit LIMIT. The account pin (dashboard picker) is the compile dialect; the request body cannot switch it.

Do “last 30 days” and “order by recent” work if the model omits them?

Yes. Ranges and prompt ORDER BY are compiler-owned. last 30 days / last month / last year are rolling windows (month = 30 days). next N days is a bounded future window. A unique date column is assumed (soft-delete timestamps skipped). Several dates ask which one. over 500 and between 100 and 500 bind on the table’s only declared numeric column, or on a named column such as qty. If the table has qty and unit_amount and you do not name one, the compiler returns candidates[] — it does not pick the first or guess from the size of the number. order them by recent time overwrites schema default_order. order by last name is the last_name column, not recency. last 7 days is a window, not a sort. We do not invent calendar dates that are not in the prompt.

Where is the compile API documented?

On this page under API documentation, and as markdown at /docs/prismsql-api.md. The reference covers routes, success/clarify/refused shapes, date and numeric column selection, every locked edge case (hygiene over 500, line items last 30 days, unnamed qty vs unit_amount, two date columns), and reason codes. The dashboard PrismSQL tab also compiles against your saved contract. The landing playground shows documented Harbor / acme_orders compiles without a warehouse; signed-in live compile calls POST /query/execute against your saved schema.

What happens when the prompt is incomplete?

The API does not guess. Several unnamed numeric columns (invoice line items over 5) return status: clarify with candidates[] so your UI can render Choose column chips. A matched table missing the column type (hygiene over 500 on appointments) also clarifies. Unknown tables refuse SEMANTIC_UNSUPPORTED. Naming the column in the retry prompt compiles. See the clarification loop on this page.

How much code is the compile integration?

Three steps: send Authorization Bearer JWT, POST /api/prismsql/v1/query/execute with prompt and schema_id, bind sql_template + params in your warehouse driver. There is no SDK and we do not take a DSN. If status is clarify, do not execute — name a candidate and retry. Upload the schema JSON in the dashboard first.

What if our application needs something PrismSQL does not compile yet?

Contact us. If you need a special adjustment for your integration — a range pattern, an extra declared operator, a join-path shape, a dialect detail, or help calling the compile API from your agent — we add it for that application. The hosted product stays compile-only: you keep the warehouse credential, the model still does not write SQL, and we still do not connect to your database.

Capabilities

Your schema, stored on your account

Dashboard PrismSQL tab: upload tables, isolation, join_paths, and optional indexes/enums/timezone. Validate shows required vs recommended fields. We save the contract for your login and never invent omitted columns.

The model cannot invent SQL

Closed Query IR (no SQL, no ON). Compiler owns ranges (last 30 days, over 500, between) and prompt ORDER BY. Isolation is injected from the JWT. Ten dialect printers, gated by plan.

Clear pricing in the same tab

Sandbox free (PostgreSQL). Developer $49/mo. Pro $399/mo (six dialects). Enterprise from $2,000/mo (all ten dialects, invoiced).

Install

Not a pip package. Log in → dashboard.html#prismsql → upload schema JSON → call POST /api/prismsql/v1/query/execute with a JWT.

Pricing

Sandbox free then Developer $49/mo (PostgreSQL). Pro $399/mo (Postgres, MySQL, MariaDB, SQLite, Snowflake, Redshift). Enterprise from $2,000/mo adds SQL Server, Oracle, BigQuery, Databricks SQL.

Frequently asked questions

Does PrismSQL query InsightITS’s database when I call the API?

No. After you log in, upload your schema contract in the dashboard PrismSQL tab. The API authenticates you, loads that stored contract, and compiles parameterized SQL for your tables. We do not return InsightITS CRM rows and we do not connect to your warehouse.

Why not let ChatGPT write the SQL?

A model that emits SQL can invent joins, interpolate values, and skip tenancy. PrismSQL forces a closed Query IR (no SQL, no ON clauses), validates it against your contract, injects isolation from the JWT, and prints parameterized SQL. The compiler is the only component that writes the statement.

How does a prompt become SQL?

PrismGuard checks the prompt. VectorPrism scores it against embeddings stored when you saved the schema (tables and join paths; a new upload replaces those chunks). Eligible path_ids go to a closed Query IR. PrismManifest validates that IR against the full contract. A deterministic compiler emits parameterized SQL and injects isolation. A dialect printer emits quoting, placeholders, and LIMIT/FETCH for the contract dialect. You run sql_template + params in your environment.

What do I upload?

A JSON schema contract: schema_id, dialect (one of the ten printers, gated by plan), tables keyed as schema.table with allow_columns, column_types, and isolation, plus join_paths for every allowed join. Recommended warehouse facts — timezone, indexes, column_values, operators, default_order, soft_delete, cardinality — appear on the Validate checklist. Missing recommended fields do not block save; the matching improver is a no-op. We never invent a column. The dashboard shows the exact format and an example.

What is isolation?

A compiler-injected predicate so generated SQL cannot scan another tenant. jwt_email binds the logged-in InsightITS email into the column you name. via_join requires a declared join path. none means you will enforce tenancy in your own database. constant injects a value you stored on the contract.

How is PrismSQL priced?

Sandbox is free (1 schema, 5,000 compiles/month, PostgreSQL). Developer is $49/month at that same envelope, billed with Stripe in the dashboard. Pro/Team is $399/month (listed in the $299–$499 range) with 3 schemas, 50,000 compiles, $8 per extra 1,000 compiles, and PostgreSQL, MySQL, MariaDB, SQLite, Snowflake, and Redshift. After Stripe Checkout succeeds, the dashboard confirms the session and writes your subscriber plan — the next compile uses that quota (5,000 on Developer, 50,000 on Pro, unlimited on Enterprise). Enterprise starts at $2,000/month ($24k/year), invoiced, and adds SQL Server, Oracle, BigQuery, and Databricks SQL plus volume and VPC/on-prem options.

Do you run the SQL against my database?

Not on the hosted API. The response is sql_template plus params. You run that statement in your environment. Live EXPLAIN cost guardrails against your warehouse and VPC/on-prem execution are Enterprise options — contact sales. We will not pretend to return your rows from our Postgres.

Where do I see my license and payments?

Log into insightits.com, open the dashboard, then the PrismSQL tab. Sandbox is provisioned on first visit. Developer and Pro checkout use Stripe from that tab. When Checkout returns, the tab confirms the session and shows the new plan, compile quota, and dialect printers. Super-admins can also set plan and inspect compiles, payments, and schemas from the admin PrismSQL tab. Enterprise is invoiced.

Is PrismSQL the same as text-to-SQL or NL2SQL?

It is in that market: natural-language questions become SQL. It is not “chat with any database,” not arbitrary English → SQL, and it is not a vendor that runs the query. The compiler owns last/next N days, over/under/between on a declared amount column, and prompt ORDER BY (recent / last / order by) so those facts do not depend on the model writing SQL. Unknown tables refuse with SEMANTIC_UNSUPPORTED. The API returns parameterized SQL you run.

How is this different from ChatGPT or a RAG SQL library that executes queries?

Those products either let the model write SQL or they take a live DSN and return rows. PrismSQL does neither. Joins must be declared join_paths. Isolation is compiler-injected from the JWT. The hosted response is sql_template + params with an empty row set. We do not publish Spider or BIRD scores and we do not claim SOC 2.

Can an MCP client or agent use PrismSQL?

Yes, as a compile boundary: the agent sends a prompt and JWT, receives parameterized SQL, and runs that statement in the environment that already holds the warehouse credential. PrismSQL is not an MCP server that connects to your database.

What happens if I ask about tables that are not on my contract?

The compiler refuses with SEMANTIC_UNSUPPORTED (HTTP 422) when the English does not match any table on your contract — “support tickets” on a dental schema is not remapped to patients. If the table did match but the filter cannot bind (hygiene over 500 on appointments, which has no amount column; line items last 30 days, which has no date), the API returns status: clarify, names matched_table, and explains the missing column type. If several numeric or date columns could match, it returns candidates[] and asks which column. See the API docs on this page and /docs/prismsql-api.md.

Which SQL dialects do you compile?

Sandbox and Developer print PostgreSQL. Pro adds MySQL, MariaDB, SQLite, Snowflake, and Redshift. Enterprise adds SQL Server, Oracle, BigQuery, and Databricks SQL. Dialect is a final printer after the shared IR — Oracle does not emit LIMIT, SQL Server does not emit LIMIT. The account pin (dashboard picker) is the compile dialect; the request body cannot switch it.

Do “last 30 days” and “order by recent” work if the model omits them?

Yes. Ranges and prompt ORDER BY are compiler-owned. last 30 days / last month / last year are rolling windows (month = 30 days). next N days is a bounded future window. A unique date column is assumed (soft-delete timestamps skipped). Several dates ask which one. over 500 and between 100 and 500 bind on the table’s only declared numeric column, or on a named column such as qty. If the table has qty and unit_amount and you do not name one, the compiler returns candidates[] — it does not pick the first or guess from the size of the number. order them by recent time overwrites schema default_order. order by last name is the last_name column, not recency. last 7 days is a window, not a sort. We do not invent calendar dates that are not in the prompt.

Where is the compile API documented?

On this page under API documentation, and as markdown at /docs/prismsql-api.md. The reference covers routes, success/clarify/refused shapes, date and numeric column selection, every locked edge case (hygiene over 500, line items last 30 days, unnamed qty vs unit_amount, two date columns), and reason codes. The dashboard PrismSQL tab also compiles against your saved contract. The landing playground shows documented Harbor / acme_orders compiles without a warehouse; signed-in live compile calls POST /query/execute against your saved schema.

What happens when the prompt is incomplete?

The API does not guess. Several unnamed numeric columns (invoice line items over 5) return status: clarify with candidates[] so your UI can render Choose column chips. A matched table missing the column type (hygiene over 500 on appointments) also clarifies. Unknown tables refuse SEMANTIC_UNSUPPORTED. Naming the column in the retry prompt compiles. See the clarification loop on this page.

How much code is the compile integration?

Three steps: send Authorization Bearer JWT, POST /api/prismsql/v1/query/execute with prompt and schema_id, bind sql_template + params in your warehouse driver. There is no SDK and we do not take a DSN. If status is clarify, do not execute — name a candidate and retry. Upload the schema JSON in the dashboard first.

What if our application needs something PrismSQL does not compile yet?

Contact us. If you need a special adjustment for your integration — a range pattern, an extra declared operator, a join-path shape, a dialect detail, or help calling the compile API from your agent — we add it for that application. The hosted product stays compile-only: you keep the warehouse credential, the model still does not write SQL, and we still do not connect to your database.

Official package links: PrismSQL interactive demo

View PrismSQL in shop