Financial control plane
Kordio holds the rules and the record for money your software moves. Every action asks permission before it happens, and lands as a balanced posting after. Your rails move the money. Kordio holds none of it.

Non-custodial
No funds, no accounts, none of your credentials. Kordio cannot move money on its own.
Before the fact
Policy answers in the same request. No queue to poll, no callback to wait on.
After the fact
Balanced double-entry postings on an append-only journal. Corrections are reversals.
Verifiable
Allowed decisions come back signed. Your executor checks the signature offline.
How it works
Where a workspace has the ledger enabled, decisions are mirrored as balanced postings, so what was permitted and what posted sit in one history.
Kordio Control

Budget reserved, decision cosigned, trace id written.
Reservation kept, an approver notified. Nothing spent.
Nothing reserved, nothing signed, and the rule is named.
Two endpoints. That is the integration.
const decision = await kordio.authorize({
action: "refund.issue",
resource: "order_88213",
amount: 240_00,
currency: "EUR",
}, { idempotencyKey: "refund_88213" });
if (decision.outcome === "allowed") {
await rail.refund(order, decision.cosignature);
}Caps, rolling windows, allowlists, approval thresholds and session budgets, applied across every action type together, so a paid tool call and a payment draw down the same headroom.
Cosigning
Every allowed decision returns a compact signature over the agent, the session, the action, the resource, the amount and the currency, and it expires in minutes. Whoever executes verifies it against a public key set at /.well-known/jwks.json.
No call back to us. No shared secret. No SDK. It is ES256, so any standard JWT library checks it in any language: a payment provider, a tool call, an internal service, a third-party rail. The artifact does not care which.
import { jwtVerify, createRemoteJWKSet } from 'jose'
const jwks = createRemoteJWKSet(
new URL('/.well-known/jwks.json', KORDIO_API_URL)
)
const { payload } = await jwtVerify(cosignature, jwks)
if (payload.cost_cents !== invoice.amountCents) {
throw new Error('Authorization does not match the invoice')
}Cryptography proves we authorized the action. It cannot prove the action has not already happened, soPOST /v1/cosign/verify resolves the intent and refuses one that already settled. An authorization is good for a single execution.
Kordio Ledger

Post the same idempotency key twice and the second write returns the first result rather than paying anyone again. Multi-asset, so fiat, stablecoins and crypto sit in the same books. Live today, and plenty of the teams using it never touch an agent.
See what the ledger does, or the honest version of the decision in build versus buy.
For finance and operations

Intent dashboards list every action and payment intent, show what is waiting on a human, and let someone resolve it without opening a terminal.
The boundary

Where teams start
The alternatives, argued
Pricing
The real policy engine against test-mode agents, with no time limit and no card. 10 agents, 25k action authorizations, 1k payment authorizations, 5 teammates. There is deliberately no free live allowance: live money needs a card.
Start in test mode →The first live tier. One fleet of agents moving real money under policy you wrote.
Where an agent operation lands once the fleet is doing work you would miss if it stopped.
Seven figures of authorized spend a month, priced at the thinnest rate on the ladder.
Custom volume, custom limits, and a contract. Talk to us about what your agents need to be allowed to do.
Every number here comes from the same catalogue the product bills against. The full picture is on thepricing page.
FAQ
Kordio holds the rules and the record for money your software moves. Kordio Control decides whether an action is allowed before it happens, and Kordio Ledger keeps balanced double-entry books for what did happen. The rails move the money.
No. Kordio is a required signer, never a custodian. It holds no funds, no accounts and none of your credentials. Your rails keep the money, which is why we price on authorized volume rather than taking a cut of a payment we never touch.
No, and this is the most common misunderstanding. Anything non-human that starts a money movement has the same problem: a refund service, a payout run, a batch job, an ops tool. Agents make it louder and faster, they did not invent it.
An allowed decision comes back signed, expiring in minutes. Your executor verifies it offline against a public key set. Once the executor requires a signature, a caller that skipped the check has nothing to present. A control layer only binds the paths you route through it, and we say so plainly.
Where a workspace has the ledger enabled, decisions are mirrored as balanced postings, so what was permitted and what posted sit in one history. The projection never sits in the authorization path, so the books can never slow a decision down.
Kordio Control fails closed: if we cannot answer, nothing is authorized and nothing is signed. A control layer that fails open is not a control layer. Decide that failure mode deliberately rather than discovering it during an incident.
Kordio Control is metered on live authorized dollars a month, never on a count of API calls or decisions, and a denial is not billed. The sandbox is test mode with no card and no time limit, running the same engine as live, and there is deliberately no free live allowance. Kordio Ledger has its own plans. Every number is published on the pricing page and there is no call to read them.
Sign up at app.kordio.io and get sandbox keys in under five minutes, no card. Test and live share the same API surface with separate keys.
No card, and the same engine as live mode. Post a transaction that does not balance and watch it get refused. Write a ceiling and watch an action get denied by name. Ten minutes is enough to know whether this fits.