---
title: "Update Bank Account"
method: PUT
path: "/bank-accounts/{account_id}"
tags: ["reconciliation"]
---

# Update Bank Account

`PUT /bank-accounts/{account_id}`

## Request

- Base URL: `https://app.zeno-works.ch` (the document declares no server; this is the origin it was published from)
- URL: `https://app.zeno-works.ch/bank-accounts/{account_id}`
- Auth: none declared

Update a bank account; a ledger-mapping change marks + bridges the chart side.

Setting ``ledger_account_number`` runs ``bridge_bank_account_to_chart`` in the same
transaction (mark ``control_type=bank`` + ``gl_bank_account`` bridge) — this is the
correction path the bridge's soft skips point at, and it previously updated only the
row, leaving mark and bridge stale. Clearing the mapping (explicit ``null``) only
clears the row — demoting the chart mark stays an explicit act via
``PATCH /gl/accounts``.

**The whole route is accountant-gated (ZCT-257).** It used to gate only the
``ledger_account_number`` field, with "label/currency edits stay member-level" — so a
plain member could rename any bank account and change its currency. The owner ruling
of 2026-08-31 makes every create/update/delete accountant-or-better, and a conditional
gate also read as a full gate to the api-contract classifier, printing ``accountant``
for a route a member could still use.

## Path parameters

- `account_id` string, required

## Headers

- `authorization` string, nullable

## Cookies

- `access_token` string, nullable

## Request body

- BankAccountUpdate
  - `label` string, nullable
  - `currency` string, nullable
  - `ledger_account_number` string, nullable

## Response `200`

Successful Response

- BankAccountResponse
  - `bank_account` BankAccountOut, required
    - `id` string, required
    - `company_id` string, required
    - `iban` string, required
    - `currency` string, nullable
    - `label` string, nullable
    - `holder_name` string, nullable
    - `bic` string, nullable
    - `bank_name` string, nullable
    - `ledger_account_number` string, nullable
    - `auto_created` boolean, required
    - `ownership_status` 'declared' | 'confirmed' | 'pending', required: Ownership state of a ``BankAccount`` (gap #8, D3 — foreign-statement hold). ``declared`` = the user declared the IBAN as the company's own (onboarding); ``confirmed`` = a human confirmed a statement-created account as ours (or the account predates the check and was grandfathered by migration 0032); ``pending`` = created by a statement import for an IBAN the company never declared — its entries are held (no matching, no GL settlement) until a human confirms or rejects the account. Server default is ``pending`` (fail-closed).
    - `ownership_reviewed_at` string, date-time, nullable
    - `needs_ownership_review` boolean
    - `created_at` string, date-time, required
    - `statement_count` integer, nullable
    - `entry_count` integer, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/zeno-works/apis/zeno-api.md) · [All operations](https://skmtc.dev/zeno-works/apis/zeno-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zeno-works/apis/zeno-api/revisions/1eb93dde146c?raw)
