Conventions
Base URL
Section titled “Base URL”https://sql.vreelo.xyzHTTPS only. There is no HTTP endpoint; port 80 exists to redirect and to answer certificate challenges.
Requests
Section titled “Requests”Every endpoint that takes a body takes JSON, and requires the header:
content-type: application/jsonAnything else is a 415. Every endpoint except /health requires
Authorization: Bearer ….
Responses
Section titled “Responses”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.
Headers
Section titled “Headers”| 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.
Endpoints
Section titled “Endpoints”| 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.
Versioning
Section titled “Versioning”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.
Limits at a glance
Section titled “Limits at a glance”| 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.