Browse the docs

Reference · 9 operations

Tables: rows

Last updated from API version 2026-10-06 at (live spec, refreshed hourly). openapi.json

tables.rows.list

List a table's rows: newest first, filtered, sorted or changed since a version.

get/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 is 400 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's cellStates (cell run state by column id).

  • changedSincequeryinteger

    A meta.version from an earlier answer: only rows changed after it (no paging; cursor, filter, sort and viewId are not allowed).

    min 0

Responses

200
OK.
Show schema

TableRowListResponse

  • dataarray of TableRowrequired
    0
  • metaTableRowsMetarequired

    Metadata of a rows answer: page for a page, version (store it for changedSince), and for changedSince answers schemaChanged and truncated instead of page.

    0

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"

tables.rows.upsert

Insert or update up to 5,000 rows (500 on some workspaces: more is 422 LIMIT_EXCEEDED).

post/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays 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

  • rowsarray of TableRowInputrequired
    min items 1max items 5000
  • onConflictstring
    updateEmptyoverwriteskipdefault "updateEmpty"

Responses

200
OK.
Show schema

TableRowUpsertResponse

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": {}
    }
  ]
}'

tables.rows.bulkUpdate

Set the same cells on many rows.

patch/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays 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

  • cellsobjectrequired
    0
  • rowIdsarray of string
    0
  • filterany

    A filter tree (the filter language).

    0
  • confirmCountinteger
    min 0

Responses

200
OK.
Show schema

TableRowBulkUpdateResponse

  • dataobjectrequired
    0
    + Show child fields
    • versionnumberrequired
      0
    • matchedintegerrequired
      0
    • updatedintegerrequired
      0
    • notFoundintegerrequired
      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

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": {}
}'

tables.rows.bulkDelete

Delete many rows.

post/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays 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

200
OK.
Show schema

TableRowBulkDeleteResponse

  • dataobjectrequired
    0
    + Show child fields
    • versionnumberrequired
      0
    • matchedintegerrequired
      0
    • deletedintegerrequired
      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

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
}'

tables.rows.push

Push rows to contacts, a sequence or a CRM.

post/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays 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

  • targetstringrequired
    contactssequencecrmcolumn
  • columnIdstring

    Target column only; a send column of this table (its operation, input and identity).

    0
  • identityIdstring | null

    Target column only; the sender when the column names none (else the key's bound identity, or the session member's own).

    0
  • mappingobject

    Target contacts only.

    0
  • dryRunboolean
    0
  • onConflictstring

    Target contacts only.

    fillEmptyskip
  • sequenceIdstring

    Target sequence only; an existing sequence of this workspace.

    0
  • crmobject

    Target crm only.

    0
    + Show child fields
    • providerstringrequired
      hubspot
    • objectstringrequired
      contactcompany
    • onConflictstring

      fillEmpty (default): write only the fields the CRM has empty. overwrite: also replace CRM values that differ. Never clears a field.

      fillEmptyoverwrite
  • requestApprovalboolean

    Targets sequence, crm and column; ask a person even when the key's approval mode would not.

    0
  • planIdstring

    Targets sequence, crm and column; apply this dry run's plan.

    pattern ^plan_[0-9a-f]{48}$
  • rowIdsarray of string
    0
  • filterany

    A filter tree (the filter language).

    0
  • confirmCountinteger
    min 0

Responses

200
OK.
Show schema
202
Target sequence, crm or column: the action was created (pending_approval until a person approves it in the app).
Show schema

ActionResponse

  • dataobjectrequired
    0
    + Show child fields
    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

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
}'

tables.rows.get

Get one row with its version.

get/api/v1/tables/{id}/rows/{rowId}
Scope
read
Credits
Free
Idempotency-Key
Not used

Parameters

  • idpathstringrequired

    The table id.

  • rowIdpathstringrequired

    The row id.

Responses

200
OK.
Show schema

TableRowResponse

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"

tables.rows.update

Update a row's cells, optionally only if unchanged (If-Match).

