Reference · 9 operations
Tables: rows
Last updated from API version 2026-10-06 at (live spec, refreshed hourly). openapi.json
List a table's rows: newest first, filtered, sorted or changed since a version.
/api/v1/tables/{id}/rows- Scope
- read
- Credits
- Free
- Idempotency-Key
- Not used
Cursor-paginated (meta.page); rows added while paging never cause gaps
or duplicates. meta.version is the table's version: store it and pass it
as changedSince to get only what changed since (values, deletions as
rows with deletedAt, and cell run state), with meta.schemaChanged
(refetch the table) and meta.truncated (more changed than one answer
holds, or the store cannot list deletions: refetch the visible rows).
changedSince is at least once: it
may re-send changes of the last 5 s before changedSince, so
apply rows idempotently (dedupe by row id and version).
Without changedSince: filter (the filter language, JSON), sort
(-score,name), or a saved viewId (its filter and sorts; filter and
sort override them). Size caps: limit at most 200, a page stops early
(short page with a cursor) once it holds about 3 MB, and a cell whose JSON
is over 32 KB is cut (strings) or returned as null (structured values),
with its key listed in truncatedCells. On some
workspaces a filter or sort reads at most 5,000 rows of the table
(422 LIMIT_EXCEEDED beyond: narrow the filter). A table in another workspace, or an archived
table without includeArchived=true, is 404 NOT_FOUND.
Parameters
- idpathstringrequired
The table id.
- limitqueryinteger
Page size.
default 50min 1max 200 - cursorquerystring
Opaque cursor from
meta.page.nextCursor. Reusing it with other filters is400 CURSOR_MISMATCH. - includeArchivedqueryboolean
Include archived tables.
default false - viewIdquerystring
A saved view of this table: its filter and sorts apply.
- filterquerystring
A filter tree as JSON, e.g.
{"and":[{"column":"score","op":"gte","value":10}]}. Invalid:400 INVALID_FILTER. - sortquerystring
Up to 3 column keys,
-for descending (-score,name); nulls last, then newest first. - columnsquerystring
Only these cell keys (comma-separated).
- includequerystring
cellState: add each row'scellStates(cell run state by column id). - changedSincequeryinteger
A
meta.versionfrom an earlier answer: only rows changed after it (no paging;cursor,filter,sortandviewIdare not allowed).min 0
Responses
200OK.Show schema
TableRowListResponse
- 0
- 0
Metadata of a rows answer:
pagefor a page,version(store it forchangedSince), and forchangedSinceanswersschemaChangedandtruncatedinstead ofpage.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl "https://app.owlbound.ai/api/v1/tables/$ID/rows" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06"Insert or update up to 5,000 rows (500 on some workspaces: more is 422 LIMIT_EXCEEDED).
/api/v1/tables/{id}/rows- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
Each row: cells, optionally id (update that row), dedupeKey
(update the row with that key, else insert it with the key),
linkedContactId, linkedCompanyId (must be in this workspace, else
404 NOT_FOUND on that field). onConflict (updateEmpty by default:
only empty cells are filled; overwrite; skip) applies to rows found by
id or key. Results per row: {index, id, status: inserted|updated|skipped, errors?}; a row with an invalid cell is skipped with
INVALID_CELL_VALUE and the others are written. More rows than the
limit: 422 LIMIT_EXCEEDED.
Parameters
- idpathstringrequired
The table id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255
Request body (required) · application/json
TableRowUpsertRequest
- min items 1max items 5000
- onConflictstringupdateEmptyoverwriteskipdefault "updateEmpty"
Responses
200OK.Show schema
TableRowUpsertResponse
- 0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X POST "https://app.owlbound.ai/api/v1/tables/$ID/rows" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"rows": [
{
"cells": {}
}
]
}'Set the same cells on many rows.
/api/v1/tables/{id}/rows- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
Target rows by rowIds, or by filter with confirmCount equal to the
number of matching rows (otherwise 400 VALIDATION_ERROR with
details.count). One invalid value fails the request (400 INVALID_CELL_VALUE); nothing is written.
Parameters
- idpathstringrequired
The table id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255
Request body (required) · application/json
TableRowBulkUpdateRequest
- cellsobjectrequired0
- rowIdsarray of string0
- filterany0
A filter tree (the filter language).
- confirmCountintegermin 0
Responses
200OK.Show schema
TableRowBulkUpdateResponse
- dataobjectrequired0
+ Show child fields− Hide child fields
- versionnumberrequired0
- matchedintegerrequired0
- updatedintegerrequired0
- notFoundintegerrequired0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X PATCH "https://app.owlbound.ai/api/v1/tables/$ID/rows" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"cells": {}
}'Delete many rows.
/api/v1/tables/{id}/rows/delete- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
Target rows by rowIds, or by filter with confirmCount (as for bulk update).
Parameters
- idpathstringrequired
The table id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255
Request body (required) · application/json
any
any
Responses
200OK.Show schema
TableRowBulkDeleteResponse
- dataobjectrequired0
+ Show child fields− Hide child fields
- versionnumberrequired0
- matchedintegerrequired0
- deletedintegerrequired0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X POST "https://app.owlbound.ai/api/v1/tables/$ID/rows/delete" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"rowIds": [
"<rowIds>"
],
"confirmCount": 1
}'Push rows to contacts, a sequence or a CRM.
/api/v1/tables/{id}/rows/push- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
- Rate weight
- 2 requests
target: "contacts": up to 200 rows per request, by rowIds or by filter with
confirmCount. mapping maps contact fields (email, linkedInUrl,
firstName, lastName, fullName, phone, title, company,
companyDomain, companyLinkedInUrl, headline, location,
industry, notes) to column keys; omitted, it is guessed from the
column names and must find an email or LinkedIn column.
Each row is matched to a contact by its linked contact, then its
LinkedIn profile URL, then its email (the contact import rules); a
match gets its empty fields filled (onConflict: fillEmpty, default)
or is left as is (skip); otherwise a contact is created. Rows of one
request naming the same person become one contact. The row's
linkedContactId is set. Rows without a valid email or LinkedIn URL
are skipped. dryRun: true returns the same per-row results
without writing anything. Free.
target: "sequence" (with sequenceId) and target: "crm" (with
crm: {provider: "hubspot", object: "contact" | "company", onConflict?}) push the rows' linked contacts through
actions.sequences.enroll or actions.crm.hubspot.upsert_contact /
upsert_company: ONE action whose targets are the rows (target kind
rows), with that action's approval, claims, caps, price and dry
run (dryRun: true returns its plan; planId applies it). They
need the act scope as well as write, an Idempotency-Key, and
rowIds (at most 200; no filter, mapping or onConflict).
Rows without a linked contact are skipped NO_CONTACT (push them
to contacts first). A real call answers 202 with the action,
pending_approval until a person approves it in the app.
Not available yet for some workspaces: the call answers
409 TABLE_STORE_UNSUPPORTED.
target: "column" (with columnId) runs a send column (an
action column whose operation is actions.linkedin.connect,
.dm, .inmail or actions.sequences.enroll): ONE action of that
operation over the rows, each row's input resolved from its cells
({{Column}} references) and frozen at approval; the cells show
each target's state (pending approval, approved, sent, unknown).
Same rules as a sequence push (act, Idempotency-Key, rowIds). A
row whose last run of this column is pending, running or sent is
skipped ALREADY_RUN: a row is never sent twice by its column.
Parameters
- idpathstringrequired
The table id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255
Request body (required) · application/json
TableRowPushRequest
- targetstringrequiredcontactssequencecrmcolumn
- columnIdstring0
Target column only; a send column of this table (its operation, input and identity).
- identityIdstring | null0
Target column only; the sender when the column names none (else the key's bound identity, or the session member's own).
- mappingobject0
Target contacts only.
- dryRunboolean0
- onConflictstring
Target contacts only.
fillEmptyskip - sequenceIdstring0
Target sequence only; an existing sequence of this workspace.
- crmobject0
Target crm only.
+ Show child fields− Hide child fields
- providerstringrequiredhubspot
- objectstringrequiredcontactcompany
- onConflictstring
fillEmpty(default): write only the fields the CRM has empty.overwrite: also replace CRM values that differ. Never clears a field.fillEmptyoverwrite
- requestApprovalboolean0
Targets sequence, crm and column; ask a person even when the key's approval mode would not.
- planIdstring
Targets sequence, crm and column; apply this dry run's plan.
pattern ^plan_[0-9a-f]{48}$ - rowIdsarray of string0
- filterany0
A filter tree (the filter language).
- confirmCountintegermin 0
Responses
200OK.Show schema
one of
202Target sequence, crm or column: the action was created (pending_approval until a person approves it in the app).Show schema
pending_approval until a person approves it in the app).ActionResponse
- dataobjectrequired0
+ Show child fields− Hide child fields
- 0
One action run. Read it again with
GET /api/v1/actions/{id}.
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X POST "https://app.owlbound.ai/api/v1/tables/$ID/rows/push" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"target": "contacts",
"dryRun": true
}'Get one row with its version.
/api/v1/tables/{id}/rows/{rowId}- Scope
- read
- Credits
- Free
- Idempotency-Key
- Not used
Parameters
- idpathstringrequired
The table id.
- rowIdpathstringrequired
The row id.
Responses
200OK.Show schema
TableRowResponse
- 0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl "https://app.owlbound.ai/api/v1/tables/$ID/rows/$ROW_ID" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06"Update a row's cells, optionally only if unchanged (If-Match).
/api/v1/tables/{id}/rows/{rowId}- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
replace: true clears every other cell of the row.
Parameters
- idpathstringrequired
The table id.
- rowIdpathstringrequired
The row id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255 - If-Matchheaderstring
The row's
versionas read (12,"12"orW/"12"). When it no longer matches, nothing is written and the answer is412 VERSION_CONFLICTwithdetails.currentVersion. Without it, the last write wins (row history keeps both values).
Request body (required) · application/json
TableRowUpdateRequest
- cellsobjectrequired0
- replaceboolean0
Clear every other cell of the row.
Responses
200OK.Show schema
TableRowResponse
- 0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 412 VERSION_CONFLICT: the row changed since it was read (`If-Match` no
longer matches); `details.currentVersion` is its version now.
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X PATCH "https://app.owlbound.ai/api/v1/tables/$ID/rows/$ROW_ID" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"cells": {}
}'Delete a row, optionally only if unchanged (If-Match).
/api/v1/tables/{id}/rows/{rowId}- Scope
- write
- Credits
- Free
- Idempotency-Key
- optional
Parameters
- idpathstringrequired
The table id.
- rowIdpathstringrequired
The row id.
- Idempotency-Keyheaderstring
1 to 255 printable ASCII characters, scoped to the API key (a rotated key shares its predecessor's keys) and kept 24 h. Accepted on every POST, PATCH and DELETE (ignored on GET); required from v1 keys where the operation says
x-owlbound-idempotent: required(missing:400 VALIDATION_ERROR,param: Idempotency-Key). Same key and body after completion: the stored response is replayed withIdempotent-Replayed: true. Results over 64 KB are not stored; their replay is409 IDEMPOTENCY_RESULT_UNAVAILABLEwithdetails.originalRequestId(check state with a GET). Same key while the first request runs:409 IDEMPOTENCY_IN_PROGRESSwithRetry-After. Same key, other body or operation:422 IDEMPOTENCY_KEY_REUSED. A request that ended 5xx may be retried with the same key. 4xx results are stored and replayed too: a402 INSUFFICIENT_CREDITSreplays even after a top-up, so use a new Idempotency-Key after adding credits.min length 1max length 255 - If-Matchheaderstring
The row's
versionas read (12,"12"orW/"12"). When it no longer matches, nothing is written and the answer is412 VERSION_CONFLICTwithdetails.currentVersion. Without it, the last write wins (row history keeps both values).
Responses
200OK.Show schema
TableRowDeleteResponse
- dataobjectrequired0
+ Show child fields− Hide child fields
- idstringrequired0
- deletedbooleanrequired0
- versionnumberrequired0
- 0
Metadata on every success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 409 IDEMPOTENCY_IN_PROGRESS (the first request with this key is still
running; `Retry-After` is the lease left, at most 60 s) or
IDEMPOTENCY_RESULT_UNAVAILABLE (the original result was too large to
store; `details.originalRequestId`).
· 412 VERSION_CONFLICT: the row changed since it was read (`If-Match` no
longer matches); `details.currentVersion` is its version now.
· 422 IDEMPOTENCY_KEY_REUSED (the key was used with another body or operation), or an action that cannot run · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl -X DELETE "https://app.owlbound.ai/api/v1/tables/$ID/rows/$ROW_ID" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06" \
-H "Idempotency-Key: $(uuidgen)"A row's history, newest first.
/api/v1/tables/{id}/rows/{rowId}/history- Scope
- read
- Credits
- Free
- Idempotency-Key
- Not used
Every change written through the API (on some workspaces, every change): cell values before and after, row creation and deletion, with the actor and request id.
Parameters
- idpathstringrequired
The table id.
- rowIdpathstringrequired
The row id.
- limitqueryinteger
Page size.
default 50min 1max 200 - cursorquerystring
Opaque cursor from
meta.page.nextCursor. Reusing it with other filters is400 CURSOR_MISMATCH.
Responses
200OK.Show schema
TableRowHistoryResponse
- 0
- 0
Metadata on a paginated success response.
Errors
400 The request is invalid (VALIDATION_ERROR, CURSOR_MISMATCH, UNSUPPORTED_FILTER) · 401 Missing, invalid, expired or revoked key · 403 Missing scope, suspended workspace or unavailable identity · 404 Unknown resource or route. A resource in another workspace is also 404 · 429 Rate limit reached · 500 Unexpected error · 503 The backend is unreachable; retry after `Retry-After`. Every error is {error: {type, code, message, requestId, docUrl}}; see error codes.
curl "https://app.owlbound.ai/api/v1/tables/$ID/rows/$ROW_ID/history" \
-H "Authorization: Bearer $OWLBOUND_API_KEY" \
-H "Owlbound-Version: 2026-10-06"Models on this page
Shared objects the operations above link to. Clients must ignore fields they do not know.
TableRowobject
- idstringrequired0
- tableIdstringrequired0
- cellsobjectrequired0
Typed values keyed by the table's column keys. The keys are user data, returned exactly as stored (not camelCased; e.g.
work_email); an absent key is an empty cell. A value that does not fit its column type, or is not representable in JSON, isnullhere and its text form is inlegacyCells. - legacyCellsobject | nullrequired0
{columnKey: text}for cells whose stored value is not valid for the column type (kept as text, never lost);nullwhen there are none. Kept outsidecellsso it never collides with a column key. - linkedContactIdstring | nullrequired0
- linkedCompanyIdstring | nullrequired0
- sourceRefstring | nullrequired0
The source record this row was refreshed from;
nullfor manual rows. - versionnumberrequired0
The row's version; send it as
If-Matchto update or delete only an unchanged row. - createdAtnumberrequired0
- updatedAtnumberrequired0
- deletedAtnumber0
Only in
changedSinceanswers, on rows deleted since (tombstones). - cellStatesobject0
With
include=cellStateand inchangedSinceanswers. Run state by column id. - truncatedbooleanrequired0
True when at least one value in
cellsorlegacyCellswas over the 32 KB cell cap. - truncatedCellsarray of stringrequired0
Keys in
cellscut (strings) or returned asnull(structured values) by the cell cap. - truncatedLegacyCellsarray of stringrequired0
Keys in
legacyCellscut by the cell cap.
TableCellStateobject
Run state of one computed cell.
- statusstringrequiredqueuedrunningdoneno_resulterrorstaleskipped
- lastRunIdstring | nullrequired0
- creditsChargednumberrequired0
- providerstring | nullrequired0
- errorCodestring | nullrequired0
- errorMessagestring | nullrequired0
- versionnumberrequired0
- updatedAtnumberrequired0
TableRowsMetaobject
Metadata of a rows answer: page for a page, version (store it for
changedSince), and for changedSince answers schemaChanged and
truncated instead of page.
- requestIdstringrequired0
- 0
- pagePageMeta0
Cursor pagination.
hasMoreis the only end signal; pages may be short. - versionnumberrequired0
- schemaChangedboolean0
A column or view changed since
changedSince; refetch the table. - truncatedboolean0
Not every change is in this answer; refetch the visible rows.
CreditsMetaobject
- usednumberrequired0
Credits charged by this request. Reads are free.
- balancenumber0
- estimatednumber0
Dry run only (action operations).
- availablenumber0
Dry run only (action operations).
- reservationIdstring | null0
Async operations only; the job settles this reservation.
PageMetaobject
Cursor pagination. hasMore is the only end signal; pages may be short.
- nextCursorstring | nullrequired0
- hasMorebooleanrequired0
- limitintegerrequiredmin 1max 200
TableRowInputobject
- idstring0
Update this row of the table.
- cellsobjectrequired0
- dedupeKeystring | nullmax length 500
- linkedContactIdstring | null0
- linkedCompanyIdstring | null0
TableRowUpsertResultobject
- versionnumberrequired0
- insertedintegerrequired0
- updatedintegerrequired0
- skippedintegerrequired0
- 0
TableRowWriteResultobject
- indexintegerrequired0
- idstring | nullrequired0
- statusstringrequiredinsertedupdatedskipped
- errorsarray of object0
+ Show child fields− Hide child fields
- codestringrequiredINVALID_CELL_VALUELIMIT_EXCEEDEDNOT_FOUND
- messagestringrequired0
- columnKeystring0
- expectedstring0
ResponseMetaobject
Metadata on every success response.
- requestIdstringrequired0
- 0
- pagePageMeta0
Cursor pagination.
hasMoreis the only end signal; pages may be short. - dryRunboolean0
True only on a dry-run response (action operations).
TableRowPushResponseobject
- dataobjectrequired0
+ Show child fields− Hide child fields
- targetstringrequired0
- dryRunbooleanrequired0
- mappingobjectrequired0
- versionnumber | nullrequired0
- createdintegerrequired0
- updatedintegerrequired0
- unchangedintegerrequired0
- skippedintegerrequired0
- failedintegerrequired0
- 0
- 0
Metadata on every success response.
TableRowPushResultobject
- rowIdstringrequired0
- statusstringrequiredcreatedupdatedunchangedskippedfailed
- contactIdstring | nullrequired0
- matchedBystring | nullrequiredlinklinkedinemail
- fieldsarray of string0
- errorsarray of object0
ActionRunResponseobject
{data: {action, result}} when the action ran inline, or
{data: {plan}} with meta.dryRun: true for a dry run.
- dataone ofrequired0
+ Show child fields− Hide child fields
One of
with action
- 0
One action run. Read it again with
GET /api/v1/actions/{id}. - resultanyrequired0
The target's result, or null when it was skipped or failed.
with plan
- 0
What a real call would do, from every check up to the first side effect. Nothing is reserved, sent, written or charged. The plan is stored for 15 minutes: send its
planIdwith the real call to run exactly what was reviewed (409 PLAN_STALEwith a new plan if anything bound changed or it expired).
- 0
Metadata on every success response.
Actionobject
One action run. Read it again with GET /api/v1/actions/{id}.
- idstringrequired0
- kindstringrequired0
The operation id.
- classstringrequired
Safety class: decides scope, approval, caps and enforcement.
readwritespendexternal_writesend - statusstringrequiredpending_approvalqueuedrunningsucceededfailedrejectedcanceledexpiredpartial
- identityIdstring | nullrequired0
- 0
- costobjectrequired0
+ Show child fields− Hide child fields
- estimatednumberrequired0
- chargednumberrequired0
- reservationIdstring | nullrequired0
- 0
- targetobjectrequired0
+ Show child fields− Hide child fields
- kindstringrequired0
- tableIdstring0
- viewIdstring0
- columnIdstring0
The send column this action runs (tables.rows.push target column).
- outputobject | nullrequired0
- resultanyrequired0
The single target's result (sync), or null; bulk results are per target.
- 0
- 0
Who started the action.
agentis an LLM-driven caller (the in-app agent, MCP) acting for the key or member inonBehalfOf. - createdAtnumberrequired0
- updatedAtnumberrequired0
ActionApprovalobject
- modestringrequirednonealwaysover_threshold
- urlstring | nullrequired0
- decidedBystring | nullrequired0
- decidedAtnumber | nullrequired0
- expiresAtnumber | nullrequired0
ActionCountsobject
- totalintegerrequired0
- queuedintegerrequired0
- scheduledintegerrequired0
- runningintegerrequired0
- succeededintegerrequired0
- skippedintegerrequired0
- failedintegerrequired0
- canceledintegerrequired0
ActionErrorobject
- codestringrequired0
- messagestringrequired0
ActionActorobject
Who started the action. agent is an LLM-driven caller (the in-app
agent, MCP) acting for the key or member in onBehalfOf.
- kindstringrequiredapiKeysessionagentjob
- idstringrequired0
API key id, user id, agent run id or job id.
- onBehalfOfobject0
Agent only.
+ Show child fields− Hide child fields
- kindstringrequiredapiKeysession
- idstringrequired0
Planobject
What a real call would do, from every check up to the first side
effect. Nothing is reserved, sent, written or charged. The plan is
stored for 15 minutes: send its planId with the real call to run
exactly what was reviewed (409 PLAN_STALE with a new plan if
anything bound changed or it expired).
- operationIdstringrequired0
- classstringrequired
Safety class: decides scope, approval, caps and enforcement.
readwritespendexternal_writesend - identityIdstring | nullrequired0
- targetsobjectrequired0
+ Show child fields− Hide child fields
- totalintegerrequired0
- wouldRunintegerrequired0
- wouldSkiparray of objectrequired0
+ Show child fields− Hide child fields
- reasonstringrequired0
- countintegerrequired0
- samplearray of stringrequired0
- creditsobjectrequired0
+ Show child fields− Hide child fields
- estimatedMinnumberrequired0
- estimatedMaxnumberrequired0
- availablenumberrequired0
- capRemainingnumber | nullrequired0
- quotaobject | nullrequired0
LinkedIn sends: the daily budget the action spends (an estimate: warm-up, health and the identity's other sends move it; the send gate decides at send time).
bucketis the daily limit's key,identityRemainingTodaywhat the identity's account has left today,keyRemainingTodaythe key's, user's or agent's daily sends left (null: uncapped),wouldDeferthe targets that would wait for a later day,firstSlotAt/lastSlotAtwhen the first and last of them would go (ms; null past 7 days). Null for other operations.+ Show child fields− Hide child fields
- bucketstringrequired0
- identityRemainingTodaynumberrequired0
- keyRemainingTodaynumber | nullrequired0
- wouldDefernumberrequired0
- firstSlotAtnumber | nullrequired0
- lastSlotAtnumber | nullrequired0
- approvalobjectrequired0
+ Show child fields− Hide child fields
- requiredbooleanrequired0
- reasonstring | nullrequiredkey_modeoperation_floorover_thresholdagentrequestedidentity_owner
- writesobjectrequired0
- previewarray of anyrequired0
The first targets that would run (at most 5).
- planIdstringrequired
Valid until
expiresAt, for the principal that made the dry run only.pattern ^plan_[0-9a-f]{48}$ - expiresAtnumberrequired0
When the plan expires (epoch milliseconds).
TableHistoryEntryobject
- idstringrequired0
- rowIdstringrequired0
- columnKeystring | nullrequired0
- eventstringrequiredcell_setrow_createdrow_deletedrow_mergedrow_restored
- oldValueanyrequired0
- newValueanyrequired0
- actorTypestringrequired0
- actorIdstringrequired0
- requestIdstring | nullrequired0
- atnumberrequired0
PagedResponseMetaobject
Metadata on a paginated success response.
- requestIdstringrequired0
- 0
- 0
Cursor pagination.
hasMoreis the only end signal; pages may be short.