Skip to main content
The /api/database/* endpoints are a thin auth-required proxy over PostgREST, scoped to your project’s public schema. They use the same operators and conventions as PostgREST under the hood, but every call requires a valid Powabase auth token (no anon-key access). System schemas (ai, auth, storage, pg_catalog, information_schema, etc.) are blocked at this layer — those are managed via dedicated routes (/api/agents, /api/knowledge-bases, …). When you need the full PostgREST query language (filter operators, embedded relations, ordering, RPC calls), use the PostgREST endpoints instead. Use this proxy when you want one auth model across all platform calls and don’t need the full PostgREST surface.

Common Patterns

Discover tables with GET /tables, then read or mutate rows by primary key. The /openapi endpoint returns the project’s full PostgREST OpenAPI spec — useful for UIs that render an API reference for user-defined tables.

GET /api/database/tables

List tables in the schema (only public is currently allowed). Returns { "tables": ["users", "orders", ...] }.
schema
string
Defaults to public. Any other value returns 400.
requests.get(f"{BASE_URL}/api/database/tables", headers=headers)
await fetch(`${BASE_URL}/api/database/tables`, { headers });
curl '{BASE_URL}/api/database/tables' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"

GET /api/database/tables/

List rows from a table via PostgREST. Supports limit (default 50) and offset query parameters.
table
string
required
Table name in the public schema. Must match ^[A-Za-z_][A-Za-z0-9_]*$.
limit
integer
Defaults to 50.
offset
integer
Defaults to 0.
schema
string
Defaults to public.
requests.get(f"{BASE_URL}/api/database/tables/users?limit=20", headers=headers)
await fetch(`${BASE_URL}/api/database/tables/users?limit=20`, { headers });
curl '{BASE_URL}/api/database/tables/users?limit=20' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"

GET /api/database/tables//

Fetch a single row by id. Returns the row as a JSON object (uses PostgREST’s Accept: application/vnd.pgrst.object+json).
table
string
required
Table name
row_id
string
required
Row primary key
schema
string
Defaults to public.
requests.get(f"{BASE_URL}/api/database/tables/users/{user_id}", headers=headers)
await fetch(`${BASE_URL}/api/database/tables/users/${userId}`, { headers });
curl '{BASE_URL}/api/database/tables/users/{user_id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"

POST /api/database/tables/

Insert a row. The body is forwarded to PostgREST with Prefer: return=representation, so the response contains the inserted row.
table
string
required
Table name
{ "email": "ana@acme.io", "role": "admin" }
requests.post(f"{BASE_URL}/api/database/tables/users", headers=headers, json={"email": "ana@acme.io"})
await fetch(`${BASE_URL}/api/database/tables/users`, { method: "POST", headers, body: JSON.stringify({ email: "ana@acme.io" }) });
curl -X POST '{BASE_URL}/api/database/tables/users' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"email": "ana@acme.io"}'

PATCH /api/database/tables//

Update a row by id. Returns the updated row.
table
string
required
Table name
row_id
string
required
Row primary key
{ "role": "viewer" }
requests.patch(f"{BASE_URL}/api/database/tables/users/{user_id}", headers=headers, json={"role": "viewer"})
await fetch(`${BASE_URL}/api/database/tables/users/${userId}`, { method: "PATCH", headers, body: JSON.stringify({ role: "viewer" }) });
curl -X PATCH '{BASE_URL}/api/database/tables/users/{user_id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"role": "viewer"}'

DELETE /api/database/tables//

Delete a row by id.
table
string
required
Table name
row_id
string
required
Row primary key
requests.delete(f"{BASE_URL}/api/database/tables/users/{user_id}", headers=headers)
await fetch(`${BASE_URL}/api/database/tables/users/${userId}`, { method: "DELETE", headers });
curl -X DELETE '{BASE_URL}/api/database/tables/users/{user_id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"

GET /api/database/openapi

Return the project’s full PostgREST OpenAPI/Swagger spec. The frontend uses this to render an API reference for user-defined tables; you can use it to drive a settings UI or to introspect the schema programmatically.
spec = requests.get(f"{BASE_URL}/api/database/openapi", headers=headers).json()
const spec = await fetch(`${BASE_URL}/api/database/openapi`, { headers }).then(r => r.json());
curl '{BASE_URL}/api/database/openapi' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"

Error Responses

Errors from this proxy return {"error": "<message>"}. Errors from the upstream PostgREST/Postgres are forwarded verbatim with their original status code.
StatusDescription
400Table name failed validation (must match ^[A-Za-z_][A-Za-z0-9_]*$)
400Schema is not public (only public is exposed via this proxy)
401Missing or invalid auth headers
500GET /tables failed against information_schema
502PostgREST connection failed (network error, gateway unreachable)
4xx/5xxForwarded from PostgREST (e.g. constraint violation, RLS denial)