New benchmark Every run, recordedAn optional ClickHouse run store for history, the event log and usage: every run the Rust data plane serves is recorded, in about 13 bytes, with reads in milliseconds at 250 million runs. Experimental, since 0.45. Read the story The numbers
{{ pillVersion }} is out: {{ pillNote }} See what's new → 16/19of an independent agent-safety checklist, covered in the server Read the comparison →

One governed gate between your databases
and everything that asks them for data.

Write the SQL once. QueryAPIGate publishes it as a REST endpoint, an MCP tool for AI agents, a live event stream and a scheduled export. Each call checks who is asking and what they may see, and leaves a record.

{{ installFile }}
{{ p.code }}
{{ p.note }} {{ lk.t }}
All install options → Reference architectures and measured performance →
Self-hosted: your data never leaves Signed releases with provenance and SBOM Open source, Apache-2.0 Python 3.11+, one process
9database types
5front doors
8output formats
~50client languages
65how-to guides
PostgreSQLMySQLSQLiteDuckDBClickHouseMongoDBTrino expH2 expGeneric JDBC exp

PostgreSQL, MySQL, SQLite, DuckDB, ClickHouse and MongoDB are Tier 1: under the compatibility promise and tested against the real database in CI. Trino, H2 and generic JDBC are experimental, and labelled so in the product. Files in S3, GCS, R2, over HTTPS or on disk read through DuckDB.

The support matrix →
RESTGET /q/<name>MCPqueryapigate mcpEventsGET /eventsExportsqueryapigate exportManagement/api/v1

One saved query behind every door, and the same eight stages on every call: identity, policy, execution, record.

Follow a call through the stages →
JSONNDJSONCSVTSVXMLYAMLXLSXPARQUET

Paged by default. Constant-memory streaming with ?stream=true for CSV, TSV, NDJSON and Parquet, however large the result; queryapigate export writes the same formats to a file, a bucket or a folder.

Reference · query parameters →
PythonTypeScriptJavaGoC#KotlinRubyRustPHPSwiftand about 40 more

Every server publishes a complete OpenAPI 3.0 spec with each saved query as its own typed endpoint. Point OpenAPI Generator at it and every query becomes a typed method, with parameter rules checked before the request is sent.

Generate a client →

Short how-to guides in seven categories, from the first endpoint to a SIEM stream, each run against a real server in CI. Five reading paths put them in order, and every box of the architecture diagram has a path of its own.

All guides, with times and outcomes →

From caller to database, through one core

How it fits together

Every front door runs the same checks, so an AI agent's call is governed exactly like an app's. The core is the product; the front doors and drivers plug into it. Write the SQL once; QueryAPIGate publishes it as a REST endpoint, an MCP tool, a live event stream and a scheduled export, and reports every call to the systems you name. An optional Rust data plane serves saved-query reads from the core's own decisions, and an optional ClickHouse run store keeps every run's record at that rate. Both are experimental.

Who callsApps, partners, AI agents, people, pipelinesBackends and dashboards, scoped partner keys, any MCP client, the Console through your SSO, cron and Kubernetes CronJobs.
In front, optionalRust data plane ExpOn the public port: serves saved-query reads from the core's own plans and forwards everything else. Every decision stays in the core.
Front doorsREST · MCP · live events · exports · /api/v1One endpoint per saved query, saved queries as agent tools, server-sent events, scheduled exports and the management API.
AsksIdentity provider · secret provider · shared stateTokens are checked against your identity provider over JWKS and OIDC, credentials come from Vault or AWS, and Redis or the PostgreSQL store hold cache, limits and quotas across instances. Answered, never stored.
The governed coreIdentity → policy → execution → recordIdentify the caller, apply its limits, check the grant, validate parameters, guard the SQL, run it, mask and format, record it.
Your dataDatabases, files and deliveriesPostgreSQL, MySQL, SQLite, DuckDB, ClickHouse and MongoDB, plus Trino, H2 and JDBC; Parquet, CSV and JSON in S3, GCS or R2.
Reports toLog · traces · metrics · audit · run storeEach call goes to stdout, OpenTelemetry, Prometheus and your SIEM as counts, timings and audit entries, never a row or a credential. Run history, events and usage can be kept in ClickHouse (experimental).
Front doors

Save a query once. Serve it five ways.

The same saved query behind every door, and the same eight stages on every call: identity, policy, execution, record. Pick a door, follow one call through, see what each stage produces, and what the call gets back when a stage refuses.

PlaygroundTry every door in your browserPick a key, change a parameter, make any stage refuse. Nothing to install. Open it
the call as one trace · eight spans · hover one for its stage{{ totalMs }} · every span, in the Playground →
  1. {{ st.num }} · {{ st.ms }}{{ st.title }}
