Connect your agent
Two doors into the same rules: an HTTP API for your own code, and an MCP server for Claude, ChatGPT and anything else that speaks it. Both obey the grant you gave the agent: its permissions, its daily caps, its trusted addresses.
The key
Create an agent on the Agents screen in the app. The key is shown once and never again; it authenticates as the agent, not as you, and it can do only what the grant allows.
curl https://app.orla.finance/agent/me \
-H "Authorization: Bearer $ORLA_AGENT_KEY"Base URL: https://app.orla.finance. Every response is JSON. An agent may hold two live keys at a time, which is what a rotation needs: mint the new one, move the bot, revoke the old.
Writes need an idempotency key
Every call that changes anything requires an Idempotency-Key header. Reuse the same key when you retry and the first answer comes back verbatim, so a retried “book $4,000 to the contractor” is one payment rather than two. The same key with a different body is a conflict, not a replay.
curl -X POST https://app.orla.finance/agent/spaces/$SPACE/transactions \
-H "Authorization: Bearer $ORLA_AGENT_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"account_id":"…","amount":"-42.00","currency":"USD","payee":"Serper","occurred_on":"2026-08-10"}'Observation mode
A new agent starts observing: writes are queued as proposals for a person to accept, rather than applied. The response says so (applied: false with a proposal id), which is the shape to handle before you switch the agent to active.
MCP
Add https://app.orla.finance/mcp as a connector. The client sends the person to an Orla page that names it and asks which space, which role and which limits; approving there creates the agent. Nothing is copied by hand, and the same tools below are what the client sees.
Tools
| MCP tool | HTTP | What it does |
|---|---|---|
orla_whoami | GET /agent/me | Which spaces this key reaches, and what it may do in each. |
orla_list_accounts | GET /agent/spaces/{id}/accounts | Accounts the grant exposes. |
orla_list_categories | GET /agent/spaces/{id}/categories | The space's categories. |
orla_list_transactions | GET /agent/spaces/{id}/transactions | Ledger rows, newest first. |
orla_list_payments | GET /agent/spaces/{id}/payments | Payments and their state. |
orla_book_transaction | POST /agent/spaces/{id}/transactions | Write a ledger row. |
orla_amend_transaction | PATCH /agent/spaces/{id}/transactions/{tx} | Correct one. |
orla_propose_payment | POST /agent/spaces/{id}/payments | Propose a payment. Always needs a human signature: an agent never signs one. |
orla_propose_onchain_payment | POST /agent/spaces/{id}/chain-payments | Prepare an on-chain payment to a trusted address, for a person to sign. |
orla_card | GET /agent/spaces/{id}/card | The agent's own card and its fence. |
orla_card_reveal_link | POST /agent/spaces/{id}/card/reveal | Short-lived link to the card details. |
orla_wallet | GET /agent/spaces/{id}/wallet | The agent's float: addresses and balances. |
orla_wallet_transfer | POST /agent/spaces/{id}/wallet/transfers | Spend from the float. Inside policy it sends; outside it, the answer is a proposal for the owner. |
orla_pay_for_resource | POST /agent/spaces/{id}/x402 | Fetch a URL and pay its price if it asks for one (x402). |
What an agent can never do
- Sign a payment to a person. That signature is a human act, always.
- Send to an address the space does not trust. Over policy, it becomes a proposal.
- Spend past the daily cap on its grant, or the per-request ceiling on its wallet.
- Read data outside the spaces it was granted, or beyond what its owner can read.
Treat every response as untrusted input to your model: it carries other people’s text (payee names, memos, invoice lines), and a tool result is data, not instructions.