Commands: REST & MCP
Every action in Payvy is a command in a single registry. The registry is served two ways, identically:
- REST:
POST /api/commands/{name} - MCP:
POST /mcp(tools are generated from the registry)
There is no write path outside the registry: the web app is one more caller of the same commands, and a bypass would be invisible to agents — so it isn’t allowed by design.
Actors and keys
Section titled “Actors and keys”Create keys per actor:
cargo run -- key create --actor robert --kind person- Person keys carry the rights of the person they name, including person-only commands.
- Agent keys can prepare work: read and enter bills, file documents, signal events, propose workflows and payees. Person-only commands (approve, reject, release, void, accept/decline) refuse agent keys, and agents don’t see them in
tools/list.
People can also sign in to the web app with an emailed link (no passwords); a signed-in person acts with the same rights as their person key.
Confirmed commands
Section titled “Confirmed commands”Anything that moves money or destroys state is confirmed-tier: call once to preview (the real command runs and rolls back), then commit with the single-use token returned, bound to exactly the input you previewed. Changing the amount or destination invalidates the token. See Paying through your bank for bill.release as the worked example.
Idempotency and events
Section titled “Idempotency and events”Payment attempts carry a deterministic idempotency key the bank honours, so retries can’t pay twice. Every write returns the new state and appends an event in the same transaction; bill.created from an extraction, for example, records which fields a person corrected. Money is integer cents everywhere.
Example commands
Section titled “Example commands”| Command | Actor | Purpose |
|---|---|---|
document.list, document.get, document.extract |
agent or person | Inbox, inspection, model read |
bill.create, bill.release, bill.mark_paid |
create: any; release/mark_paid: person (confirmed) | Enter and pay bills |
email.new_address, email.address, email.list |
person creates | Inbound addresses |
bank.connect, bank.recipients |
person connects | Mercury setup |
vendor.propose_payee, vendor.accept_payee |
propose: any; accept: person | Who gets paid |
payment.list, payment.refresh |
any | Bank payment tracking |