Stage {{ cur.num }} · {{ cur.layer }} {{ cur.status }}cumulative {{ cur.elapsed }}

{{ cur.title }}

{{ cur.desc }}

{{ r.k }}{{ r.v }} {{ r.mark }}
Governance · your data

The controls on every call, and everything they reach

QueryAPIGate ~ governance · your data{{ gov.counter }}

Governed, not just exposed

Read-only by default. A single-statement SQL guard blocks writes and multi-statement injection unless a connection or key explicitly opts in. Every call passes the same four controls whether it comes from an app, a partner key or an AI agent. The security model →

Governance01

Identity

Scoped API keys, reusable roles, named administrators with owner, admin, developer and auditor roles. App users by JWT / JWKS.

Governance02

Policy

Per-query and collection grants, table allow-lists, write ceilings, per-user values bound from token claims, rate limits, IP allow-lists, key expiry.

Governance03

Masking

Column masking traced to source columns through joins and aliases with sqlglot, applied before the response is formatted, in every output format.

Governance04

Record

Audit log of who changed what, run history for every query, alerts on failures, Prometheus /metrics.

Every major database, one interface

Native drivers, plus generic JDBC for anything with a driver jar. Point a connection at a folder or bucket of Parquet, CSV or JSON and each file becomes a view, through DuckDB.

{{ d.name }} exp

{{ catNote }}

Tier 1 · every feature, tested against a real server in CIexp · experimental, may change in a minor release

Files, through DuckDBGuide 41 →

No database to load them into

A connection reads exactly the paths you allow; each file becomes a view, and a saved query over it is an endpoint like any other.

Off until every layer agrees

Read-only by default. A server ceiling, then each key, can only narrow what is allowed, down to a single verb on a single query.

Read-only by default, the same four controls for every caller, and one saved-query interface over nine database types and files.The security model →
Platform

Run it like the rest of your platform

config diff · applyGuide 55 →

Configuration as code

The whole setup as one YAML file with no secret in it: diffed on every pull request, applied all or nothing on merge, and locked on prod if you want it.

Helm chartKubernetes →

GitOps on Kubernetes

A Helm chart for one pod or several. Argo CD or Flux syncing it is the deploy, configuration included.

Support policySupport →

Upgrades you can plan

Every store from an earlier release upgrades, or refuses clearly, tested in CI. A written compatibility promise, and rolling upgrades on several instances.

Compared with a hand-rolled API

What you stop writing

Each column is something you would build and maintain per endpoint, and what QueryAPIGate gives every saved query instead.

Endpoints

QueryAPIGate: GeneratedSave the SQL. The endpoint, OpenAPI and Postman collection are generated.Guide 01 →
By hand: Written per endpointController, repository layer, serializer, pagination.

Access

QueryAPIGate: Built inScoped keys, roles, limits and expiry, managed in the Console or /api/v1.Guide 13 →
By hand: You build itAuth middleware, key storage, rate limiting, per-client scopes.

Input safety

QueryAPIGate: On every callTyped parameters, always bound. A fuzz-tested SQL guard on every call.Guide 06 →
By hand: Reviewed per endpointParameter validation and injection defences, checked by hand each time.

Every client

QueryAPIGate: One queryThe same saved query behind REST, MCP, SSE and the export CLI.The five doors →
By hand: One integration eachA second integration for AI agents, a third for exports, a fourth for events.

Observability

QueryAPIGate: Out of the boxStructured logs, request IDs, Prometheus metrics, a Grafana dashboard and an audit log.Guide 35 →
By hand: You build itLogging, metrics, audit trail, dashboards.
Client libraries

A typed client in your team's language, generated in one command

Every server publishes a complete OpenAPI 3.0 spec, checked against the official validator in CI, with each saved query as its own typed endpoint. Point OpenAPI Generator at it and get a client in any of its roughly 50 languages: methods named after your queries, parameters typed from their rules, nothing written by hand.

TypeScript✓Python✓Java✓GoC#KotlinSwiftRustPHPRubyDartScala+ about 40 more

✓ generated and called against a live server. Generate with a partner's key and their client contains only the queries that key may call. Regenerate when you publish a new query version.

{{ l.t }}
Where it's going

Toward 1.0

1.0.0-rc1 · nextThe freeze: the compatibility promise becomes a contract
Full roadmap →

Open source, built in the open

Apache-2.0 since 0.39: use, modify and redistribute it for any purpose, including as a service. Issues, discussions and 65 how-to guides live on GitHub. See what it's built with →

latest {{ latestTag }}PyPI {{ pypiVersion }}open issues {{ issues }}licence {{ licence }}
Star on GitHub{{ starsSuffix }} Documentation