---
title: "Link or unlink related rows"
method: POST
path: "/v1/tables/{tableId}/rows/{rowId}/relations/{fieldKey}"
tags: ["Tables"]
---

# Link or unlink related rows

`POST /v1/tables/{tableId}/rows/{rowId}/relations/{fieldKey}`

## Request

- Base URL: `https://api.banksync.io`
- URL: `https://api.banksync.io/v1/tables/{tableId}/rows/{rowId}/relations/{fieldKey}`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Operation-shaped (`add` / `remove` / `set` / `reorder`) rather than "here is the new list", because cardinality is enforced by the statement: a `one`-sided `add` that would create a second live link fails in SQL, not after a read another writer can invalidate. Returns the cell as it now reads.

## Path parameters

- `tableId` string, required: Table ID
- `rowId` string, required: Row ID
- `fieldKey` string, required: Field key

## Request body

- object
  - `op` 'add' | 'remove' | 'set' | 'reorder', required
  - `targetRowIds` string[], required

## Response `200`

The relation cell after the change

- object
  - `success` true, required
  - `property` union, required
    - object
      - `type` 'text', required
      - `value` string, nullable, required
    - object
      - `type` 'long_text', required
      - `value` string, nullable, required
    - object
      - `type` 'url', required
      - `value` string, nullable, required
    - object
      - `type` 'email', required
      - `value` string, nullable, required
    - object
      - `type` 'phone', required
      - `value` string, nullable, required
    - object
      - `type` 'number', required
      - `value` number, nullable, required
      - `currency` string, nullable
    - object
      - `type` 'rating', required
      - `value` number, nullable, required
    - object
      - `type` 'auto_number', required
      - `value` number, nullable, required
      - `text` string, nullable, required
    - object
      - `type` 'checkbox', required
      - `value` boolean, required
    - object
      - `type` 'date', required
      - `value` string, nullable, required
    - object
      - `type` 'datetime', required
      - `value` string, nullable, required
    - object
      - `type` 'select', required
      - `option` object, nullable, required
        - `id` string, required
        - `label` string, required
        - `color` string
        - `group` 'not_started' | 'in_progress' | 'complete'
    - object
      - `type` 'status', required
      - `option` object, nullable, required
        - `id` string, required
        - `label` string, required
        - `color` string
        - `group` 'not_started' | 'in_progress' | 'complete'
    - object
      - `type` 'multi_select', required
      - `options` object[], required
        - `id` string, required
        - `label` string, required
        - `color` string
        - `group` 'not_started' | 'in_progress' | 'complete'
    - object
      - `type` 'user', required
      - `users` object[], required
        - `userId` string, required
        - `name` string, nullable, required
        - `email` string, nullable, required
        - `avatarUrl` string, nullable, required
    - object
      - `type` 'json', required
      - `value` unknown
    - object
      - `type` 'attachment', required
      - `items` object[], required
        - `id` string, required
        - `filename` string, required
        - `contentType` string, required
        - `sizeBytes` integer, required
        - `position` integer, required
        - `thumbnailAvailable` boolean
      - `total` integer, required
      - `hasMore` boolean, required
    - object
      - `type` 'relation', required
      - `items` object[], required
        - `rowId` string, required
        - `tableId` string, required
        - `primary` string, nullable, required
        - `position` integer, required
        - `unavailable` boolean
        - `preview` object[]
          - `key` string, required
          - `text` string, required
      - `total` integer, required
      - `hasMore` boolean, required
    - object
      - `type` 'formula', required
      - `preset` 'lookup' | 'rollup' | 'count' | 'thread'
      - `resultKind` object, required
        - `base` 'text' | 'number' | 'boolean' | 'date' | 'datetime' | 'json' | 'option_counts' | 'currency_totals' | 'record' | 'attachment' | 'user' | 'null', required
        - `list` boolean
      - `value` unknown
      - `currency` string, nullable
      - `stale` boolean, required
      - `error` 'division_by_zero' | 'invalid_value' | 'missing_reference' | 'type_mismatch' | 'complexity_limit' | 'depth_limit' | 'link_limit' | 'unavailable'
    - object
      - `type` 'created_time', required
      - `value` string, required
    - object
      - `type` 'last_edited_time', required
      - `value` string, nullable, required
    - object
      - `type` 'created_by', required
      - `actor` union, required
        - object
          - `kind` 'user', required
          - `userId` string, required
        - object
          - `kind` 'sync', required
          - `feedId` string, required
          - `jobId` string
          - `cause` object
            - `automationId` string, required
            - `runId` string, required
            - `depth` integer, required
            - `untrustedSender` true
        - object
          - `kind` 'extractor', required
          - `feedId` string, required
          - `jobId` string
          - `untrustedSender` true
        - object
          - `kind` 'import', required
          - `importId` string, required
          - `userId` string, required
        - object
          - `kind` 'api', required
          - `clientId` string, required
        - object
          - `kind` 'system', required
          - `reason` string, required
        - object
          - `kind` 'automation', required
          - `automationId` string, required
          - `revision` string, required
          - `grantId` string, required
          - `runId` string, required
          - `node` string, required
          - `startedBy` ActorRef, required (recursive)
          - `depth` integer, required
          - `untrustedSender` true
    - object
      - `type` 'last_edited_by', required
      - `actor` union, required
        - object
          - `kind` 'user', required
          - `userId` string, required
        - object
          - `kind` 'sync', required
          - `feedId` string, required
          - `jobId` string
          - `cause` object
            - `automationId` string, required
            - `runId` string, required
            - `depth` integer, required
            - `untrustedSender` true
        - object
          - `kind` 'extractor', required
          - `feedId` string, required
          - `jobId` string
          - `untrustedSender` true
        - object
          - `kind` 'import', required
          - `importId` string, required
          - `userId` string, required
        - object
          - `kind` 'api', required
          - `clientId` string, required
        - object
          - `kind` 'system', required
          - `reason` string, required
        - object
          - `kind` 'automation', required
          - `automationId` string, required
          - `revision` string, required
          - `grantId` string, required
          - `runId` string, required
          - `node` string, required
          - `startedBy` ActorRef, required (recursive)
          - `depth` integer, required
          - `untrustedSender` true
  - `version` integer, required

## Other responses

- `400`: Validation failed, or a read-only field was written — `code` names the refusal and `details[]` the offending field or cell
- `401`: Unauthorized
- `403`: Forbidden — missing scope, insufficient role, or plan limit reached
- `404`: Not found
- `409`: Conflict — the table is locked, the schema or row version moved, a cell the patch writes was changed by another edit (`ROW_CELL_CONFLICT`, with each cell’s current value in `details`), or a relation accepts one row. `code` says which.

---

[API](https://skmtc.dev/banksync/apis/banksync-api.md) · [All operations](https://skmtc.dev/banksync/apis/banksync-api/llms.txt) · [OpenAPI document](https://skmtc.dev/banksync/apis/banksync-api/revisions/94465f5ee922?raw)
