API Reference
Base URL: https://data-brain-api.marlin-pohl.workers.dev
All endpoints (except admin and health) require tenant authentication via Bearer token.
Authentication
Include your API key in the Authorization header:
Authorization: Bearer sk_live_your_api_key_here
Admin endpoints use a separate admin API key.
Optional: Workspace Scoping
To scope requests to a specific workspace, include the X-Workspace-Id header alongside your API key:
Authorization: Bearer sk_live_your_api_key_here
X-Workspace-Id: ws_your_workspace_id
When this header is present, all table, row, column, and view operations are filtered to that workspace.
Error Format
All errors follow a consistent format:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description",
"details": {}
}
}Common error codes: UNAUTHORIZED, NOT_FOUND, VALIDATION_ERROR, QUOTA_EXCEEDED, CONFLICT.
Tables
List Tables
GET /api/v1/tables
Auth: Tenant API key (Bearer token)
Example Response (200):
[
{
"id": "tbl_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"workspaceId": "ws_tenant-uuid",
"name": "Contacts",
"description": null,
"icon": null,
"createdAt": "2026-02-20T10:00:00.000Z",
"updatedAt": "2026-02-20T10:00:00.000Z"
}
]Create Table
POST /api/v1/tables
Auth: Tenant API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Table name (1--255 chars) |
description | string | No | Table description (max 1000 chars) |
icon | string | No | Icon identifier (max 50 chars) |
Example Request:
{
"name": "Contacts",
"description": "Customer contact information"
}Example Response (201):
{
"id": "tbl_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"workspaceId": "ws_tenant-uuid",
"name": "Contacts",
"description": "Customer contact information",
"icon": null,
"createdAt": "2026-02-20T10:00:00.000Z",
"updatedAt": "2026-02-20T10:00:00.000Z"
}Get Table
GET /api/v1/tables/:tableId
Auth: Tenant API key (Bearer token)
Error Responses:
404-- Table not found or belongs to another tenant
Update Table
PATCH /api/v1/tables/:tableId
Auth: Tenant API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New table name |
description | string | No | New description |
icon | string | No | New icon |
Delete Table
DELETE /api/v1/tables/:tableId
Auth: Tenant API key (Bearer token)
Example Response (200):
{ "success": true }Columns
List Columns
GET /api/v1/tables/:tableId/columns
Auth: Tenant API key (Bearer token)
Example Response (200):
[
{
"id": "col_uuid",
"tableId": "tbl_uuid",
"name": "Full Name",
"type": "text",
"position": 0,
"width": 200,
"isPrimary": true,
"config": {}
}
]Create Column
POST /api/v1/tables/:tableId/columns
Auth: Tenant API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Column name (1--255 chars) |
type | string | Yes | Column type (see below) |
position | number | No | Display position |
width | number | No | Column width in pixels |
isPrimary | boolean | No | Whether this is the primary column |
config | object | No | Type-specific configuration |
Column types: text, number, date, boolean, select, multi_select, url, file, formula, relation, rollup, created_time, last_edited_time
Get Column
GET /api/v1/columns/:columnId
Update Column
PATCH /api/v1/columns/:columnId
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New column name |
width | number | No | New column width |
config | object | No | New configuration |
Delete Column
DELETE /api/v1/columns/:columnId
Reorder Columns
PUT /api/v1/tables/:tableId/columns/reorder
Request Body: Array of column UUIDs in desired order.
["col_uuid_3", "col_uuid_1", "col_uuid_2"]Rows
Query Rows
GET /api/v1/tables/:tableId/rows
Auth: Tenant API key (Bearer token)
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (1--200) |
offset | number | 0 | Number of rows to skip |
cursor | string | -- | Pagination cursor |
includeArchived | boolean | false | Include archived rows |
filters | string | -- | JSON-encoded array of filter objects |
sorts | string | -- | JSON-encoded array of sort objects |
Filter object: { "columnId": "col_1", "operator": "contains", "value": "Alice" }
Sort object: { "columnId": "col_1", "direction": "asc" }
Example Response (200):
{
"rows": [
{
"id": "row_uuid",
"tableId": "tbl_uuid",
"cells": {
"col_1": { "value": "Alice" },
"col_2": { "value": "alice@example.com" }
},
"isArchived": false,
"createdAt": "2026-02-20T10:05:00.000Z",
"updatedAt": "2026-02-20T10:05:00.000Z"
}
],
"total": 1
}Create Row
POST /api/v1/tables/:tableId/rows
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
cells | object | No | Column ID to cell value map |
parentRowId | string | No | UUID of parent row (for sub-items) |
Example Request:
{
"cells": {
"col_1": { "value": "Alice" },
"col_2": { "value": "alice@example.com" }
}
}Get Row
GET /api/v1/rows/:rowId
Update Row
PATCH /api/v1/rows/:rowId
Request Body: Object mapping column IDs to cell values.
{
"col_1": { "value": "Alice Johnson" }
}Delete Row
DELETE /api/v1/rows/:rowId
Archive Row
POST /api/v1/rows/:rowId/archive
Unarchive Row
POST /api/v1/rows/:rowId/unarchive
Bulk Create Rows
POST /api/v1/tables/:tableId/rows/bulk
Request Body: Array of row objects (1--1,000).
[
{ "cells": { "col_1": { "value": "Alice" } } },
{ "cells": { "col_1": { "value": "Bob" } } }
]Example Response (201): Array of created Row objects.
Bulk Delete Rows
DELETE /api/v1/rows/bulk
Request Body: Array of row UUIDs (1--1,000).
["row_uuid_1", "row_uuid_2", "row_uuid_3"]Bulk Archive Rows
POST /api/v1/rows/bulk/archive
Request Body: Array of row UUIDs (1--1,000).
Views
List Views
GET /api/v1/tables/:tableId/views
Create View
POST /api/v1/tables/:tableId/views
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | View name (1--255 chars) |
type | string | Yes | View type: table, board, calendar, gallery, timeline, list |
isDefault | boolean | No | Whether this is the default view |
position | number | No | Display position |
config | object | No | View configuration (filters, sorts, column visibility) |
Example Request:
{
"name": "Active Contacts",
"type": "table",
"config": {
"filters": [{ "columnId": "col_3", "operator": "equals", "value": true }]
}
}Get View
GET /api/v1/views/:viewId
Update View
PATCH /api/v1/views/:viewId
Delete View
DELETE /api/v1/views/:viewId
Reorder Views
PUT /api/v1/tables/:tableId/views/reorder
Request Body: Array of view UUIDs in desired order.
Select Options
List Options
GET /api/v1/columns/:columnId/options
Create Option
POST /api/v1/columns/:columnId/options
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Option name (1--255 chars) |
color | string | No | Color identifier (max 50 chars) |
position | number | No | Display position |
Example Request:
{
"name": "High Priority",
"color": "red"
}Update Option
PATCH /api/v1/options/:optionId
Delete Option
DELETE /api/v1/options/:optionId
Reorder Options
PUT /api/v1/columns/:columnId/options/reorder
Request Body: Array of option UUIDs in desired order.
Relations
Create Relation
POST /api/v1/relations
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
sourceRowId | string | Yes | UUID of the source row |
sourceColumnId | string | Yes | UUID of the relation column |
targetRowId | string | Yes | UUID of the target row |
Example Request:
{
"sourceRowId": "row_uuid_1",
"sourceColumnId": "col_relation",
"targetRowId": "row_uuid_2"
}Delete Relation
DELETE /api/v1/relations
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
sourceRowId | string | Yes | UUID of the source row |
columnId | string | Yes | UUID of the relation column |
targetRowId | string | Yes | UUID of the target row |
Get Related Rows
GET /api/v1/rows/:rowId/relations/:columnId
Example Response (200): Array of Row objects.
Get All Relations for Row
GET /api/v1/rows/:rowId/relations
Example Response (200):
[
{ "columnId": "col_relation_1", "targetRowId": "row_uuid_2" },
{ "columnId": "col_relation_1", "targetRowId": "row_uuid_3" }
]File References
Add File Reference
POST /api/v1/file-refs
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
rowId | string | Yes | UUID of the row |
columnId | string | Yes | UUID of the file column |
fileId | string | Yes | External file identifier |
fileUrl | string | Yes | URL to the file |
originalName | string | Yes | Original filename (1--255 chars) |
mimeType | string | Yes | MIME type (1--100 chars) |
sizeBytes | number | No | File size in bytes |
position | number | No | Display position |
metadata | object | No | Additional metadata |
Example Request:
{
"rowId": "row_uuid",
"columnId": "col_file",
"fileId": "sb_file_id",
"fileUrl": "https://storage.example.com/files/receipt.pdf",
"originalName": "receipt.pdf",
"mimeType": "application/pdf",
"sizeBytes": 245000
}Remove File Reference
DELETE /api/v1/file-refs/:fileRefId
Get File References
GET /api/v1/rows/:rowId/files/:columnId
Example Response (200): Array of FileReference objects.
Reorder File References
PUT /api/v1/rows/:rowId/files/:columnId/reorder
Request Body: Array of file reference UUIDs in desired order.
Workspaces
Workspaces partition data within a tenant. All workspace endpoints require a tenant API key.
List Workspaces
GET /api/v1/workspaces
Auth: Tenant API key (Bearer token)
Example Response (200):
[
{
"id": "ws_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenantId": "tenant-uuid",
"name": "Production",
"slug": "production",
"quotaRows": null,
"usedRows": 0,
"metadata": null,
"createdAt": "2026-02-20T10:00:00.000Z",
"updatedAt": "2026-02-20T10:00:00.000Z"
}
]Create Workspace
POST /api/v1/workspaces
Auth: Tenant API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workspace name (1--255 chars) |
slug | string | Yes | URL-safe unique identifier (must be unique within tenant) |
quotaRows | number | No | Row limit override (null = inherits tenant default) |
metadata | object | No | Arbitrary JSON metadata |
Example Request:
{
"name": "Production",
"slug": "production"
}Example Response (201):
{
"id": "ws_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenantId": "tenant-uuid",
"name": "Production",
"slug": "production",
"quotaRows": null,
"usedRows": 0,
"metadata": null,
"createdAt": "2026-02-20T10:00:00.000Z",
"updatedAt": "2026-02-20T10:00:00.000Z"
}Error Responses:
409-- A workspace with the given slug already exists for this tenant
Get Workspace
GET /api/v1/workspaces/:id
Auth: Tenant API key (Bearer token)
Error Responses:
404-- Workspace not found or belongs to another tenant
Update Workspace
PATCH /api/v1/workspaces/:id
Auth: Tenant API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New workspace name |
quotaRows | number | No | New row limit |
metadata | object | No | New metadata (replaces existing) |
Error Responses:
404-- Workspace not found or belongs to another tenant
Delete Workspace
DELETE /api/v1/workspaces/:id
Auth: Tenant API key (Bearer token)
Deletes the workspace and all tables, rows, columns, and views within it. This action is irreversible.
Example Response (200):
{ "success": true }Error Responses:
404-- Workspace not found or belongs to another tenant
Tenant
Get Tenant Info
GET /api/v1/tenant/info
Auth: Tenant API key (Bearer token)
Example Response (200):
{
"id": "tenant-uuid",
"name": "My App",
"quotaRows": 100000,
"usedRows": 1234,
"maxTables": 100,
"createdAt": "2026-02-15T08:00:00.000Z"
}Admin
Admin endpoints require the ADMIN_API_KEY environment variable to be configured. They use a separate API key from tenant keys.
Create Tenant
POST /api/v1/admin/tenants
Auth: Admin API key (Bearer token)
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Tenant name (1--100 chars) |
quotaRows | number | No | Max rows (default: 100,000) |
maxTables | number | No | Max tables (default: 100) |
Example Request:
{
"name": "My Application",
"quotaRows": 500000,
"maxTables": 200
}Example Response (201):
{
"tenant": {
"id": "new-tenant-uuid",
"name": "My Application",
"quotaRows": 500000,
"usedRows": 0,
"maxTables": 200,
"createdAt": "2026-02-20T10:00:00.000Z"
},
"apiKey": "sk_live_abc123def456..."
}Important: The
apiKeyfield is only returned once at creation. Store it securely.
Health
Health Check
GET /health
Auth: None
Example Response (200):
{
"status": "ok",
"timestamp": "2026-02-20T10:00:00.000Z",
"environment": "production"
}