Connecting from code
Connect to a Resta database with its URL and a database token, using the official @tursodatabase/serverless client or any HTTP client. Resta speaks Turso’s “SQL over HTTP” protocol, version 3, so code written for Turso’s serverless driver works by changing the URL and token.
JavaScript and TypeScript
@tursodatabase/serverless 1.4.1 is tested against Resta: queries, streaming results, interactive and atomic transactions, batches, errors and read-only tokens.
npm install @tursodatabase/serverless
import { connect } from '@tursodatabase/serverless';
const db = connect({
url: 'https://db.example.com/db/user-42-9cbfaa9b',
authToken: process.env.RESTA_DB_TOKEN,
});
// Statements
await db.exec('CREATE TABLE IF NOT EXISTS todos (id INTEGER PRIMARY KEY, title TEXT, done INTEGER DEFAULT 0)');
const { lastInsertRowid } = await db.run('INSERT INTO todos (title) VALUES (?)', 'write docs');
const open = await db.all('SELECT * FROM todos WHERE done = 0');
// Named parameters
await db.run('UPDATE todos SET done = 1 WHERE id = :id', { id: lastInsertRowid });
// Interactive transaction: rolled back if the function throws
await db.transactionAsync(async (tx) => {
await tx.run('INSERT INTO todos (title) VALUES (?)', 'a');
await tx.run('INSERT INTO todos (title) VALUES (?)', 'b');
})();
// Atomic batch in one request: all statements or none
await db.batch(
[
{ sql: 'INSERT INTO todos (title) VALUES (?)', args: ['c'] },
'DELETE FROM todos WHERE done = 1',
],
'immediate',
);
// Stream a large result row by row
for await (const row of (await db.prepare('SELECT * FROM todos')).iterate()) {
console.log(row.title);
}
Plain HTTP
Any language can send the protocol directly. One request, one statement:
curl https://db.example.com/db/user-42-9cbfaa9b/v3/pipeline \
-H "Authorization: Bearer $RESTA_DB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"requests": [
{"type": "execute", "stmt": {"sql": "SELECT * FROM todos WHERE id = ?", "args": [{"type": "integer", "value": "1"}]}},
{"type": "close"}
]}'
Values are tagged: {"type": "integer", "value": "1"} (integers as strings), {"type": "float", "value": 1.5}, {"type": "text", "value": "hi"}, {"type": "blob", "base64": "..."}, {"type": "null"}.
| Endpoint | Use |
|---|---|
POST /db/{id}/v3/pipeline | Run requests in order on a stream. |
POST /db/{id}/v3/cursor | Run a batch and stream rows back, one JSON object per line. |
POST /db/{id}/v2/pipeline | Older clients. |
Each response includes rows_read, rows_written and query_duration_ms per statement. SQL errors come back inside a 200 response with a code such as SQLITE_CONSTRAINT; HTTP errors (401, 404, 503) mean the request itself failed.
Transactions over HTTP
Send BEGIN in one request. The response has a baton; send it with the next request to continue the same transaction, and finish with COMMIT or ROLLBACK. A baton is single-use and expires after 30 seconds idle, which rolls the transaction back.
Other languages
Clients for Turso’s protocol in other languages should work, but only the JavaScript client is tested against Resta so far.
Choosing tokens
- Read-only (
"access": "ro") wherever writes are not needed. - One database per token, from
POST /v1/databases/{name}/tokens, not the server-wide token. - Short lifetimes, minted by your backend when needed. Tokens cannot be revoked individually.