# company.shareholders.update

Replace the shareholder register with { register: { classes, holders, holdings, officers }, expectedRevision, idempotencyKey } (from company.shareholders.get, changed). Ids are 8 to 40 lowercase letters, digits and hyphens; shares are whole numbers; every holding names a holder and class in the register. Removing a shareholder removes their saved tax number. Audited with counts only.

`POST /api/v1/accounting/company.shareholders.update`

Permissions: `accounting:read`, `accounting:write`, `accounting:admin` · Roles: admin · Idempotency key required · Send `expectedRevision`

MCP tool: `accounting_company_shareholders_update`

## Fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `register` | object | Yes | No other fields. |
| `register.classes` | array of objects | Yes | at most 20 items. |
| `register.classes[].id` | string | Yes | The record's ID. Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.classes[].name` | string | Yes | A display name. 1–60 characters. |
| `register.classes[].kind` | enum | Yes | Which kind of record or job this is. One of: `common`, `preferred`. |
| `register.classes[].voting` | boolean |  | Default `true`. |
| `register.classes[].note` | string |  | A short note, kept with the record. at most 500 characters. Default `""`. |
| `register.holders` | array of objects | Yes | at most 200 items. |
| `register.holders[].id` | string | Yes | The record's ID. Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.holders[].kind` | enum |  | Which kind of record or job this is. One of: `person`, `corporation`, `trust`. Default `"person"`. |
| `register.holders[].legalName` | string | Yes | 1–200 characters. |
| `register.holders[].email` | "" or string (email) |  | An email address. One of: ``. Default `""`. |
| `register.holders[].address` | object |  | No other fields. Default `{"line1":"","line2":"","city":"","region":"","postalCode":"","country":""}`. |
| `register.holders[].address.line1` | string |  | at most 120 characters. Default `""`. |
| `register.holders[].address.line2` | string |  | at most 120 characters. Default `""`. |
| `register.holders[].address.city` | string |  | at most 80 characters. Default `""`. |
| `register.holders[].address.region` | string |  | at most 80 characters. Default `""`. |
| `register.holders[].address.postalCode` | string |  | at most 20 characters. Default `""`. |
| `register.holders[].address.country` | string |  | at most 2 characters. Default `""`. |
| `register.holders[].residency` | enum |  | One of: `canada`, `other`. Default `"canada"`. |
| `register.holders[].note` | string |  | A short note, kept with the record. at most 500 characters. Default `""`. |
| `register.holdings` | array of objects | Yes | at most 1000 items. |
| `register.holdings[].id` | string | Yes | The record's ID. Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.holdings[].holderId` | string | Yes | Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.holdings[].classId` | string | Yes | Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.holdings[].shares` | string | Yes | Matches ^[1-9]\d{0,14}$. |
| `register.holdings[].issuedOn` | string or null |  | Default `null`. |
| `register.holdings[].certificate` | string |  | at most 40 characters. Default `""`. |
| `register.holdings[].considerationMinor` | string or null |  | An amount in cents (the currency's smallest unit), written as a whole-number string such as "1250" for $12.50. Default `null`. |
| `register.holdings[].endedOn` | string or null |  | Default `null`. |
| `register.holdings[].note` | string |  | A short note, kept with the record. at most 500 characters. Default `""`. |
| `register.officers` | array of objects | Yes | at most 50 items. |
| `register.officers[].id` | string | Yes | The record's ID. Matches ^[a-z0-9][a-z0-9-]{7,39}$. |
| `register.officers[].name` | string | Yes | A display name. 1–200 characters. |
| `register.officers[].roles` | array of enum values | Yes | One of: `director`, `president`, `secretary`, `treasurer`, `officer`. 1–5 items. |
| `register.officers[].startedOn` | string or null |  | Default `null`. |
| `register.officers[].endedOn` | string or null |  | Default `null`. |
| `register.officers[].residency` | enum |  | One of: `canada`, `other`. Default `"canada"`. |
| `expectedRevision` | integer | Yes | The record's current revision, from the last time you read it. If someone changed the record since, the request is refused with a conflict so you can reload and check before trying again. 0 to 1000000000. |
| `idempotencyKey` | string | Yes | Any unique text you generate once per intended change, so a retried request only happens once. Send it as the Idempotency-Key header instead if you prefer; if you send both they must match. 8–200 characters. |

## Example request

```bash
curl https://app.getoatmilk.com/api/v1/accounting/company.shareholders.update \
  -H "Authorization: Bearer $OATMILK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "register": {
    "classes": [
      {
        "id": "aaaaaaaa",
        "name": "Synthetic Ventures Inc.",
        "kind": "common"
      }
    ],
    "holders": [
      {
        "id": "aaaaaaaa",
        "legalName": "Synthetic Ventures Inc."
      }
    ],
    "holdings": [
      {
        "id": "aaaaaaaa",
        "holderId": "aaaaaaaa",
        "classId": "aaaaaaaa",
        "shares": "1"
      }
    ],
    "officers": [
      {
        "id": "aaaaaaaa",
        "name": "Synthetic Ventures Inc.",
        "roles": [
          "director"
        ]
      }
    ]
  },
  "expectedRevision": 3
}'
```

Reference page: https://app.getoatmilk.com/docs/api/company.shareholders.update