patch/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • If-Matchheaderstring

    The row's version as read (12, "12" or W/"12"). When it no longer matches, nothing is written and the answer is 412 VERSION_CONFLICT with details.currentVersion. Without it, the last write wins (row history keeps both values).

Request body (required) · application/json

TableRowUpdateRequest

  • cellsobjectrequired
    0
  • replaceboolean

    Clear every other cell of the row.

    0

Responses

200
OK.
Show schema

TableRowResponse

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": {}
}'

tables.rows.delete

Delete a row, optionally only if unchanged (If-Match).

delete/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 with Idempotent-Replayed: true. Results over 64 KB are not stored; their replay is 409 IDEMPOTENCY_RESULT_UNAVAILABLE with details.originalRequestId (check state with a GET). Same key while the first request runs: 409 IDEMPOTENCY_IN_PROGRESS with Retry-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: a 402 INSUFFICIENT_CREDITS replays even after a top-up, so use a new Idempotency-Key after adding credits.

    min length 1max length 255
  • If-Matchheaderstring

    The row's version as read (12, "12" or W/"12"). When it no longer matches, nothing is written and the answer is 412 VERSION_CONFLICT with details.currentVersion. Without it, the last write wins (row history keeps both values).

Responses

200
OK.
Show schema

TableRowDeleteResponse

  • dataobjectrequired
    0
    + Show child fields
    • idstringrequired
      0
    • deletedbooleanrequired
      0
    • versionnumberrequired
      0
  • metaResponseMetarequired

    Metadata on every success response.

    0

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)"

tables.rows.history

A row's history, newest first.

get/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 is 400 CURSOR_MISMATCH.

Responses

200
OK.
Show schema

TableRowHistoryResponse

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
  • idstringrequired
    0
  • tableIdstringrequired
    0
  • cellsobjectrequired

    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, is null here and its text form is in legacyCells.

    0
  • legacyCellsobject | nullrequired

    {columnKey: text} for cells whose stored value is not valid for the column type (kept as text, never lost); null when there are none. Kept outside cells so it never collides with a column key.

    0
  • linkedContactIdstring | nullrequired
    0
  • linkedCompanyIdstring | nullrequired
    0
  • sourceRefstring | nullrequired

    The source record this row was refreshed from; null for manual rows.

    0
  • versionnumberrequired

    The row's version; send it as If-Match to update or delete only an unchanged row.

    0
  • createdAtnumberrequired
    0
  • updatedAtnumberrequired
    0
  • deletedAtnumber

    Only in changedSince answers, on rows deleted since (tombstones).

    0
  • cellStatesobject

    With include=cellState and in changedSince answers. Run state by column id.

    0
  • truncatedbooleanrequired

    True when at least one value in cells or legacyCells was over the 32 KB cell cap.

    0
  • truncatedCellsarray of stringrequired

    Keys in cells cut (strings) or returned as null (structured values) by the cell cap.

    0
  • truncatedLegacyCellsarray of stringrequired

    Keys in legacyCells cut by the cell cap.

    0
TableCellStateobject

Run state of one computed cell.

  • statusstringrequired
    queuedrunningdoneno_resulterrorstaleskipped
  • lastRunIdstring | nullrequired
    0
  • creditsChargednumberrequired
    0
  • providerstring | nullrequired
    0
  • errorCodestring | nullrequired
    0
  • errorMessagestring | nullrequired
    0
  • versionnumberrequired
    0
  • updatedAtnumberrequired
    0
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.

  • requestIdstringrequired
    0
  • creditsCreditsMetarequired
    0
  • Cursor pagination. hasMore is the only end signal; pages may be short.

    0
  • versionnumberrequired
    0
  • schemaChangedboolean

    A column or view changed since changedSince; refetch the table.

    0
  • truncatedboolean

    Not every change is in this answer; refetch the visible rows.

    0
CreditsMetaobject
  • usednumberrequired

    Credits charged by this request. Reads are free.

    0
  • balancenumber
    0
  • estimatednumber

    Dry run only (action operations).

    0
  • availablenumber

    Dry run only (action operations).

    0
  • reservationIdstring | null

    Async operations only; the job settles this reservation.

    0
