Rows
Read and write rows on a table surface. Single-row CRUD, atomic bulk ops up to 500 changes per call, cross-surface moves, and per-cell change history.
Generated from src/lib/api-paths/rows.ts. The body schemas come straight from CreateRowSchema, UpdateRowSchema, and MoveRowsSchema in the runtime, so what's documented here is what's enforced.
get/api/workspaces/{slug}/rows
List rows in a workspace
Returns rows from the workspace's primary table surface unless `?surface=<slug>` is passed. Newest-first by default.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
surface | string | no | Surface slug to scope to. Omit for the primary table surface. |
limit | string | no | Page size. Default 50, max 500. |
offset | string | no | Offset-based pagination cursor. |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Row list with total count. |
403 | Error | Forbidden. |
post/api/workspaces/{slug}/rows
Create a row
Add a new row to a table surface. `data` keys must match column ids on the surface; values are coerced to the column type. Multi-surface workspaces accept `surface` (slug) or `surfaceId` to pick which sheet the row lands on; omit both to fall through to the workspace's primary table surface.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
data | object | yes | |
position | integer | no | |
auto_create_columns | boolean | no | |
surfaceId | string | no | |
surface | string | no | |
surface_slug | string | no |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Created. |
400 | Error | Invalid body. |
402 | Error | Row cap reached for the current plan. |
403 | Error | Forbidden. |
get/api/workspaces/{slug}/rows/{id}
Get a single row
Fetch one row by id, including its current cell values.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes | |
id | string | yes |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Row detail. |
404 | Error | Row not found. |
patch/api/workspaces/{slug}/rows/{id}
Update a row
Patch the `data` field on an existing row. Only the column keys you include get updated; other cells are left alone. Setting `surface` (slug) or `surfaceId` to a different sheet MOVES the row there: position recomputes to the destination's tail (override with `position`) and a `row.moved_surface` event fires. Same-surface is a no-op move.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes | |
id | string | yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
data | object | no | |
position | number | no | |
auto_create_columns | boolean | no | |
surfaceId | string | no | |
surface | string | no | |
surface_slug | string | no |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Updated. |
delete/api/workspaces/{slug}/rows/{id}
Delete a row
Permanent. No soft-delete on individual rows.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes | |
id | string | yes |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Deleted. |
post/api/workspaces/{slug}/rows/bulk
Bulk row operations
Atomic create + update + delete in a single request. Up to 500 ops per call. All ops apply in one Prisma transaction so partial-success scenarios don't happen.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
create | object[] | no | |
patch | object[] | no | |
delete | string[] | no |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Bulk applied. |
post/api/workspaces/{slug}/rows/move
Move rows to a different surface
Atomic batch move. All rows move to the target surface (specified by `surfaceId` or `surface` slug). Positions are recomputed at the destination tail.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
rowIds | string[] | yes | |
surfaceId | string | no | |
surface | string | no | |
surface_slug | string | no |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | Moved. |
get/api/workspaces/{slug}/rows/{id}/history
Row change history
Per-cell change history for one row. Returns chronological diffs with author + timestamp.
Auth: Bearer token (API key or OAuth access token).
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
slug | string | yes | |
id | string | yes |
Responses
| Status | Body | Description |
|---|---|---|
200 | object | History entries. |
Frequently asked questions
- How do I append a row to a Dock table via the REST API?
- POST `/api/workspaces/:slug/rows` with `{ data: { col1: val1, ... } }`. For multi-surface workspaces, pass `surface` (slug) or `surfaceId` to pick which sheet; omit to fall through to the workspace's primary table surface.
- What happens if my row data has keys that don't match any column?
- The keys are stored on the row's `data` JSON (nothing is dropped), but they won't render in the table UI until the column exists. The response surfaces them as `unmapped_fields: [...]` plus a human-readable `warning` so you can decide whether to call `add_column` or retry with `auto_create_columns: true`. Older clients see the same warning embedded in the row response.
- Can the Dock rows API auto-create columns for unknown keys?
- Yes, with explicit opt-in. POST/PATCH `/rows` with `{ data, auto_create_columns: true }`. When set, the server appends a `text` column (key + humanised label) for every key in `data` not already on the surface, then applies the row write atomically. Response payload then includes `created_columns: ColumnDef[]`. Off by default to keep typo pollution out of the schema (a stray `compamy` payload key shouldn't become a permanent column unless you ask). MCP `create_row` / `update_row` accept the same arg.
- How do I list rows in a Dock workspace?
- GET `/api/workspaces/:slug/rows`. Query params: `?limit=100&after=<cursor>&sort=title&surface=<slug>`. Default returns rows from every surface (back-compat); pass `surface` to scope.
- How do I update a row in a Dock workspace?
- PATCH `/api/workspaces/:slug/rows/:id` with `{ data: { col: newVal } }`. Partial-merge: only the keys you include are updated. Setting `surface` or `surfaceId` to a different sheet MOVES the row. Pass `auto_create_columns: true` to have the server promote any unknown keys to fresh text columns in the same call (default off).
- How do I delete a row in a Dock workspace?
- DELETE `/api/workspaces/:slug/rows/:id`. Hard-delete; not recoverable. Editor role required. Emits `row.deleted` event with full attribution.
- How do I move many Dock rows to a different sheet at once?
- POST `/api/workspaces/:slug/rows/move` (or MCP `move_rows`) with `{ rowIds, target_surface_slug }`. Atomic; all-or-nothing if any rowId doesn't belong to the workspace. Up to 500 rows per call. Idempotent on rows already on the target.
- Does the Dock rows API return who created each row?
- Yes. Every row response includes `createdBy: { principalType, id, name }` and `updatedBy` after edits. Pre-attribution rows show `null`. Use `principal.type === 'agent'` to filter agent-only writes.
- How do I read rows from a specific surface in a multi-surface Dock workspace?
- GET `/api/workspaces/:slug/rows?surface=<slug>` (or `?surfaceId=<id>`). Without the param, returns rows from every surface in the workspace (back-compat for single-sheet clients).
- Does the Dock rows API support real-time updates?
- Yes, via SSE on `GET /api/workspaces/:slug/stream` (subscribe to `row.created` / `row.updated` / `row.deleted` / `row.moved_surface` events). Or via webhooks for serverless / cron agents. Learn more →
- What's the rate limit on Dock row writes?
- Plan-tier-scoped against the org's monthly API call cap (Free 10K, Pro 100K, Scale 1M). Per-principal burst limits prevent monopolization. Hitting the cap returns 402 with actionable next-step recommendations. Learn more →
- Can my Dock agent get notified when a row changes?
- Yes. Register a webhook on `row.updated` (or `row.created` / `row.deleted` / `row.moved_surface`). The payload includes the changed row + `principal` block so the agent can route per-principal (e.g., react only to human edits).
Related
- Web → Table mode: UI for the same cells (find/replace, drag-fill, CSV export, keyboard nav).
- Surfaces API: manage the table tabs that hold rows.
- Comments API: anchor a comment to a row or cell.
- Error codes: including the 402 row-cap error per plan.