Skip to content
Beta — Truss is in public beta. Documentation is actively updated but may not reflect the latest changes. Report issues on GitHub.

REST API

The Truss API runs on port 8787. There are two API layers:

  • Client API (/v1/*) — for your applications, requires API keys
  • Dashboard API (/api/*) — for the Truss dashboard, uses session cookies

All client API endpoints require an API key via the apikey header.

Terminal window
# All /v1/* requests need an API key
curl http://localhost:8787/v1/db/users \
-H "apikey: truss_pk_your_key"

Two key types: anon (prefix truss_pk_) respects RLS, service_role (prefix truss_sk_) bypasses RLS. See API Keys.

POST /v1/sql — Execute arbitrary SQL (service_role only)

{
"sql": "SELECT * FROM users WHERE active = $1",
"params": [true],
"row_limit": 10000,
"timeout": 15000
}

timeout is in milliseconds (default 15000, max 30000). row_limit defaults to 10000 (max 50000) and is only applied when the query has no explicit LIMIT.

Response:

{
"rows": [...],
"rowCount": 42,
"columns": [{"name": "id", "dataTypeID": 23, "typeName": "int4"}],
"command": "SELECT"
}

POST /v1/sql/transaction — Execute multiple statements in a transaction (service_role only)

{
"statements": [
{"sql": "INSERT INTO orders (total) VALUES ($1)", "params": [99.99]},
{"sql": "UPDATE inventory SET count = count - 1 WHERE id = $1", "params": [5]}
]
}

Max 20 statements. Rolls back on any failure.

MethodEndpointDescriptionKey type
GET/v1/db/:tableSelect rowsanon or service_role
POST/v1/db/:tableInsert row(s)anon or service_role
PATCH/v1/db/:tableUpdate rows (filter required)anon or service_role
DELETE/v1/db/:tableDelete rows (filter required)anon or service_role
POST/v1/db/rpc/:functionCall a Postgres functionanon or service_role
ParamExampleDescription
selectselect=id,name,emailColumns to return
orderorder=created_at.descSort order
limitlimit=50Max rows (default 1000, max 10000)
offsetoffset=100Skip rows
Filterstatus=eq.activeWhere clause (see filter operators)

eq, neq, gt, gte, lt, lte, like, ilike, is, in

Examples: ?age=gt.18, ?name=ilike.*john*, ?id=in.(1,2,3), ?deleted=is.null

All management endpoints require a service_role key, with two exceptions: GET /v1/gateway/health and GET /v1/oauth2/discovery only need a valid API key (any anon or service_role key works).

MethodEndpointDescription
GET/v1/statusComprehensive platform overview
GET/v1/modulesEnabled modules
GET/v1/metricsAPI consumption metrics
GET/v1/audit-logsAudit log entries
MethodEndpointDescription
GET/v1/projectsList all projects
GET/v1/projects/:idFull project detail with keys, tables, storage
PATCH/v1/projects/:idUpdate project (name, status)
MethodEndpointDescription
GET/v1/database/schemaFull schema introspection
GET/v1/database/tables/:schema/:tableTable detail (columns, PKs, FKs, indexes, triggers, RLS)
GET/v1/branchesList database branches
GET/v1/backupsList backups
MethodEndpointDescription
GET/v1/keysList all keys
POST/v1/keysCreate a key
DELETE/v1/keys/:idRevoke a key
POST/v1/keys/:id/rotateRotate a key
MethodEndpointDescription
GET/v1/auth/identitiesList identities
GET/v1/auth/identities/:idIdentity detail
MethodEndpointDescription
GET/v1/storage/bucketsList buckets with object counts
MethodEndpointDescription
GET/v1/webhooksList webhooks with delivery stats
GET/v1/webhooks/:idWebhook detail with recent logs
MethodEndpointDescription
GET/v1/realtimeRealtime engine status + subscriptions
MethodEndpointDescription
GET/v1/oauth2/clientsList OAuth2 clients
POST/v1/oauth2/clientsCreate OAuth2 client
DELETE/v1/oauth2/clients/:idDelete OAuth2 client
GET/v1/oauth2/discoveryOIDC discovery document
MethodEndpointDescription
GET/v1/gateway/healthGateway health check
GET/v1/gateway/rulesList access rules

All errors return a consistent JSON structure:

{
"error": "Human-readable error message",
"code": "POSTGRES_ERROR_CODE",
"detail": "Additional detail from Postgres",
"hint": "Suggested fix"
}

Rate limiting is opt-in per API key. In the open-source core there is no default limit — keys are unlimited unless you set a per-key rate_limit (requests/minute). Every response still carries the limit headers; when a key is unlimited they report -1:

X-RateLimit-Limit: -1
X-RateLimit-Remaining: -1

When a per-key limit is configured, the headers show the limit and the remaining count in the current 60-second window, and the API returns 429 Too Many Requests once the limit is exceeded.