What Cartulary is, how an approval relates to money, every concept in the console, and the API.
Software agents are beginning to make payments. Cartulary applies a governance workflow and produces an internally verifiable record of what it decided: every payment an agent submits is decided before settlement, allow, hold, or refuse, against the agent's mandate and the organisation's signed policy, with the screening status receipted; live requests record not_screened while no engine is connected. Every step of every decision is an append-only, hash-chained receipt that can be recomputed by anyone holding it.
Humans sit exactly where they should: they sign the policy, they grant and revoke authority, they decide held payments, they investigate what cannot be dispositioned, and they pull the kill switch. The agents move fast inside the fence; the humans own the fence.
Cartulary never holds funds and never holds signing keys; it is the decision and evidence layer, not the custodian. An approval becomes a governed decision record, and where a rail exists an approval can lead to a test-value USDC transfer on Base Sepolia, receipted from intent through on-chain confirmation. Everything else ends at allowed, and live screening receipts record not_screened, because the screening engine is not built; its proposed implementation is described on the roadmap. Production settlement and the Canton adapter are not available yet.
The binding works in two gates. Gate one, before anything is prepared: may this action be attempted at all? Gate two, after the rail prepares the transaction and before your wallet or custodian signs it: is this prepared transaction exactly the one that was approved, with sender, receiver, instrument, amount, and an independently recomputed hash matching the approved intent? The signature stays with the key holder; Cartulary authorises and verifies. Where Cartulary relays the signed transaction, only the approved transaction is submitted, because Cartulary submits nothing else. Where the key holder broadcasts directly, as a browser wallet does, the same check becomes detective rather than preventive: the payment would settle and the receipt would record the difference. The distinction matters and we would rather state it than let a screen imply the stronger of the two. The first implementation is a narrow external-signing validator run against a local Canton network, using Canton's example Iou model: not a stablecoin settlement, not integrated into this application, and not run on DevNet, TestNet, or MainNet. It is described on the architecture page, and the mechanics are specified in the standard.



