Data API
Tested with: Databasezy API v1 · PostgreSQL 17 · supabase-js 2 · zb CLI 0.1
The Data API turns the tables of your project’s primary Postgres (or TimescaleDB) database into a REST and a GraphQL API, and answers SQL over HTTPS for every instance in the project. Each request runs as the caller’s role, so row-level security decides what it sees.
Quickstart
Section titled “Quickstart”-
Choose the project’s primary database under Project settings.
-
Open Platform → Data API, turn it on, pick the schemas to expose and a maximum number of rows per request. Or with the API:
shell zb api PUT /v1/orgs/{org}/projects/<project-id>/data-api -d '{"enabled": true, "schemas": ["public"], "max_rows": 1000, "graphql_enabled": true}'System and platform schemas (
auth,storage,pg_*) are never exposed. -
Create a table with a policy, then read it with a publishable key:
SQL create table todos (id bigint generated always as identity primary key, title text, done boolean default false,is_public boolean default false);alter table todos enable row level security;create policy "public todos" on todos for select to anon using (is_public);Terminal window curl "https://<ref>.us-east.databasezy.com:8443/rest/v1/todos?select=*" \-H "apikey: <publishable-key>" \-H "Authorization: Bearer <publishable-key>"import { createClient } from "@supabase/supabase-js";const supabase = createClient("https://<ref>.us-east.databasezy.com:8443", "<publishable-key>");const { data, error } = await supabase.from("todos").select("*");from supabase import create_clientsupabase = create_client("https://<ref>.us-east.databasezy.com:8443", "<publishable-key>")rows = supabase.table("todos").select("*").execute()// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, serde_json, tokiolet key = "<publishable-key>";let res = reqwest::Client::new().get("https://<ref>.us-east.databasezy.com:8443/rest/v1/todos?select=*").header("apikey", key).bearer_auth(key).send().await?.error_for_status()?;let json: serde_json::Value = res.json().await?; -
Generate TypeScript types for supabase-js:
shell zb gen types --output src/lib/database.types.ts
PostgREST serves /rest/v1/<table> with filters (?done=eq.false), ordering, pagination (Range headers or
limit/offset), embedding of related tables (?select=*,author(name)), inserts, upserts, updates, deletes and
/rest/v1/rpc/<function>. The portal shows the generated OpenAPI description of your API.
GraphQL
Section titled “GraphQL”With graphql_enabled, /graphql/v1 answers GraphQL queries and mutations reflected from your schema by
pg_graphql, with the same roles and policies as REST. GraphQL needs the pg_graphql extension, which ships with
the extended Postgres image; the portal tells you when an instance cannot serve it.
curl -X POST "https://<ref>.us-east.databasezy.com:8443/graphql/v1" \ -H "apikey: <publishable-key>" -H "Content-Type: application/json" \ -d '{"query":"{ todosCollection(first: 5) { edges { node { id title } } } }"}'SQL over HTTPS for every engine
Section titled “SQL over HTTPS for every engine”/query/v1/<instance-id> runs a query on any instance in the project, whatever its engine, with a secret key.
Use it from servers, scripts and edge runtimes that cannot open a database connection. Publishable keys are refused.
curl -X POST "https://<ref>.us-east.databasezy.com:8443/query/v1/inst_01jb2m4n8r6xv3t8r5k6p0c2wd" \ -H "apikey: <secret-key>" -H "Authorization: Bearer <secret-key>" \ -H "Content-Type: application/json" \ -d '{"sql": "select count(*) from orders"}'| Engine family | Path after the instance | Body |
|---|---|---|
| SQL engines (Postgres, TimescaleDB, MySQL, MariaDB, ClickHouse, QuestDB, InfluxDB, DuckDB, libSQL) | /query (default) | {"sql": "..."} |
| Valkey and Redis | /command | {"command": "PING"} or {"args": ["GET", "key"]} |
| MongoDB and FerretDB | /find | the find request |
| CouchDB, Qdrant, Weaviate, TypeDB | /request | the engine’s HTTP request |
Who sees what
Section titled “Who sees what”| Caller | Role | Sees |
|---|---|---|
| Publishable key | anon | Rows your policies grant to anon |
| A user’s session token | authenticated | Rows your policies grant to that user |
| Secret key | service_role | Everything; bypasses row-level security |
Tokens are verified at the edge and again by PostgREST. A sleeping free-tier database is woken by the first request, which waits until it is ready.
Limits and billing
Section titled “Limits and billing”| Limit | Free | Solo | Team | Enterprise |
|---|---|---|---|---|
| Active API keys per project | 5 | 20 | 50 | Unlimited |
| Requests per second per key | 20 | 100 | 500 | 2,000 |
The Data API has no per-request charge; response bytes count toward your plan’s egress allowance.