# Sync bank

URL: https://docs.hanzo.ai/docs/openapi/books/post-books-bank-sync

> Pulls every connected bank (Plaid/Teller) for the caller's org, maps each fetched transaction to a posting and books it idempotently, then advances that connector's cursor so the next sync resumes where this one stopped.

`POST /v1/books/bank/sync`

> [Books →](https://docs.hanzo.ai/docs/openapi/books) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                           |
| ------------- | ----------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/books/bank/sync` |
| **Method**    | `POST`                                    |
| **Operation** | `post_books_bank_sync`                    |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY`    |

Pulls every connected bank (Plaid/Teller) for the caller's org, maps each
fetched transaction to a posting and books it idempotently, then advances that
connector's cursor so the next sync resumes where this one stopped. One connector's
outage is skipped rather than failing the whole sync. It reports the batch: how many
transactions were seen, how many vouchers posted, how many inflows reconciled against
the processor clearing account, how many raised a question, how many were own-account
transfers, and how many were already-processed no-ops. It is READ-ONLY against the
bank — it ingests, it never sends money.

## Request

The document declares no body for `POST /v1/books/bank/sync`. The handler is typed in cloud but its shape is not yet emitted, so the fields are not listed here — ask MCP's `describe` for `post_books_bank_sync`, which answers from the running route.

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `200`     | books.BankTally | ok      |
| `default` | problem-details | refused |

`200` body — 6 fields.

| Field        | In   | Type            | Always | Description                                  |
| ------------ | ---- | --------------- | ------ | -------------------------------------------- |
| `ingested`   | body | integer (int64) | —      | transactions seen                            |
| `posted`     | body | integer (int64) | —      | vouchers newly posted (outflow + reconciled) |
| `questions`  | body | integer (int64) | —      | unmatched inflows that raised a question     |
| `reconciled` | body | integer (int64) | —      | inflows cleared against Square-clearing      |
| `skipped`    | body | integer (int64) | —      | already-processed idempotent no-ops          |
| `transfers`  | body | integer (int64) | —      | own-account moves recorded (no P\&L)         |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo books bank sync
```

**SDK**

**.ts**

```ts
import { Configuration, BooksApi } from 'hanzoai';

const api = new BooksApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postBooksBankSync();
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import BooksApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = BooksApi(client).post_books_bank_sync()
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.BooksAPI.PostBooksBankSync(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, books_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = books_api::post_books_bank_sync(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.BooksApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new BooksApi(client).postBooksBankSync();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/books/bank/sync \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

MCP reaches **books** through the `books` tool, which names its 20 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_book_accounts"
         }
       }
     }'
```

---

[Books API](https://docs.hanzo.ai/docs/openapi/books) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
