Skip to main content
Every request needs an API key, and your tenant is resolved from the key — never from a header or body field you control. Keys are scoped (ledger:read, withdrawal:create, treasury:spend, …); a 403 means the key is valid but lacks the scope the operation requires, not that something is broken.

Bearer keys

The simple form, and the right default for anything read-only:
kp_test_… keys run against testnet; kp_live_… against mainnet. They are otherwise identical — same endpoints, same shapes — so integrate against test and swap the key when you’re ready. See Networks for how the two stay isolated end to end.
A bearer key is a bearer credential: whoever holds it can act as your tenant. Keep it server-side only, and prefer signed requests (below) for anything that moves money, so a leaked key alone is not enough.

Signed requests

For withdrawals, treasury spends, and anything else that moves funds, sign the request instead of sending the secret. The signature covers:
Ed25519-sign that string with your key’s private half, then send: No secret travels on the wire, and a captured request cannot be replayed (the nonce) or altered (the signature covers the body’s hash) or reused past its window (the timestamp).
A minimal, zero-dependency signer — copy it straight into your backend rather than depending on a KeyPair SDK for something this small:

Choosing between them

Bearer for reads, signed for writes that move money — everything else (creating a customer, opening an account) is safe either way, since nothing there can move funds on its own.