Agent API & MCP
Your agent gets a key. You keep the signature
Connect a Claude or ChatGPT client to the MCP server, or call the same endpoints from your own code with a revocable key.
Base URL: https://app.orla.finance/api · Selling to machines? The integration API is the other door.
Four ways in
A connector, the CLI, your own code, or a skill file
Ways in
- An MCP connector
- Add app.orla.finance/api/mcp in Claude, Cursor, VS Code, Zed or Windsurf and approve the space once; no key to paste.
- The CLI
- For a script, a cron job, or a laptop that does the books on Sundays. Open source under MIT: npx orla-cli.
- Your own code
- A bearer key over HTTPS, shown once and revocable on its own.
- A skill file
- npx skills add cheetah-trade/orla-cli, or orla.finance/skill.md. One file teaches an agent both doors and where paying stops.
- The other direction
- Webhooks: six signed events from the book to an address of yours, documented at orla.finance/en/webhooks.
- What a grant carries
- Spaces, a role in each, the accounts it may see, a daily payment cap and a write budget; yours to set.
- The contract, for a machine
- orla.finance/openapi.json is the OpenAPI description of the agent endpoints below and of the integration API, cut to those two doors.
The one rule the API cannot be talked out of
An agent asks to pay. A person releases it
A write inside the budget lands as a transaction. A write outside it, or any payment, comes back as a proposal id and waits on the Agents screen.
# $API = https://app.orla.finance/api
curl -X POST $API/agent/spaces/$SPACE/transactions \
-H "Authorization: Bearer $ORLA_KEY" \
-H "Idempotency-Key: 2026-03-28-hetzner" \
-H "Content-Type: application/json" \
-d '{
"occurred_on": "2026-03-28",
"amount": "-58.00",
"currency": "EUR",
"payee": "Hetzner",
"category": "Hosting"
}'The tools
Agents can read and record. Payments wait for a person
The MCP tool names and the HTTP endpoints are the same calls, computed against the grant at the moment of the call, never cached.
| Tool | Endpoint | What it does | Needs a person |
|---|---|---|---|
orla_ | GET / | Which spaces this key reaches, what it may do in each, and whether it is still observing | no |
orla_ | GET / | The accounts the grant exposes, with balances | no |
orla_ | GET / | The categories of the space, for sorting rows | no |
orla_ | GET / | Transactions, newest first, with the usual filters | no |
orla_ | GET / | The approval queue: every payment that is waiting for a person to sign it | no |
orla_ | POST / | Record an income or an expense inside the daily write budget; a proposal while observing | no |
orla_ | PATCH / | Correct the category, payee or note, never the amount, date or account; while observing, a proposal | no |
orla_ | POST / | Propose a payment the way the payee is already paid, and receive a pending payment id | yes, always |
orla_ | POST / | Prepare a crypto send to a trusted address, screened before it is built at all | yes, always |
orla_ | GET / | Its own float: addresses and what they hold | no |
orla_ | GET / | How much it may still spend today: the daily ceiling, what is spent and left, the per-request ceiling, the hosts it may pay | no |
orla_ | POST / | USDT or USDC from its wallet to a trusted address | only past its limits |
orla_ | POST / | Fetch a URL that answers 402, pay the quoted price from the wallet, return the content | no inside the ceilings |
orla_ | GET / | The agent's card: balance, last four digits, and the merchant rules and ceilings where the card carries any. A new card carries none, and its balance is the whole limit | no |
orla_ | POST / | The number, expiry, CVV and 3-D Secure password, handed over once. A second ask is refused until the owner saves the card's form again, and what was taken cannot be taken back | the owner arms it, per card |
orla_ | POST / | The latest one-time code for a payment that asks for 3-D Secure. Armed by the same switch and not rationed; when no code exists yet, the answer says so in words | the owner arms it, per card |
orla_ | POST / | A short-lived link to the issuer's own page with the number, expiry and CVV, for a card whose issuer has such a page. A new card has none, so the call is refused and orla_card_details is the way | no |
| HTTP only | POST / | Ask for wider access; the fence is the owner's to move, so this waits in the queue | yes, always |
Over MCP only
The same grant behind them, and no HTTP twin yet.
- orla_list_budgets, orla_set_budget
- Each budget with what was spent against it; change one budget's amount, with the budgets permission.
- orla_find_service
- Search three catalogues for a service the agent could pay, with host, price, networks and source. It opens nothing: a host is paid only once the owner lists it.
- orla_net_worth
- What the space is worth right now in its base currency, naming whatever was left out of the sum.
- orla_list_reports, orla_read_report
- The assistant's reports, the list first, then one by name. Addresses come masked unless the grant says otherwise, and an agent limited to some accounts sees only their figures.
- orla_split_balances, orla_list_shared_expenses, orla_add_shared_expense
- Who owes whom in a shared space, the expenses behind it, and a new one divided between the people.
- Five risk reads
- orla_risk_alerts, orla_risk_counterparties, orla_risk_check, orla_risk_trace and orla_risk_case: open findings over a business space's payouts, what is known about a counterparty before paying it, and the hops the money took.
- orla_risk_resolve
- A person's verdict on a finding; a bot connection gets it with its own consent, a personal one never does.
What the key cannot buy
What the API refuses to do
Each of these is a rule in the code, not a default someone can change.
Refused
- Releasing an approved payment
- Never, by any agent.
- Widening its own grant
- Only as a proposal a person accepts.
- Paying an address it read in a document
- Refused: a send goes only to an address the space trusts.
- Reaching a space you did not name
- Refused, and nothing about that space is confirmed.
- Seeing card numbers or IBANs
- Masked unless the grant says unmasked.
- Its own card number
- Not handed over unless the owner armed that card for it, and then once per arming.
- A host that is not a hostname
- A request to open a service is refused before it reaches the owner's queue unless it is a plain hostname; an IP, a wildcard, another port or a login in the address never gets there.
- A fresh key
- Starts observing: every write it tries becomes a proposal.
Practical
- Rate limits
- 120 calls a minute per agent, reads included.
- Idempotency
- An Idempotency-Key header on every write, so a retry is safe.
- Errors
- A code you can branch on, not prose.
- Expiry
- A grant can carry a date.
- Revocation
- Takes effect on the next call.
- The trail
- Every call is in the audit log with the agent's name on it.
Set it up
Your own books, in the client you already use
No key and no paid plan: you tick which spaces the client may reach.
- Claude →
- A custom connector in Settings, nothing to install.
- Claude Code →
- One command in the terminal, then /mcp to sign in.
- Cursor →
- One entry in mcp.json, globally or in the repository.
- VS Code →
- One entry under servers, or one code --add-mcp line.
- Zed →
- One entry under context_servers in settings.json.
- Windsurf →
- One entry with serverUrl in the Codeium config.
- Terminal →
- The CLI itself, and a stdio bridge for clients without HTTP.
- Any agent →
- A skill file the agent reads itself: one install, every client.
See it on your own books
Thirty minutes: we connect an account, drop a real bill in, and close a month together.