Concepts
How Mintbot works under the hood.
Agent Wallets
Each agent wallet is an isolated account with its own API key, balance, and optional spending cap. Wallets are identified by a wallet_id (e.g., w_a1b2c3d4) and authenticated via a mb_live_... API key.
API keys are hashed with bcrypt before storage — the raw key is shown exactly once at creation and cannot be recovered. The api_key_prefix (first 15 characters) is stored for display purposes so you can identify which key belongs to which wallet.
Wallets can have an optional budget_limit_sats — a maximum spending cap enforced per payment. This is useful for restricting how much an automated agent can spend in total.
Internal Payments
When you pay another Mintbot wallet using to_wallet, no Lightning routing occurs. The transfer is an atomic database transaction — the sender's balance decrements and the recipient's increments in a single SQL commit.
This means internal payments are:
- Instant — no Lightning propagation delay
- Zero fee — no routing fees, no miner fees
- Atomic — either both balances update or neither does
- Permanent — recorded in the transaction log with a unique
tx_id
Internal payments are the primary mechanism for agent-to-agent commerce where both agents are registered on the same Mintbot instance.
What is Cashu?
Cashu is an ecash protocol built on top of the Lightning Network. It uses blind signatures (Chaumian ecash) to issue bearer tokens that represent real satoshis held by a mint.
In Mintbot, Cashu proofs are stored in the database on behalf of each wallet. When you fund via Lightning, the server mints Cashu proofs and stores them. When you pay a Lightning invoice or withdraw, those proofs are melted (redeemed) at the mint.
Cashu tokens (the cashuA... strings returned by /agent/withdraw) are:
- Portable — any Cashu-compatible wallet can redeem them
- Offline-redeemable — no Lightning node needed by the recipient
- Bearer tokens — whoever holds the token can spend it
- No expiry — valid until the mint goes offline
Lightning Network
The Lightning Network is a payment protocol built on Bitcoin that enables near-instant, low-fee transactions. Mintbot uses Lightning as its entry and exit ramp.
Funding (Lightning In): You request a BOLT11 invoice. When you pay it from any Lightning wallet, the Mintbot mint confirms payment and issues Cashu proofs to your wallet. The confirmation is handled by the mint polling service — no callback needed.
Sending (Lightning Out): When you pay a BOLT11 invoice or Lightning address, Mintbot performs a "melt" — it redeems your Cashu proofs at the mint, which pays the Lightning invoice via its own Lightning node. Routing fees are deducted from your balance.
Lightning Address
A Lightning address looks like an email address (e.g., user@getalby.com) and maps to a Lightning payment endpoint via LNURL-pay.
Paying via Lightning Address
When you call POST /agent/pay with to_address, Mintbot:
- Fetches
https://domain/.well-known/lnurlp/userto get the LNURL-pay metadata - Verifies the requested amount is within the min/max sendable range
- Requests an invoice from the callback URL
- Pays the invoice via Cashu melt
This means you can pay any Lightning address holder worldwide — wallets, exchanges, services — with a single API call and no Lightning node of your own.
Your Agent's Lightning Address
When a wallet is created with an agent_name, Mintbot automatically registers a Lightning address for that agent: {agent_name}@mintbot.cash. This address is returned as the lightning_address field in the create response.
This means every agent wallet is also receivable from anywhere on the Lightning network — no extra setup required. Any Lightning wallet, exchange, or service can send sats directly to your agent using its address.
Address sanitization
The agent name is sanitized before registration: converted to lowercase with special characters removed. If the resulting address is already taken, a 4-character hex suffix is appended automatically (e.g. my-agent-78b3@mintbot.cash).
How it resolves
The address resolves via the LNURL-pay protocol. When a sender queries my-agent@mintbot.cash, Mintbot's LNURL endpoint returns a payable Lightning invoice. The sender pays the invoice and the sats are credited to the agent wallet automatically — from any Lightning wallet, worldwide.
agent_name is provided at creation, lightning_address will be null and the wallet has no receivable Lightning address. LN address registration is non-fatal — the wallet is created successfully even if registration fails.
What is L402?
L402 (originally LSAT) is a protocol that combines HTTP 402 Payment Required responses with Lightning payments. It enables pay-per-request API monetization for machine clients.
In the Mintbot implementation, the L402 Proxy works differently from the original spec — instead of macaroon tokens, it uses Mintbot API keys directly. This simplifies the client implementation significantly:
- Client sends a request to
/l402/proxy/:slug/*withAuthorization: Bearer mb_live_... - The proxy verifies the API key and deducts the endpoint price from the wallet
- The request is forwarded to the upstream URL
- The upstream response is returned to the client
If the wallet has insufficient balance, the proxy returns 402 Payment Required. The client can then fund the wallet via Lightning and retry.
Agent-to-Agent Payments
Mintbot is designed for autonomous economic coordination between AI agents. The typical pattern is:
- Orchestrator agent has a funded wallet and delegates tasks to worker agents
- Worker agents have wallets with small balances or no balance
- When a worker completes a task, the orchestrator calls
POST /agent/paywith the worker'swallet_id - The worker can use its balance to pay other services, or withdraw as a Cashu token
Since internal payments have zero fees and instant settlement, agents can transact in very small amounts (even 1 sat) without economic friction.
Example: Translator Pipeline
from mintbot import AgentWallet
orchestrator = AgentWallet(api_key="mb_live_orchestrator...")
translator = AgentWallet(api_key="mb_live_translator...")
# Orchestrator assigns a translation task and pays upfront
result = orchestrator.pay(
to_wallet=translator._wallet_info.wallet_id,
amount=10,
memo="translate: 'Hello world' → Spanish",
)
# Worker processes the task and earns the payment
# (translator's balance now has 10 more sats)
print(translator.balance) # balance increased
Security Model
Key security properties of the Mintbot agent API:
- API key hashing: Keys are hashed with bcrypt (cost 12) before storage. A compromised database does not expose usable keys.
- Rate limiting: Payment endpoints are rate-limited per wallet to prevent abuse.
- Budget controls: Optional
budget_limit_satscaps the maximum balance an agent can spend, limiting blast radius if a key is compromised. - Proof isolation: Cashu proofs are stored per-wallet. One wallet cannot access another wallet's proofs.
- Atomic operations: All balance mutations use database transactions with row-level locking to prevent race conditions and double-spends.