# Treasury

URL: https://docs.hanzo.ai/docs/openapi/treasury

> The reserve fund behind every payout: real capital, held and accounted for.

Also for this capability: **API** · [CLI](https://docs.hanzo.ai/docs/cli/treasury) · [SDKs](https://docs.hanzo.ai/docs/sdks)

The reserve fund behind every payout: real capital, held and accounted for.

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

|                |                                        |
| -------------- | -------------------------------------- |
| **Base URL**   | `https://api.hanzo.ai`                 |
| **Operations** | 2                                      |
| **Auth**       | `Authorization: Bearer $HANZO_API_KEY` |

## Specification

> **HIP-1221 · Treasury — The Reserve Fund** — Draft · [read the specification →](https://github.com/hanzoai/hips/blob/7ed737180339cd05b5f2935eafe7f7b83d2449a2/HIPs/hip-1221-treasury-the-reserve-fund.md)

`/v1/treasury` is the reserve fund behind every payout: real capital, held and
accounted for. Where finance tracks what each customer holds and spends,
treasury tracks what the platform holds, so a growth-loop payout — referrals,
affiliates, OSS authors — is a debit against funded capital and never unbounded
minting (`apps/treasury/treasury.go:1-8`). It is `hanzoai/cloud`
`apps/treasury`: the HTTP adapter, tenant scoping, audit and the L1 anchor
around a ledger-of-record port whose backend owns the double-entry.

### Motivation

The app answers on two prefixes today and owns neither whole
(`manifest/apps.go:413`): its front door lives under `/v1/finance`, an address
that belongs to no capability. The reads come home to the app that serves them.

### Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted
as in RFC 2119.

#### §1 Addresses

Every route is typed (`apps/treasury/treasury.go:177-186`), and the target
surface is:

- `GET /v1/treasury` — reserve health and policy, the pool backing the caller's
  payouts (from `/v1/finance/treasury`).
- `GET /v1/treasury/accounts` — the caller's own ledger accounts (from
  `/v1/finance/accounts`; admin may widen with `?scope=house` / `?org=`).
- `/v1/admin/treasury{,/policy,/sweep,/seed,/anchor,/anchor/signer}` — the
  operator's view, served by treasury, already at HIP-0139 §3.2's exempt depth.
  It keeps.

Where the router still serves the `/v1/finance` spellings, the pairs are the
`treasury` lines in cloud's `openapi/misfiled.txt`, closed by fold.

#### §2 The store it owns

Its own double-entry ledger, behind one port (`ledger.Backend`). The default
and offline backend is the native engine — per-tenant Base/SQLite files opened
through `cek` so the namespace keys the file
(`apps/treasury/ledger/sqlstore/sqlstore.go:69`,
`apps/treasury/storage.go:29-34`) — with reserve, revenue and house accounts on
the house tenant. The opt-in backend is a Formance Ledger service, selected by
`FORMANCE_LEDGER_URL` and driven over its v2 HTTP API; the double-entry and the
overdraw guard are Formance's own, never reimplemented here
(`apps/treasury/formance/formance.go:1-14`). Selecting one is a config flip.

The shared datastore OLAP projection is NEVER the ledger of record: single-
tenant drill-down reads the authoritative ledger, cross-tenant aggregates read
the projection (`apps/treasury/treasury.go:22-29`).

#### §3 Tenant

One scope-aware engine, three surfaces projected by IAM scope
(`apps/treasury/treasury.go:30-32`): the tenant is derived from the validated
identity (HIP-0026), house and reserve are locked to SuperAdmin, and a per-org
caller only ever sees its own tenant. The org is never an input.

#### §4 A payout is backed or it is refused

Every payout sink is named once, by program (`apps/treasury/treasury.go:81-84`),
and lands as a debit against the funded reserve through the single-writer,
overdraw-guarded ledger. A transaction the reserve cannot cover MUST be refused
as "not backed" — the native engine and the Formance backend both answer that
way — rather than plugged by minting.

#### §5 The anchor

The books live off-chain, so a deterministic root of the whole journal is
committed to the Hanzo L1 EVM (chain 36963), making any change to a historical
posting visible against an immutable witness (`apps/treasury/anchor.go:15-19`).
The signing key is a KMS reference and MUST NOT be a plaintext key
(`apps/treasury/anchor.go:21-23`; HIP-0027); the signer wallet is set by the
operator at `PUT /v1/admin/treasury/anchor/signer`.

#### §6 Price, events, observability

It is free, in those words: `Price: cloud.Free` (`plugin/treasury/main.go:26`);
reads and SuperAdmin mutations, no meter behind any route.

It publishes no events on the platform bus, so a customer's webhooks (HIP-1310)
receive nothing from it. Every money action lands a best-effort audit record
(`apps/treasury/treasury.go:96`, `:572-578`) that mirrors to the shared
datastore projection on the same event stream o11y already emits — one
pipeline, no second metering path. Beyond that and the request span, nothing.

#### §7 Stage and upstream

The stage is `ga` — the manifest row declares none, and absent is `ga`
(HIP-0139 §8).

It derives from none: no OSS project is forked, embedded or mirrored in HEAD.
The optional Formance backend is a network client onto a separately deployed
service, stated as the dependency it is; none of its code survives here.

### Rationale

The alternative to its own capability is folding the reads into billing, since
both talk about money. They do not share a store: billing projects the
customer's wallet, treasury keeps the platform's book, and HIP-0139 §7.2 only
permits a boundary where the stores divide — which is exactly where this one
sits. The port-and-two-backends shape exists so the reserve works offline today
and the production ledger of record is an upgrade, not a rewrite.

### Security Considerations

The wrong implementation mints. A payout path that skips the ledger creates
unbacked liabilities the reserve cannot cover; the overdraw guard is the
control, and it must fail closed. A tenant taken from the caller instead of the
validated identity reads the house books — revenue, reserve, every program's
payouts — across orgs. A plaintext anchor key lets an attacker sign a false
witness for doctored books, which is why the signer is a KMS reference and the
mutation SuperAdmin-only.

## Four surfaces

| Surface  | Reaches this capability as                       | Coverage                                                                  |
| -------- | ------------------------------------------------ | ------------------------------------------------------------------------- |
| **REST** | `treasury` at its own prefix                     | 2 operations                                                              |
| **CLI**  | `hanzo treasury …`                               | 2 of 2                                                                    |
| **SDK**  | `TreasuryApi` in every published client          | 2 methods                                                                 |
| **MCP**  | tool `treasury` on `https://api.hanzo.ai/v1/mcp` | 2 operations, 0 under the document's own id — ask `describe` for the rest |

## Quickstart

```bash
export HANZO_API_KEY=sk-...   # console.hanzo.ai → API keys
```

Then the first call — a read that needs nothing but the key. `GET /v1/treasury`, operation `get_treasury`:

**CLI**

```bash
hanzo treasury get
```

**SDK**

**.ts**

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

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

**.py**

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

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

**.go**

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

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

**.rs**

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

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

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

**.java**

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

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

var result = new TreasuryApi(client).getTreasury();
```

**HTTP**

```bash
curl https://api.hanzo.ai/v1/treasury \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

MCP reaches **treasury** through the `treasury` tool, which names its 2 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_treasuries"
         }
       }
     }'
```

Answers `200` with `object` — ok.

## Endpoints

| Endpoint                                                                                         | What it does                                                                                     |
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| [`GET /v1/treasury/accounts`](https://docs.hanzo.ai/docs/openapi/treasury/get-treasury-accounts) | Returns the ledger accounts the caller may see, with their balances.                             |
| [`GET /v1/treasury`](https://docs.hanzo.ai/docs/openapi/treasury/get-treasury)                   | Returns the reserve fund's health and the current revenue-share policy for any validated caller. |

---

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