PageMetaobject

Cursor pagination. hasMore is the only end signal; pages may be short.

  • nextCursorstring | nullrequired
    0
  • hasMorebooleanrequired
    0
  • limitintegerrequired
    min 1max 200
TableRowInputobject
  • idstring

    Update this row of the table.

    0
  • cellsobjectrequired
    0
  • dedupeKeystring | null
    max length 500
  • linkedContactIdstring | null
    0
  • linkedCompanyIdstring | null
    0
TableRowUpsertResultobject
  • versionnumberrequired
    0
  • insertedintegerrequired
    0
  • updatedintegerrequired
    0
  • skippedintegerrequired
    0
  • resultsarray of TableRowWriteResultrequired
    0
TableRowWriteResultobject
  • indexintegerrequired
    0
  • idstring | nullrequired
    0
  • statusstringrequired
    insertedupdatedskipped
  • errorsarray of object
    0
    + Show child fields
    • codestringrequired
      INVALID_CELL_VALUELIMIT_EXCEEDEDNOT_FOUND
    • messagestringrequired
      0
    • columnKeystring
      0
    • expectedstring
      0
ResponseMetaobject

Metadata on every success response.

  • requestIdstringrequired
    0
  • creditsCreditsMetarequired
    0
  • Cursor pagination. hasMore is the only end signal; pages may be short.

    0
  • dryRunboolean

    True only on a dry-run response (action operations).

    0
TableRowPushResponseobject
  • dataobjectrequired
    0
    + Show child fields
    • targetstringrequired
      0
    • dryRunbooleanrequired
      0
    • mappingobjectrequired
      0
    • versionnumber | nullrequired
      0
    • createdintegerrequired
      0
    • updatedintegerrequired
      0
    • unchangedintegerrequired
      0
    • skippedintegerrequired
      0
    • failedintegerrequired
      0
    • resultsarray of TableRowPushResultrequired
      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
TableRowPushResultobject
  • rowIdstringrequired
    0
  • statusstringrequired
    createdupdatedunchangedskippedfailed
  • contactIdstring | nullrequired
    0
  • matchedBystring | nullrequired
    linklinkedinemail
  • fieldsarray of string
    0
  • errorsarray of object
    0
ActionRunResponseobject

{data: {action, result}} when the action ran inline, or {data: {plan}} with meta.dryRun: true for a dry run.

  • dataone ofrequired
    0
    + Show child fields

    One of

    with action

    • actionActionrequired

      One action run. Read it again with GET /api/v1/actions/{id}.

      0
    • resultanyrequired

      The target's result, or null when it was skipped or failed.

      0

    with plan

    • planPlanrequired

      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).

      0
  • metaResponseMetarequired

    Metadata on every success response.

    0
Actionobject

One action run. Read it again with GET /api/v1/actions/{id}.

  • idstringrequired
    0
  • kindstringrequired

    The operation id.

    0
  • classstringrequired

    Safety class: decides scope, approval, caps and enforcement.

    readwritespendexternal_writesend
  • statusstringrequired
    pending_approvalqueuedrunningsucceededfailedrejectedcanceledexpiredpartial
  • identityIdstring | nullrequired
    0
  • approvalActionApproval | nullrequired
    0
  • costobjectrequired
    0
    + Show child fields
    • estimatednumberrequired
      0
    • chargednumberrequired
      0
    • reservationIdstring | nullrequired
      0
  • countsActionCountsrequired
    0
  • targetobjectrequired
    0
    + Show child fields
    • kindstringrequired
      0
    • tableIdstring
      0
    • viewIdstring
      0
    • columnIdstring

      The send column this action runs (tables.rows.push target column).

      0
  • outputobject | nullrequired
    0
  • resultanyrequired

    The single target's result (sync), or null; bulk results are per target.

    0
  • errorActionErrorrequired
    0
  • actorActionActorrequired

    Who started the action. agent is an LLM-driven caller (the in-app agent, MCP) acting for the key or member in onBehalfOf.

    0
  • createdAtnumberrequired
    0
  • updatedAtnumberrequired
    0
