---
title: "Join a member to a row’s thread"
method: PUT
path: "/v1/tables/{tableId}/rows/{rowId}/participants/{person}"
tags: ["Tables"]
---

# Join a member to a row’s thread

`PUT /v1/tables/{tableId}/rows/{rowId}/participants/{person}`

## Request

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

Put the member this credential acts for on the row’s thread, or change how they watch it (`all`, `mentions`, `none`). A participant’s role comes from how they joined, and this endpoint never changes it: send the role they already hold (as the participant list shows it) or, to join, the thread’s default role (`member` on a free-form table); any other role is a 403 `FORBIDDEN`. Another member’s place is never a credential’s to set (403 `FORBIDDEN`), whatever role the key carries. `person` must be an active member of this workspace — anyone else is a 422 `MENTION_NOT_A_MEMBER`.

## Path parameters

- `tableId` string, required: Table ID
- `rowId` string, required: Row ID
- `person` string, required: The member, as a person key: `user:<userId>`

## Request body

- object
  - `role` string, required
  - `watch` 'all' | 'mentions' | 'none', required

## Response `200`

The participant

- object
  - `success` true, required
  - `data` object, required
    - `workspaceId` string, required
    - `tableId` string, required
    - `rowId` string, required
    - `person` string, required
    - `role` string, required
    - `watch` 'all' | 'mentions' | 'none', required
    - `lastReadAt` string
    - `lastReadMessageId` string
    - `addedBy` 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
    - `addedAt` string, 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

---

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