Overview
API keys and controls
Per-key limits, read-only keys, safe retries and statements for teams that run agents in production.
An agent that spends money needs limits that hold even when its code has a bug. FiloBook lets you put those limits on the API key itself, so the server refuses an order before it reaches the book.
Key policy
Set a policy when you create a key in the app (API keys), or change it later on the same page. The key string does not change when you edit its policy.
| Field | What it does | Refused with |
|---|---|---|
Access: full / read | A read key can call GET endpoints only: dashboards, monitoring, accounting. Any write returns 403. | 403 key_read_only |
| Max per order | Highest max_price the key may post, in USDG. Checked on every order, also inside a batch. | 403 key_max_order |
| Daily budget | USDG the key may commit per UTC day: the max_price of its open orders plus the price of its filled orders. Cancelled and expired orders free their share. | 403 key_daily_budget |
| Request types | The only type values the key may post, for example market_data and web_search. Empty = all. | 403 key_type_not_allowed |
Limits apply to orders posted with that key. A browser session of the same wallet is not limited by them, and neither are other keys. The app shows what each key has committed today.
maxPerFill and dailyCap, which your wallet sets on-chain and the settlement key cannot exceed. Use both: the key policy stops a runaway agent early, the escrow caps what can ever be paid. See Settlement.Idempotency
Networks drop responses. To retry POST /v1/orders or POST /v1/orders/batch without posting twice, send an Idempotency-Key header. Use a new random value per logical order and reuse it only for retries.
curl -X POST https://dapp.filobook.run/v1/orders \
-H "Authorization: Bearer $FILOBOOK_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c1e4b2a-run-42" \
-d '{ "request": "ETH-USD spot, JSON", "type": "market_data", "max_price": "0.002" }'- Same key and same body within 24 hours: you get the stored first response, with header
idempotent-replay: true. No new order is created. - Same key with a different body:
422 idempotency_mismatch. - Same key while the first request is still running:
409 idempotency_in_progress. Retry after a moment. - Only successful responses are stored. If the first attempt failed (bad input, rate limit), a retry with the same key runs again.
- Keys are scoped to your wallet and the endpoint, so two wallets cannot collide.
Statements
`GET /v1/me/statement` exports your fills for a period as JSON or CSV for accounting: role, counterparty, price, savings, settlement tx, ledger entry and the key that posted each order. Each statement carries a statement_hash and the latest ledger anchor, so you can later show it was not edited. The app's My activity page has the same export.
Proof you can keep
- Signed receipts: an EIP-712 signature from the settlement key over each fill's facts. Verify it offline with any EIP-712 library.
- Ledger anchors: the ledger head is written to Robinhood Chain every hour when the ledger grew, so entries below an anchor cannot be rewritten without it showing.
- Provider SLA: quote pass rate, latency and settle rate per provider, from the same data the book uses.
- The dapp's Trust center checks the latest anchor against the chain in your browser.