Workspace

Upsert rows on matchColumns (the single v2 batch write primitive)

Changed on

v2's one row-write endpoint; there is no bare per-row insert (an insert-only call is just an upsert whose rows match nothing). All writes go through api_batches and are idempotent per batchId.

Rows matching an existing row on every matchColumns value update that row's input cells; non-matching rows insert. Per-row inserted/updated/skipped outcomes are recorded on the batch.

  • Row keys and matchColumns are input column slugs (from GET /tables/{tableId}/columns → columns[].slug), never display names. A non-slug row key → UNKNOWN_FIELDS.
  • matchColumns (required) must be real input columns (UNKNOWN_COLUMN) and every match value must be present + non-empty on every row (MISSING_MATCH_VALUE).
  • Duplicate request keys → DUPLICATE_MATCH_KEY; multiple existing rows match one key → AMBIGUOUS_MATCH (409).
  • enrich (default true) enriches freshly inserted rows.
  • reenrichUpdated (default false): set true to also re-run enrichment on rows the upsert updated (re-spends credits); off by default so an upsert never silently re-enriches matched rows.

Only input-kind columns are writable. Enrichment, score, and sequence columns are populated automatically; sequences are agent/column-generated only (see POST /tables/{tableId}/campaigns), never set via this endpoint; passing one returns NON_INPUT_COLUMNS.

The response references the tracking object by id: it is an enrichment_run the caller polls via GET /enrichment-runs/{runId}.

post/tables/{tableId}/rows/upsert

Request

  • Base URL
    https://origami.chat/api/v2
  • URL
    https://origami.chat/api/v2/tables/{tableId}/rows/upsert
  • Auth
    HTTP bearer

Headers

Idempotency-Keystring

Transport-level replay protection: any v2 POST may send it (1-255 printable ASCII characters; UUIDs recommended). The first response for a key is recorded and replayed verbatim for retries with the same key + method/path/body for 24 hours; replayed responses carry the Idempotency-Replay: true response header. Reusing a key with a different request, or retrying while the original is still in flight, returns 409 IDEMPOTENCY_ERROR. 5xx responses are never recorded (the retry re-executes).

Request body

rowsobject[] required
matchColumnsstring[] required
enrichboolean
reenrichUpdatedboolean
batchIdstring uuid

Response

Idempotent replay of an existing batchId (same receipt shape).

object'enrichment_run' required
idstring uuid required
batchIdstring uuid required

Legacy alias of id.

tableRunIdstring uuid nullable required

Linked table-run parent (enrich=true batches only). Lets consumers poll GET /tables/{tableId}/runs/{runId} or await the table.run.completed webhook without a version bump. null for enrich=false writes and pre-migration batches. Completion is first-owner scoped: overlapping cells already active under an earlier run are not adopted into this parent, so this run can complete while those cells are still executing elsewhere.

Changes

    • info

      added the non-success response with the status

    • info

      added the non-success response with the status

    • info

      added the non-success response with the status

    • info

      added the required property to the response with the status

    • info

      added the required property to the response with the status