Evenbead docs

Quickstart

This walks through a first agent integration: a key with the right scopes, a read, a dry run, a write that posts, and one that waits for approval. Every example uses curl against https://api.evenbead.com; the same operations are MCP tools (see MCP setup).

1. Get a key

A company's owner signs in to the web app at https://app.evenbead.com with their owner key, then creates people and agents in Settings. Through the API, an owner (or any person with the admin scope) registers an agent and mints its key:

export EVENBEAD_KEY="eb_..."        # the owner's key; keep it out of shell history and source control

curl -s https://api.evenbead.com/v1/agents \
  -H "Authorization: Bearer $EVENBEAD_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: register-categorizer-001" \
  -d '{"name":"categorizer","scopes":["read","propose"],"posting_threshold_cents":50000}'

curl -s https://api.evenbead.com/v1/keys \
  -H "Authorization: Bearer $EVENBEAD_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: categorizer-key-001" \
  -d '{"principal_type":"agent","agent_id":"<agent id>","scopes":["read","propose"],"expires_in_days":30}'

The response holds the key once. Only its hash is stored, so a lost key is replaced, not recovered.

2. Scopes

ScopeAllows
readEvery read: accounts, reports, documents, the audit log, exports
proposeWrites that go through policy: journal entries, documents, bank categorization
approveApproving or rejecting proposals (never your own), finishing reconciliations
adminCompany setup: accounts, periods, people, agents, keys

Give an agent the least it needs. Agents should almost never hold admin. An agent's effective scopes are the key's scopes limited by the agent's own.

3. Read something

curl -s https://api.evenbead.com/v1/me -H "Authorization: Bearer $AGENT_KEY"
curl -s "https://api.evenbead.com/v1/accounts" -H "Authorization: Bearer $AGENT_KEY"

/v1/me shows who you are, your scopes, your company and when your key expires.

4. Dry run, then write

Any write accepts "dry_run": true. Nothing is written and no idempotency key is needed:

curl -s https://api.evenbead.com/v1/journal-entries/propose \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H "X-Agent-Model: your-model-name-and-version" \
  -H "Content-Type: application/json" \
  -d '{"entry_date":"2026-09-03","memo":"Office supplies","dry_run":true,
       "lines":[{"account":"6300","debit_cents":4299},{"account":"1000","credit_cents":4299}]}'

The answer has outcome: "dry_run", would (post, queue_for_approval or be_refused), the policy verdict with its reasons, the period, the affected balances and any validation errors. Drop dry_run and add an Idempotency-Key to write it:

curl -s https://api.evenbead.com/v1/journal-entries/propose \
  -H "Authorization: Bearer $AGENT_KEY" \
  -H "X-Agent-Model: your-model-name-and-version" \
  -H "X-Agent-Run-Id: run-2026-09-03-a" \
  -H "Idempotency-Key: supplies-2026-09-03-4299" \
  -H "Content-Type: application/json" \
  -d '{"entry_date":"2026-09-03","memo":"Office supplies",
       "lines":[{"account":"6300","debit_cents":4299},{"account":"1000","credit_cents":4299}]}'
  • 201 with outcome: "posted": within policy, posted.
  • 202 with outcome: "pending_approval": a proposal is waiting for a person.

5. Idempotency keys

  • Required on every write except a dry run: 8 to 200 characters of A-Z a-z 0-9 . _ : -.
  • Same key and same request: the original response comes back with the header Idempotency-Replayed: true. Retry freely after a timeout.
  • Same key with a different request: 409 idempotency_conflict.
  • Keys are kept per company for at least 30 days. Derive them from your own data (a bank line id, an invoice number) so a crashed run can safely start over.

Writes that set a value (for example a plan or a setting) say so in the reference; they need no key because repeating them leaves the same state.

6. Proposals and approval thresholds

Each agent has a posting_threshold_cents. An agent write becomes a proposal instead of a posting when any of these apply:

ReasonWhen
over_thresholdThe entry total is above the agent's threshold
sensitive_accountIt touches an equity account
period_soft_lockedThe period is soft-locked (only a person may post, with a reason)
low_confidenceThe agent sent confidence below 0.7
new_counterpartyAn invoice, bill or payment for a customer or vendor with no posted documents yet

People see proposals in the web app's approval queue. Through the API:

curl -s "https://api.evenbead.com/v1/proposals?status=pending" -H "Authorization: Bearer $APPROVER_KEY"
curl -s https://api.evenbead.com/v1/proposals/<id>/approve -X POST \
  -H "Authorization: Bearer $APPROVER_KEY" -H "Idempotency-Key: approve-<id>" -H "Content-Type: application/json" -d '{}'

Rejecting needs a reason, which stays on the record. Nobody approves their own proposal. Hard-locked periods refuse every write, in the database.

7. Rate limits

Requests are limited per key, per company for agents, and per address. Plan limits: Solo 60, Business 300, Advanced 1,200 requests per minute. A key can carry its own lower budget (rate_limit_rpm). Over the limit you get 429 with error.type: "rate_limited" and a Retry-After header in seconds: wait that long, then retry with the same idempotency key.

8. Key expiry and rotation

  • People's keys last 365 days; agents' keys 30 days by default and at most 90.
  • /v1/me reports key.expires_at. Rotate before then:
curl -s https://api.evenbead.com/v1/keys/<key id>/rotate -X POST \
  -H "Authorization: Bearer $AGENT_KEY" -H "Idempotency-Key: rotate-2026-10" \
  -H "Content-Type: application/json" -d '{"overlap_seconds":3600}'

The new secret is returned once. The old key keeps working for the overlap window (default 24 hours, at most 7 days), then stops. An agent can rotate its own key; admins rotate any key in the company. Revoking an agent stops all of its keys on the next request.

Next