Skip to content

Conventions

https://sql.vreelo.xyz

HTTPS only. There is no HTTP endpoint; port 80 exists to redirect and to answer certificate challenges.

Every endpoint that takes a body takes JSON, and requires the header:

content-type: application/json

Anything else is a 415. Every endpoint except /health requires Authorization: Bearer ….

Successes are JSON. Failures are application/problem+json — see Errors.

Control-plane responses are enveloped, so that adding a field later is not a breaking change:

{ "database": { "id": "db_…", "name": "production", "status": "active" } }

Data-plane responses are not enveloped, because the result of a query is the whole point of the response:

{
"columns": ["n"],
"rows": [[3]],
"rowsAffected": 0,
"lastInsertRowid": null,
"epoch": 1,
"txid": null,
"durability": "read",
"waitedMs": 0
}

Unknown fields may be added to any response. Ignore the ones you do not recognize rather than validating strictly against a fixed shape.

Header On
X-Request-Id Every response A UUID we generate. Quote it when reporting a problem.
X-Durability /query, /batch durable or read.
X-Durable-TXID /query, /batch (writes) The durable high-water mark. Absent on reads.
X-Database-Epoch /query, /batch The ownership generation that served the request.

A client-supplied X-Request-Id is ignored, not echoed. An attacker-supplied id ends up in our logs, and a 10 MB one would be a cheap way to fill them. Correlate using the id we return.

Method Path Scope
GET /health none Liveness
POST /v1/databases org:admin Create a database
GET /v1/databases org:admin List databases
GET /v1/databases/{id} org:admin Get one database
DELETE /v1/databases/{id} org:admin Delete a database
POST /v1/databases/{id}/query db:read or db:write One statement
POST /v1/databases/{id}/batch db:read or db:write Several, atomically

The data-plane scope depends on the SQL, not the endpoint: db:read for a read, db:write for anything that modifies data or schema.

The path carries v1. Within v1 we will add fields and endpoints but not remove or repurpose them, and we will not change the meaning of an existing type URI. A breaking change gets a new prefix.

Limit Value
Request body 8 MiB
SQL per statement 1 MiB
Statements per /query 1
Statements per /batch 100

See Limits for what happens at each boundary.