API

Errors and rate limits

Response envelope, 429 Retry-After, RateLimit headers, and inventory caps.

Response envelope

Successful tool calls return:

{ "ok": true, "data": { … } }

Failures return:

{ "ok": false, "error": { "code": "…", "message": "…", "details": { … } } }

Per-tool pages document the shape of data. Sidebar response examples are illustrative.

Unknown fields

Unknown request fields (including nested paths such as boxes[0].typo or alertSettings.foo) are rejected. They are not silently ignored.

  • Tool HTTP status is typically 400
  • Body: { "ok": false, "error": { "code": "invalid_argument", "message": "…", "details": { "fields": ["…"] } } }
  • MCP tools/call returns the same error object with isError: true

Budgets use baseCurrency; boxes, expenses, accounts, transactions, and investments use per-item currency. Values are ISO 4217 codes from the Currencies allow-list.

Idempotency

Create-style tools require a client key so a retry after a timeout does not insert twice (create_budget, create_box, create_expense, create_transaction, create_investment_group, create_investment, link_account, duplicate_budget, duplicate_box, duplicate_expense).

create_transactions uses a per-row idempotencyKey instead of a top-level key (same namespace as create_transaction). The batch counts as one write toward the rate limit.

SituationHTTPerror.code
Missing / invalid key400idempotency_key_invalid
Header and body key disagree400idempotency_key_mismatch
Same key, different body409idempotency_conflict
Same key still processing409idempotency_in_progress
Same key, same body (replay)200— (original data)

Send Idempotency-Key on HTTP and/or idempotencyKey in the JSON / MCP arguments. Keys last about 24 hours. See Tools index.

Rate limits

Fixed minute windows. Each API token (liq_…) and each OAuth access token has its own read and write budget. API scripts and MCP sessions do not share one account-wide pool.

LimitScopeCap
Tool readsEach token (PAT or OAuth access token)60 / minute
Tool writesEach token (PAT or OAuth access token)60 / minute
Failed authenticationsEach client IP20 / minute

After 20 failed Bearer authentications from one IP in a minute, every request from that address receives 429 until the window ends, even with a valid token.

Inventory

ResourceCap
Active API tokens (liq_… PATs)10 / user

Create tokens in the app (Connections → API tokens); an 11th active token is rejected there. Plan Analysis / Transactions Analysis daily caps are separate (Pro and Ultra 10/day) and not exposed on this API.

Creation caps

Hitting a collection cap returns resource_limit.

ResourceCap
Owned budgets (Ultra Tools / MCP)20
Boxes per budget30
Expenses per box100
Nested create_budget tree items3000
create_transactions rows per call100
Linked accounts per budget30
Manual transactions per account1000
Manual investment groups per budget30
Manual holdings per investment group1000

Field caps

Out-of-range values return invalid_argument.

FieldCap
Names, descriptions, city, group, code, isin100 characters
Money amounts (boxes, expenses, balances, …)0 … 1,000,000
Manual transaction amount±1,000,000
Budget monthlyNetIncome0 … 3,000,000,000

search_help returns at most 10 hits (limit default 5).

On limit

  • HTTP 429
  • Header Retry-After: <seconds>
  • JSON body includes error / retryAfterSeconds (and often code: assistant_rate_limited)

On success

Response may include:

  • RateLimit-Limit
  • RateLimit-Remaining
  • RateLimit-Reset (unix seconds)

Clients must honor Retry-After and avoid tight retry loops.