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 toolHTTPWhat it does
orla_whoamiGET /agent/meWhich spaces this key reaches, and what it may do in each.
orla_list_accountsGET /agent/spaces/{id}/accountsAccounts the grant exposes.
orla_list_categoriesGET /agent/spaces/{id}/categoriesThe space's categories.
orla_list_transactionsGET /agent/spaces/{id}/transactionsLedger rows, newest first.
orla_list_paymentsGET /agent/spaces/{id}/paymentsPayments and their state.
orla_book_transactionPOST /agent/spaces/{id}/transactionsWrite a ledger row.
orla_amend_transactionPATCH /agent/spaces/{id}/transactions/{tx}Correct one.
orla_propose_paymentPOST /agent/spaces/{id}/paymentsPropose a payment. Always needs a human signature: an agent never signs one.
orla_propose_onchain_paymentPOST /agent/spaces/{id}/chain-paymentsPrepare an on-chain payment to a trusted address, for a person to sign.
orla_cardGET /agent/spaces/{id}/cardThe agent's own card and its fence.
orla_card_reveal_linkPOST /agent/spaces/{id}/card/revealShort-lived link to the card details.
orla_walletGET /agent/spaces/{id}/walletThe agent's float: addresses and balances.
orla_wallet_transferPOST /agent/spaces/{id}/wallet/transfersSpend from the float. Inside policy it sends; outside it, the answer is a proposal for the owner.
orla_pay_for_resourcePOST /agent/spaces/{id}/x402Fetch 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.