Simulated is the public showroom: a fictional treasury operation with real mechanics and one scripted incident, open to everyone. Live is yours: sign in, create your organisation, and everything you see is your own data. The two are separated at the database, and the switch is always top right.
An agent is software that spends under a named principal, with an operator of record and a key whose private half only you hold. One all-powerful agent is one key with all authority, which is the failure this product exists to prevent: separate agents keep mandates narrow, keep the kill switch's blast radius small, and make every payment attributable to a function.
There is no Connect Wallet button, and there is not meant to be one. An agent runs unattended, often for months, so its signing key belongs where that agent runs: a key file on disk while you are developing, and a key-management service, hardware security module, or signing quorum in production. The SDK reaches all of them through one interface of two methods, an address and a signature over a hash, and ships a conformance check that verifies a signer returns recoverable, correctly formed signatures for its own address before it touches a payment.
An agent's wallet address is bound to it once and cannot be rebound through the API, so a stolen API credential cannot rebind the agent to another wallet; rebinding is a governed action in the console. Compromise of the signing key itself is a separate failure mode, and that key controls the wallet it already holds. Cartulary never holds funds and never holds keys: it decides what may be attempted, verifies that the prepared transaction is the one that was approved, and records both afterwards in an integrity-checkable receipt chain. That record does not independently prove that the authority existed or that the policy was followed.
You can still watch this happen without writing code. The live rail walkthrough in the console lets a person connect a browser wallet, read the prepared transaction, sign it, and follow the payment to its settled receipt.
A mandate is one agent's permission to spend: instruments, per-payment and daily limits, expiry. Different agent-payment protocols carry their own authority objects, and this one model is designed to express each of them, keeping the native object beside the normalised form. The simulated environment shows that side by side; adapters that ingest these objects directly are not built yet:
The full mapping, including what each protocol does not supply, is in the standard. Revocation cancels scheduled spend under the authority at once.
The policy is the organisation's signed rulebook: limits, escalation threshold, screening behaviour, permitted instruments. A change is a new immutable version: drafted, compared field by field against the active version, backtested against your last 7 days of payments, then signed and activated. Every decision receipt names the exact version and rules hash that evaluated it. The engine enforces what the policy says: limits refuse, and payments above the escalation threshold are held for human approval.
A hold pauses the workflow before the transaction is submitted to a ledger, when screening returns a near match or when the payment crosses the escalation threshold. Nothing is submitted until someone releases it, blocks it and opens a reporting case (the record carries the authority, channel, and filing deadline; Cartulary does not file), or opens an investigation with requested evidence, an assignee, and its own deadline. Decided holds stay on the Hold Desk as the record. A hold cannot stop a transfer that never passed through Cartulary.
Suspending an agent freezes every mandate it holds in one action and cancels its scheduled spend; the API refuses a suspended agent's attempts with the rule on the receipt. Reinstatement restores the frozen mandates.
Every payment's receipt chain reads as operator (what happened), auditor (full payloads and hash linkage, recomputed at render), examiner (a formal attestation with an exportable bundle), and counterparty (its own leg plus every hash, so a partially disclosed chain still verifies by linkage). What verification proves, and what it cannot, is stated in the standard.
Invite colleagues by email as operator (drafts and acts), approver (signs), or auditor (reads everything, changes nothing). Roles are enforced in the actions. The invitation attaches when that email first signs in.
For test-value USDC on Base Sepolia, one SDK call drives the payment from decision through signing, submission, and confirmation. The agent holds an API key and a signing key; Cartulary holds the policy, builds the transaction, verifies the signature against the bound wallet, relays it, and receipts every step. No RPC endpoint, no gas logic, two dependencies.
import { Cartulary } from "cartulary";
const agent = new Cartulary({ apiKey: process.env.CARTULARY_KEY, agent: "procurement" });
const paid = await agent.pay({ to: "0x1F98431c8aD98523631AE4a59f267346ea31F984", amount: "1.50" });
console.log(paid.status, paid.txHash, paid.evidence);The first run generates a key at ./.cartulary, binds its address to the agent write-once, and prints funding instructions. Refusals throw with the rule that refused them; holds return and can be awaited while a human decides; every retry carries an idempotency key, so a repeated request replays the original decision rather than creating a second payment. Three recovery paths are automated and receipted: an expired template is reissued for the same payment, a stuck transaction is re-bid at the same nonce with only its fees raised, and a reorganisation appends an observation to the chain rather than rewriting it.
npm install cartulary. Source and a runnable example: github.com/prasants/cartulary/tree/main/sdk.
One endpoint decides a payment before settlement and returns a receipt chain recording what Cartulary says it decided, with disclosed linkage that can be independently recomputed. It runs against the simulated environment with the published test key below, and against your own organisation with a live key: sign in, set up the live loop in the console, and issue one.
curl -X POST https://www.cartulary.xyz/api/v1/decisions \
-H "Authorization: Bearer ck_test_bishopsgate" \
-H "Content-Type: application/json" \
-d '{
"amount": "1250.000000",
"currency": "USD",
"instrument": "usdc-base",
"agent": "procurement",
"counterparty": { "name": "Northgate Data Services Ltd" }
}'The response is the decision and its evidence:
{
"decision": "allow",
"reasons": ["Within mandate, policy passed, screening clear."],
"environment": "simulated",
"payment": { "external_ref": "API-482913", "state": "settled", ... },
"receipts": [
{ "seq": 1, "event_type": "initiated", "hash": "84387411..." },
{ "seq": 2, "event_type": "evaluated", "hash": "6aeefacf..." },
{ "seq": 3, "event_type": "screened", "hash": "c8d16a23..." },
{ "seq": 4, "event_type": "allowed", "hash": "6f89e04e..." },
{ "seq": 5, "event_type": "settled", "hash": "1f1f33d9..." }
],
"links": { "evidence": "https://cartulary.xyz/console/evidence/..." }
}| Decision | What happens |
|---|---|
| allow | Within mandate and policy. Simulated payments settle; live payments on usdc-base return a signing template, and the transaction settles on Base Sepolia once the agent's signature verifies against its bound wallet. |
| hold | A screening near match, or above the policy's escalation threshold. The payment stops and appears on the Hold Desk with a deadline. |
| refuse | The payment violates its mandate or policy and is never constructed. The attempt is receipted with the rule that refused it. |
Fields: amount is a fixed-point string with six decimals; currency must match the instrument (usdc-base, usdcx-canton, gbpd-pentland, eurc-ethereum); agent is one of your registered agents (simulated: treasury-rebalancer, procurement, compute-buyer); unknown counterparties are recorded unverified. Rate limited. The receipt schema is published in the standard's repository.