From zero to policy-enforced agent card in 10 minutes.
This guide walks you through provisioning your first BotWallet virtual card, configuring spending policy, and wiring it into an AI agent — with a full audit trail from the first transaction.
- 01
Secure Your Workspace
Open your Admin Console at /admin. You'll be prompted for your
ADMIN_PASSWORD. Once authenticated, you have access to three panels: Provision Virtual Card, Live Transactions, and Policy Editor.NOTEYour admin session expires after 8 hours. The authentication token is stored as an
httpOnlycookie — it is invisible to JavaScript and safe from XSS. You will be redirected to the login screen automatically when it expires.PRO TIPSet a strong, random
ADMIN_PASSWORDbefore inviting team members. Generate one with:openssl rand -hex 32. Rotate it immediately if you suspect it has been compromised — all existing sessions invalidate instantly. - 02
Define Your Safety Switch
Every BotWallet card is governed by three enforceable rules. Configure them in the Policy Editor or via the Admin API:
Daily LimitMaximum total spend per UTC calendar day. Resets at midnight UTC. Running total is tracked across all authorizations.Merchant AllowlistComma-separated descriptor substrings. Case-insensitive match. "openai" matches "OPENAI * API", "OPENAI CHATGPT", etc.Currency RulesISO 4217 codes the card may be charged in. Default: USD only. Add "EUR" to allow Euro-denominated charges.Or update programmatically via the Admin API:
typescript// Update a card's daily limit via the Admin API // (or use the Policy Editor in /admin) await fetch('/api/admin/policy', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ card_token: 'card_mock_abc123', daily_limit_dollars: 100, // $100.00/day cap }), }) // Response // { "ok": true, "updated": { "card_token": "card_mock_abc123", "daily_limit": 10000 } }NOTESpending limits are enforced at the Lithic network level — not in application code. An agent cannot bypass them by batching smaller transactions. The running UTC-day total is computed from all approved records in the
transactionstable before each authorization decision.PRO TIPAlways start with a
$1.00daily limit when integrating a new agent. Confirm the correct merchants are being approved and declined by reviewing the audit log, then scale the limit up incrementally. - 03
Provision Your First Agent Card
In the Admin Console, fill in Agent Name and Daily Limit, then click Provision Card. The API response confirms the card is active with its safety switch engaged:
json · 201 Created{ "card_token": "card_mock_9f2a1b3cde4f5a6b", "agent_name": "research-agent-v1", "daily_limit_usd": 10, "status": "ACTIVE", "safety_switch": true, "provider": "mock", "created_at": "2026-03-07T13:00:00.000Z" }NOTEThe
safety_switch: truefield is your confirmation that the policy engine is active. Every authorization attempt against thiscard_tokenwill be evaluated against your rules before any charge clears — including the very first one.PRO TIPTreat the
card_tokenlike an API key. Store it in your agent's secure environment config (e.g. a secret manager, not hardcoded). One card token per agent makes it trivial to pause a specific agent without disrupting others. - 04
Integrate via SDK
Provision cards programmatically from your deployment pipeline or agent bootstrap code. Once a card is issued, BotWallet enforces policy at the Lithic network level — your agent code requires zero limit-checking logic.
Node.js / TypeScript
typescript// Node.js / TypeScript — native fetch (Node 18+) const BACKEND = 'https://botwallet-backend-production.up.railway.app' const res = await fetch(`${BACKEND}/api/cards/create`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ agent_name: 'research-agent-v1', daily_limit_dollars: 10, // Start low — scale after audit review }), }) const card = await res.json() // { // card_token: "card_mock_9f2a1b3c...", // agent_name: "research-agent-v1", // daily_limit_usd: 10, // status: "ACTIVE", // safety_switch: true, ← policy engine is live // provider: "mock", // created_at: "2026-03-07T13:00:00.000Z" // } console.log(`Card issued: ${card.card_token}`) console.log(`Safety switch: ${card.safety_switch}`) // true // Store this token in your agent's secure environment. // Every charge against it is evaluated by BotWallet in real time. process.env.AGENT_CARD_TOKEN = card.card_tokenPython
python# Python — requests library # pip install requests import requests BACKEND = "https://botwallet-backend-production.up.railway.app" response = requests.post( f"{BACKEND}/api/cards/create", json={ "agent_name": "research-agent-v1", "daily_limit_dollars": 10, # Start low — scale after audit review }, ) card = response.json() # { # "card_token": "card_mock_9f2a1b3c...", # "agent_name": "research-agent-v1", # "daily_limit_usd": 10, # "status": "ACTIVE", # "safety_switch": True, <- policy engine is live # "provider": "mock", # "created_at": "2026-03-07T13:00:00.000Z" # } print(f"Card issued: {card['card_token']}") print(f"Safety switch: {card['safety_switch']}") # True # Every charge against this card_token is evaluated by BotWallet # in real time — no agent-side limit checking required. card_token = card["card_token"]Claude Tool-Use Integration
python# Wiring BotWallet into a Claude tool-use agent # pip install anthropic requests import anthropic import requests client = anthropic.Anthropic() BACKEND = "https://botwallet-backend-production.up.railway.app" # 1. Provision a card for this agent session card = requests.post(f"{BACKEND}/api/cards/create", json={ "agent_name": "claude-researcher", "daily_limit_dollars": 25, }).json() CARD_TOKEN = card["card_token"] # 2. Define spend-related tools tools = [ { "name": "purchase_api_credits", "description": ( "Purchase credits from an AI API provider. " "BotWallet enforces the $25/day policy automatically." ), "input_schema": { "type": "object", "properties": { "provider": { "type": "string", "description": "e.g. OpenAI, Anthropic" }, "amount_usd": { "type": "number", "description": "Amount in USD" }, }, "required": ["provider", "amount_usd"], }, } ] # 3. Run the agent — BotWallet intercepts every spend at the network level response = client.messages.create( model="claude-opus-4-6", max_tokens=1024, tools=tools, messages=[{ "role": "user", "content": "Purchase $20 of OpenAI API credits for the pipeline.", }], ) # If the agent tries to spend more than $25 today, BotWallet # declines at the Lithic network layer — before any charge posts.NOTEBotWallet intercepts every authorization at the Lithic network layer — before any charge posts to the card. Your agent code does not need to track spend, call BotWallet before each purchase, or implement retry logic for declines. Policy enforcement is entirely transparent to the agent.
PRO TIPIn production, replace
provider: "mock"with a live Lithic-backed provider by settingLITHIC_API_KEYandLITHIC_WEBHOOK_SECRETin your Railway environment. The card issuance interface is provider-agnostic — no code changes required. - 05
Audit & Explain
Every authorization — approved or declined — produces a structured audit record visible in /admin → Live Transactions. Click JSON on any row to expand the full record including the raw Lithic payload and the exact rule that fired.
json// Example: DECLINE audit record (visible in /admin → Live Transactions → JSON) { "id": "txn_01HXYZ...", "token": "asa_01HABC...", "card_token": "card_mock_9f2a1b3c", "merchant": "OPENAI * API", "amount": 1500, // $15.00 in cents "currency": "USD", "decision": "DECLINE", "rule_id": "RULE_DAILY_LIMIT", // ← the exact rule that fired "reason": "Spend would exceed daily limit of $10.00 USD.", "raw_payload": { ... }, // Full Lithic ASA request "created_at": "2026-03-07T14:22:01Z" }Rule ID Reference
RULE_ALL_PASSEDAPPROVEAll policy checks passed.RULE_DAILY_LIMITDECLINEAmount would exceed the daily spending cap.RULE_MERCHANT_NOT_ALLOWEDDECLINEMerchant descriptor not in the allowlist.RULE_CURRENCY_MISMATCHDECLINECurrency not in the permitted currencies list.RULE_NO_POLICYDECLINENo policy found for this card_token.NOTERULE_ALL_PASSEDmeans every policy check was satisfied and the transaction was approved. All other rule IDs identify the specific check that triggered a decline — use them to tune your merchant allowlist or adjust daily limits without guesswork.PRO TIPSet up a webhook or poll
GET /api/admin/transactionsfrom your observability stack to alert on unexpectedRULE_NO_POLICYdeclines — they indicate a card_token reached the network without a corresponding policy row, which should never happen in a healthy deployment.
Start Building in Sandbox
Your sandbox environment is live. Provision a card, run a transaction, and watch the audit log explain every decision in real time.