Databases
Manage tables and rows, import data, and run SQL queries via the API.
Endpoints for databases under /api/v1/databases.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/databases | List tables |
| POST | /api/v1/databases | Create a table |
| PATCH | /api/v1/databases/{tableId} | Update a table |
| GET | /api/v1/databases/{tableId}/rows | List rows |
| POST | /api/v1/databases/{tableId}/rows | Insert rows |
| PATCH | /api/v1/databases/{tableId}/rows | Update rows |
| DELETE | /api/v1/databases/{tableId}/rows | Delete rows |
| GET | /api/v1/databases/{tableId}/export | Export a table |
| POST | /api/v1/databases/import | Import data (CSV) |
| POST | /api/v1/databases/query | Run a SQL query |
Tables and rows
GET /api/v1/databases returns { databases[], tables[] } for the workspace.
POST /api/v1/databases creates a database (when only databaseName is given) or a table:
| Field | Type | Notes |
|---|---|---|
databaseName | string | Target database (required) |
tableName | string | If present, creates a table in that database |
columns | array | Column definitions; type ∈ text | number | status | date | json |
rows | array | Optional initial rows; scalar columns keep their documented scalar values, while a json column accepts any JSON value, including arrays, objects, booleans, and null |
GET /api/v1/databases/{tableId}/rows supports limit and offset and returns
{ table, rows[], pagination: { limit, offset, returned, total } }. POST inserts one row
({ values }), PATCH updates by { rowIndex, values }, and DELETE removes by { rowIndex }.
PATCH /api/v1/databases/{tableId} trashes a table ({ trashed }) or adds a column
({ column, defaultValue }).
Each row's values object must name only declared columns. Scalar columns accept strings or finite
numbers; values supplied as JavaScript numbers (not strings) must be finite. A partial PATCH updates
only the supplied keys and leaves every other cell untouched, including cells stored as absent or JSON
null. Structured values are valid only in columns declared as json. Invalid table creation, inserts,
or updates return 400 (BAD_REQUEST in tRPC); they are never surfaced as an internal-server error.
JSON exports preserve the original structure, while CSV exports serialize each JSON cell as compact JSON
text.
Import CSV
POST /api/v1/databases/import is multipart/form-data only:
| Field | Notes |
|---|---|
file | Required, .csv / CSV mime; max 5 MB (413), non-CSV → 415 |
databaseId / databaseName | Target database |
tableName | Defaults to a cleaned-up filename |
hasHeader | true/1/yes, default true |
delimiter | Optional delimiter override (auto-detected otherwise) |
columns | JSON array of { name, type } type overrides |
Returns 201 with { table, stats, rowsUrl }. Malformed CSV returns 422 { error, code }.
Run a SQL query
POST /api/v1/databases/query runs a read-only query against one database's tables:
{ "databaseId": "db_...", "sql": "SELECT * FROM \"orders\" WHERE total > 100 LIMIT 100" }
Both fields are required. Queries are SELECT-only and run in a sandbox over the database's
tables (never against Postgres). Success returns { columns, rows, truncated, durationMs }. A
missing database returns 404; a slow query returns 408 { error, code, availableTables }; other
SQL errors return 400. See Databases & SQL for the constraints.
Export
GET /api/v1/databases/{tableId}/export?format=csv|json (default json) returns the table as a
downloadable file with a Content-Disposition: attachment header.