ActionApprovalobject
  • modestringrequired
    nonealwaysover_threshold
  • urlstring | nullrequired
    0
  • decidedBystring | nullrequired
    0
  • decidedAtnumber | nullrequired
    0
  • expiresAtnumber | nullrequired
    0
ActionCountsobject
  • totalintegerrequired
    0
  • queuedintegerrequired
    0
  • scheduledintegerrequired
    0
  • runningintegerrequired
    0
  • succeededintegerrequired
    0
  • skippedintegerrequired
    0
  • failedintegerrequired
    0
  • canceledintegerrequired
    0
ActionErrorobject
  • codestringrequired
    0
  • messagestringrequired
    0
ActionActorobject

Who started the action. agent is an LLM-driven caller (the in-app agent, MCP) acting for the key or member in onBehalfOf.

  • kindstringrequired
    apiKeysessionagentjob
  • idstringrequired

    API key id, user id, agent run id or job id.

    0
  • onBehalfOfobject

    Agent only.

    0
    + Show child fields
    • kindstringrequired
      apiKeysession
    • idstringrequired
      0
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).

  • operationIdstringrequired
    0
  • classstringrequired

    Safety class: decides scope, approval, caps and enforcement.

    readwritespendexternal_writesend
  • identityIdstring | nullrequired
    0
  • targetsobjectrequired
    0
    + Show child fields
    • totalintegerrequired
      0
    • wouldRunintegerrequired
      0
    • wouldSkiparray of objectrequired
      0
      + Show child fields
      • reasonstringrequired
        0
      • countintegerrequired
        0
      • samplearray of stringrequired
        0
  • creditsobjectrequired
    0
    + Show child fields
    • estimatedMinnumberrequired
      0
    • estimatedMaxnumberrequired
      0
    • availablenumberrequired
      0
    • capRemainingnumber | nullrequired
      0
  • quotaobject | nullrequired

    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). bucket is the daily limit's key, identityRemainingToday what the identity's account has left today, keyRemainingToday the key's, user's or agent's daily sends left (null: uncapped), wouldDefer the targets that would wait for a later day, firstSlotAt / lastSlotAt when the first and last of them would go (ms; null past 7 days). Null for other operations.

    0
    + Show child fields
    • bucketstringrequired
      0
    • identityRemainingTodaynumberrequired
      0
    • keyRemainingTodaynumber | nullrequired
      0
    • wouldDefernumberrequired
      0
    • firstSlotAtnumber | nullrequired
      0
    • lastSlotAtnumber | nullrequired
      0
  • approvalobjectrequired
    0
    + Show child fields
    • requiredbooleanrequired
      0
    • reasonstring | nullrequired
      key_modeoperation_floorover_thresholdagentrequestedidentity_owner
  • writesobjectrequired
    0
  • previewarray of anyrequired

    The first targets that would run (at most 5).

    0
  • planIdstringrequired

    Valid until expiresAt, for the principal that made the dry run only.

    pattern ^plan_[0-9a-f]{48}$
  • expiresAtnumberrequired

    When the plan expires (epoch milliseconds).

    0
TableHistoryEntryobject
  • idstringrequired
    0
  • rowIdstringrequired
    0
  • columnKeystring | nullrequired
    0
  • eventstringrequired
    cell_setrow_createdrow_deletedrow_mergedrow_restored
  • oldValueanyrequired
    0
  • newValueanyrequired
    0
  • actorTypestringrequired
    0
  • actorIdstringrequired
    0
  • requestIdstring | nullrequired
    0
  • atnumberrequired
    0
PagedResponseMetaobject

Metadata on a paginated success response.

  • requestIdstringrequired
    0
  • creditsCreditsMetarequired
    0
  • pagePageMetarequired

    Cursor pagination. hasMore is the only end signal; pages may be short.

    0

← All operations