Quickstart
Everything below is curl against the live API. If you do not have a token yet, see
Authentication — an operator issues you one.
export SQLITED_TOKEN='dbk_live_key_…'export SQLITED_BASE='https://sql.vreelo.xyz'1. Create a database
Section titled “1. Create a database”curl -sS "$SQLITED_BASE/v1/databases" \ -H "Authorization: Bearer $SQLITED_TOKEN" \ -H 'content-type: application/json' \ -d '{"name":"production"}'{ "database": { "id": "db_01a00b50-f7d7-74e8-be44-877297734dec", "name": "production", "status": "active", "createdAt": "2026-08-16T09:14:02.118Z", "deletedAt": null }}The id is what every other request needs. Note the envelope — the record is under database, not
at the top level:
export DB=db_01a00b50-f7d7-74e8-be44-877297734decThis request needs the org:admin scope. If you were handed a narrower data-plane key, it will answer
403 here and that is correct; creating databases and querying them are different powers.
2. Create a table
Section titled “2. Create a table”curl -sS "$SQLITED_BASE/v1/databases/$DB/query" \ -H "Authorization: Bearer $SQLITED_TOKEN" \ -H 'content-type: application/json' \ -d '{"sql":"CREATE TABLE events (id INTEGER PRIMARY KEY, kind TEXT NOT NULL, at TEXT NOT NULL)"}'{ "columns": [], "rows": [], "rowsAffected": 0, "lastInsertRowid": 0, "epoch": 1, "txid": 1, "durability": "durable", "waitedMs": 121}"durability": "durable" means the schema change is in object storage. There is no separate migration
step or commit — DDL is a write like any other, and it is durable by the time you read this.
3. Write a row
Section titled “3. Write a row”Always bind values rather than interpolating them into the SQL. ? is positional:
curl -sS "$SQLITED_BASE/v1/databases/$DB/query" \ -H "Authorization: Bearer $SQLITED_TOKEN" \ -H 'content-type: application/json' \ -d '{ "sql": "INSERT INTO events (kind, at) VALUES (?, ?)", "params": ["signup", "2026-08-16T09:15:00Z"] }'{ "columns": [], "rows": [], "rowsAffected": 1, "lastInsertRowid": 1, "epoch": 1, "txid": 2, "durability": "durable", "waitedMs": 117}Named parameters work too — pass an object and use :name in the SQL. See
Query.
4. Read it back
Section titled “4. Read it back”curl -sS "$SQLITED_BASE/v1/databases/$DB/query" \ -H "Authorization: Bearer $SQLITED_TOKEN" \ -H 'content-type: application/json' \ -d '{"sql":"SELECT id, kind, at FROM events ORDER BY id"}'{ "columns": ["id", "kind", "at"], "rows": [[1, "signup", "2026-08-16T09:15:00Z"]], "rowsAffected": 0, "lastInsertRowid": null, "epoch": 1, "txid": null, "durability": "read", "waitedMs": 0}Rows are arrays, not objects, positionally matching columns. That is not laziness: duplicate column
names are legal SQL — SELECT * FROM a JOIN b where both tables have an id — and an object would
silently lose one of them. Zip them yourself if you want names, and see
Client examples for a three-line helper.
"durability": "read" and "txid": null are what a read looks like. Nothing needed to become durable,
so nothing waited.
5. Do several things atomically
Section titled “5. Do several things atomically”A batch is one transaction. Either all of it is in one durable segment, or none of it committed:
curl -sS "$SQLITED_BASE/v1/databases/$DB/batch" \ -H "Authorization: Bearer $SQLITED_TOKEN" \ -H 'content-type: application/json' \ -d '{ "statements": [ {"sql": "INSERT INTO events (kind, at) VALUES (?, ?)", "params": ["login", "2026-08-16T09:16:00Z"]}, {"sql": "INSERT INTO events (kind, at) VALUES (?, ?)", "params": ["view", "2026-08-16T09:16:01Z"]}, {"sql": "SELECT count(*) AS n FROM events"} ] }'{ "results": [ { "columns": [], "rows": [], "rowsAffected": 1, "lastInsertRowid": 2 }, { "columns": [], "rows": [], "rowsAffected": 1, "lastInsertRowid": 3 }, { "columns": ["n"], "rows": [[3]], "rowsAffected": 0, "lastInsertRowid": null } ], "epoch": 1, "txid": 3, "durability": "durable", "waitedMs": 119}Note that three statements cost the same ~120 ms as one. This is the single most useful performance fact in these docs: the latency is one round trip to object storage per batch, not per statement. Ten inserts in a batch cost 120 ms; ten inserts in ten requests cost 1.2 seconds.
Where to go next
Section titled “Where to go next”- Durability — what
durablepromises, and the one case where the answer is “we do not know”. - Errors and retries — every error this API returns, and which ones to retry.
- SQL support — what SQLite features are available and which statements are refused.
- Client examples — TypeScript, Python, and Go, with retries wired in.