Developer Reference
Documentation
API reference for the Agentic Bank protocol. Read endpoints (explorer, status, history, rates) are public; borrowing endpoints (loan request, credit-line draw) require an API key. A2A uses agent signatures.
Quickstart - your agent's first loan in ~15 minutes
The full cycle: register an on-chain identity, borrow 5 USDC, repay it, and walk away with the thing that actually matters - verifiable on-chain credit history your agent can present to any lender that speaks ERC-8004.
1 · Wallet
An agentic wallet (Coinbase CDP recommended) with a few cents of ETH on Base for gas.
2 · Passport
A one-time ERC-8004 register() from the agent's own wallet - snippets on the Register page.
3 · Pilot API key
REST borrowing uses an API key during the pilot - ping @RSoft-Agentic-Bank to get one. A2A and MCP need no key.
# pip install cdp-sdk requests
# Env: CDP_API_KEY_ID / CDP_API_KEY_SECRET / CDP_WALLET_SECRET (your agent's
# CDP Server Wallet) + BANK_API_KEY (pilot key) + AGENT_WALLET (0x…)
import asyncio, os, time, uuid, requests
from cdp import CdpClient
from cdp.openapi_client.models.eip712_domain import EIP712Domain
from cdp.evm_transaction_types import TransactionRequestEIP1559
BANK = "https://rsoft-agentic-bank.com/api/v1"
KEY = {"X-API-Key": os.environ["BANK_API_KEY"]}
WALLET = os.environ["AGENT_WALLET"]
USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" # Base mainnet
VERIFYING = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432" # EIP-712 domain
async def main():
async with CdpClient(api_key_id=os.environ["CDP_API_KEY_ID"],
api_key_secret=os.environ["CDP_API_KEY_SECRET"],
wallet_secret=os.environ["CDP_WALLET_SECRET"]) as cdp:
# 1) Sign the loan terms (EIP-712 LoanRequest) with the agent's wallet
amount, nonce, deadline = 5.0, str(uuid.uuid4()), int(time.time()) + 3600
domain = EIP712Domain(name="RSoft Agentic Bank", version="1",
chain_id=8453, verifying_contract=VERIFYING)
# NOTE: CDP requires the EIP712Domain entry inside `types` (ethers/viem omit it)
types = {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"},
{"name": "verifyingContract", "type": "address"}],
"LoanRequest": [
{"name": "agentWallet", "type": "address"},
{"name": "loanAmountUsdc6", "type": "uint256"},
{"name": "nonce", "type": "string"},
{"name": "deadline", "type": "uint256"}]}
message = {"agentWallet": WALLET, "loanAmountUsdc6": int(amount * 1e6),
"nonce": nonce, "deadline": deadline}
sig = await cdp.evm.sign_typed_data(address=WALLET, domain=domain,
types=types, primary_type="LoanRequest",
message=message)
# 2) Request the loan — the 5-agent pipeline runs and disburses USDC
r = requests.post(f"{BANK}/loan/request", headers=KEY, json={
"agent_wallet": WALLET, "loan_amount": amount,
"nonce": nonce, "deadline": deadline, "signature": sig}).json()
request_id = r["request_id"]
# 3) Poll until disbursed (public endpoint, no key)
while requests.get(f"{BANK}/loan/status/{request_id}").json()["status"] \
not in ("disbursed", "rejected"):
time.sleep(5)
# 4) Repay: quote is public; pay the EXACT amount to the treasury
info = requests.get(f"{BANK}/loan/repay-info/{WALLET}").json()
base6 = int(round(info["repayment_amount"] * 1e6))
data = ("0xa9059cbb" + info["pay_to"][2:].zfill(64)
+ hex(base6)[2:].zfill(64)) # ERC-20 transfer
tx = await cdp.evm.send_transaction(address=WALLET, network="base",
transaction=TransactionRequestEIP1559(to=USDC, data=data, value=0))
# 5) Report it (optional — unreported payments are auto-detected ~10 min)
requests.post(f"{BANK}/loan/repay", headers=KEY,
json={"request_id": request_id, "tx_hash": tx})
print("Loan repaid - your agent now has on-chain credit history ✓")
asyncio.run(main())What your agent earned: a repaid loan recorded in the bank's books and a positive ERC-8004 reputation mark signed by the bank's wallet - portable, verifiable, and impossible to self-fabricate. Each repayment also climbs the credit ladder: $5 → $10 (1 repaid) → $25 (3) → $50 (6) → $100 (10). Check any agent's standing on the Reputation page.
Getting Started
What is Agentic Bank?
RSoft Agentic Bank is a decentralized lending protocol designed for AI agents. Autonomous agents can request USDC loans that are evaluated through an automated multi-agent pipeline - from identity verification to on-chain settlement.
Base URL
https://rsoft-agentic-bank.comAll endpoints are prefixed with /api/v1 except health checks.
Authentication
All read endpoints listed here are public - no API key or wallet connection required. Responses are JSON format with ISO 8601 timestamps.
How Agents Borrow
An agent can originate debt through four surfaces. REST, MCP and A2A are one-shot loans that share the same underwriting (caps, EIP-712 signature, replay-protected nonce); the credit line is revolving.
POST /api/v1/loan/requestDirect REST
Simplest path. Sign the loan terms and POST them. Pilot API key - see Quickstart.
Sign the EIP-712 LoanRequest (agentWallet, loanAmountUsdc6, nonce, deadline) and POST it. The bank runs the full 5-agent pipeline and disburses USDC to your wallet.
POST /api/v1/loan/request
X-API-Key: <bank_api_key>
{
"agent_wallet": "0x…",
"loan_amount": 5,
"nonce": "…",
"deadline": 1893456000,
"signature": "0x…" // EIP-712 LoanRequest
}tool: request_loanMCP tool
For autonomous agents that already use an MCP toolset. No API key needed.
Add the bank's MCP server to your agent's tools and call request_loan with your EIP-712 signature. Same underwriting and signature contract as REST - the MCP transports your signature, it never signs for you. See the MCP Server section for the full toolset.
// agent MCP config (Streamable HTTP)
mcpServers:
rsoft-bank:
url: https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp
// then your agent calls the tool
tool request_loan
args { "amount": 5, "agent_id": "0x…",
"signature": "0x…", "nonce": "…", "deadline": 1893456000 }bank.negotiateLoan → bank.executeLoanAgent-to-Agent
No API key needed - authenticated by your agent's signature. Start here if you have no key.
Negotiate terms with bank.negotiateLoan, sign the returned quote, then submit bank.executeLoan. Authenticated by your agent signature, not a shared key.
// 1) negotiate — get signable terms
POST /a2a
{ "method": "bank.negotiateLoan",
"params": { "agent_wallet": "0x…", "amount": 5 } }
// 2) sign the quote, then execute
POST /a2a
{ "method": "bank.executeLoan",
"params": { "signature": "0x…", … } }POST /credit-lines/request → /{id}/drawRevolving credit
For agents with recurring capital needs.
Open an approved credit line once, then draw against it repeatedly during the window instead of requesting a new loan each time. Repay to restore available credit.
// open a line (once)
POST /api/v1/credit-lines/request
{ "agent_id": "0x…", "requested_limit": 50 }
// draw against it (repeat, owner-signed)
POST /api/v1/credit-lines/{line_id}/draw
{ "amount": 5, "signature": "0x…" }Repaying a Loan
Repayment is a plain USDC transfer to the treasury for the exact owed amount (principal + full-term interest - fixed at origination, so the quote never changes). Two steps, and the second one is optional.
/api/v1/loan/repay-info/{wallet}1 · Get the repayment quote
Public - no API key.
Returns exactly what the agent owes and where to send it.
GET /api/v1/loan/repay-info/0xYourAgentWallet
{
"request_id": "req_…",
"principal": 5.0,
"interest": 0.102739,
"repayment_amount": 5.102739,
"currency": "USDC",
"pay_to": "0x274C…74C5a" // bank treasury (Base)
}Send a USDC transfer from the agent's own wallet (the sender is verified - nobody can claim your payment) to pay_to for the exact repayment_amount.
/api/v1/loan/repay2 · Report the payment (optional fast path)
API key · settles instantly.
The bank verifies the transaction on-chain (token, recipient, sender, amount) before crediting - a tx hash can settle exactly one debt, ever.
POST /api/v1/loan/repay
X-API-Key: <bank_api_key>
{
"request_id": "req_…",
"tx_hash": "0x…" // your USDC transfer
}Paying alone is enough
If your agent dies between the transfer and the report, nothing bad happens: the bank sweeps incoming treasury transfers every ~10 minutes and credits any exact-amount payment from a borrower automatically. An agent that paid can never be marked in default. Every verified repayment updates the agent's standing (credit ladder) and posts a positive, bank-signed ERC-8004 reputation mark - the portable credit history other lenders can verify.
MCP Server - the bank as a toolset
The bank speaks the Model Context Protocol. Point any MCP-capable agent (Claude, LangGraph, AgentKit, eliza, …) at the server below and the full credit cycle - creditworthiness, borrow, repay - becomes callable tools. Connecting and calling tools needs no API key; the loan request still requires your agent's own EIP-712 signature (the MCP transports it, it never signs for you). The complete cycle has been exercised end-to-end on Base mainnet with real USDC.
Endpoint (Streamable HTTP)
https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp
// agent MCP config
mcpServers:
rsoft-bank:
url: https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcpTools
get_creditworthiness(agent_id)Credit score, history and outstanding debt for any agent. Use it before requesting - it tells you what the ladder will allow.
request_loan(amount, agent_id, signature, nonce, deadline)Originates the loan. Sign the EIP-712 LoanRequest struct with the borrower wallet (see Quickstart step 1 - same struct, same domain) and pass signature + nonce + deadline. Unsigned requests are rejected. On approval the bank disburses USDC on Base to your wallet.
get_repayment_info(agent_id)What you owe (principal + interest) and the treasury address to pay. Returns the request_id you'll need to confirm.
confirm_repayment(request_id, tx_hash)After sending the exact USDC amount on-chain, report the tx hash. The bank verifies it on Base and marks the loan repaid. Forgot to call it? The treasury sweep auto-credits exact payments within ~10 minutes.
Full cycle via MCP (Python)
# pip install mcp
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
MCP_URL = "https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp"
async def main():
async with streamablehttp_client(MCP_URL) as (read, write, _):
async with ClientSession(read, write) as s:
await s.initialize()
# 1) Borrow - signature/nonce/deadline come from YOUR wallet
# signing the EIP-712 LoanRequest (see Quickstart step 1).
loan = await s.call_tool("request_loan", {
"amount": 5.0, "agent_id": "0xYourAgentWallet",
"signature": "0x…", "nonce": "…", "deadline": 1893456000,
})
# → { request_id, status: "initiated" } … disburses in seconds
# 2) Quote the debt
info = await s.call_tool("get_repayment_info",
{"agent_id": "0xYourAgentWallet"})
# → { request_id, repayment_amount, pay_to }
# 3) Send the EXACT repayment_amount in USDC to pay_to
# (your wallet stack does this - CDP, viem, web3.py, …)
# 4) Confirm
await s.call_tool("confirm_repayment", {
"request_id": "req_…", "tx_hash": "0x…",
})
# → { status: "repaid" } + positive ERC-8004 mark
asyncio.run(main())REST mirror - free reads & x402-paid intelligence
Agents without MCP support can use the same server over plain REST. Reads and repayment are free; underwriting intelligence is paid per request via x402 USDC micropayments - no account, no subscription, your agent pays the 402 challenge and gets the answer.
Free
GET /api/interest-rates current protocol rates
GET /api/creditworthiness/{agent} score + history for any agent
GET /api/repay-info/{agent} amount owed + treasury address
POST /api/repay report a repayment tx (money in is always free)Paid (x402, USDC on Base)
GET /paid/interest-rates $0.001 rates snapshot
GET /paid/reputation/{agent} $0.001 ERC-8004 ReputationRegistry snapshot
POST /paid/credit-check $0.01 Bank Analyst (Kelly-AMM) assessment
POST /paid/risk-score $0.05 Gatekeeper + Analyst + Treasury caps
POST /paid/kya-verify $0.10 signed JWT KYA token (verifiable offline)
POST /paid/validation-attest $1.00 bank-signed ERC-8004 validation attestation
POST /paid/loans $0.01 loan request (same signature contract)OpenClaw Skill - the bank as installable commands
Running an OpenClaw agent? The official bank skill packages the whole cycle - check rates and credit, sign the loan request, borrow, and repay - as ready-to-run commands. It signs with a Coinbase CDP wallet (the key never leaves Coinbase's enclave) and reads its config from a file you control, so an agent can switch wallets by pointing at a different file. A live OpenClaw agent has borrowed and repaid a real loan through it, end to end.
Install
# install the official skill (Base mainnet, real USDC)
npx clawhub install rsoft-agentic-bank
# install its dependencies (Coinbase CDP SDK), once
cd <skill-dir> && npm install
# skill page: https://clawhub.ai/rsoft-latam/skills/rsoft-agentic-bankConfigure your CDP wallet
# a file only you can read — keep it OUT of synced folders
mkdir -p ~/.rsoft && cat > ~/.rsoft/wallet.env <<'EOF'
CDP_API_KEY_ID=your-cdp-api-key-id
CDP_API_KEY_SECRET=your-cdp-api-key-secret
CDP_WALLET_SECRET=your-cdp-wallet-secret
AGENT_WALLET=0xYourWalletAddress
BANK_API_KEY=your-pilot-api-key # for loan origination
EOF
chmod 600 ~/.rsoft/wallet.env
export WALLET_CONFIG_PATH=~/.rsoft/wallet.env🔒 CDP credentials control every wallet in that CDP project - use a project dedicated to this agent, never one holding funds you don't want it to touch.
Borrow & repay
node bin/address.js # your wallet address (verifies CDP access)
node bin/request-loan.js 5 # sign + request a 5 USDC loan (one shot)
node bin/repay.js # quote, pay the exact amount, confirm — one shotReal USDC on Base mainnet. The bank only originates loans signed by the borrowing wallet - same security contract as every other door into the bank.
API Reference
Public GET endpoints for querying loan data, workflow status, and protocol information.
Loans
/api/v1/loan/status/{request_id}Get Loan Status
Retrieve the current status and details of a specific loan request.
Path Parameters
request_idstringThe unique loan request identifierResponse
{
"request_id": "req_abc123def456",
"status": "disbursed",
"agent_wallet": "0x1234...abcd",
"loan_amount": 1000,
"amount_approved": 1000,
"interest_rate": 0.085,
"term_days": 30,
"tx_hash": "0xabc...def",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:31:45Z"
}/api/v1/loan/workflow/{request_id}Get Workflow Steps
Retrieve the detailed execution status of each agent in the workflow pipeline. Includes timing, results, and errors for every step.
Path Parameters
request_idstringThe unique loan request identifierResponse
{
"request_id": "req_abc123def456",
"loan_status": "disbursed",
"workflow_status": "completed",
"total_duration_ms": 12450,
"current_step": null,
"steps": [
{
"step": "gatekeeper",
"step_order": 1,
"status": "completed",
"started_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:30:02Z",
"duration_ms": 2100,
"result": { ... },
"error": null
}
],
"created_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:31:45Z"
}/api/v1/loan/history/{wallet_address}Get Agent Loan History
Retrieve the loan history for a specific wallet address. Returns all past and current loan requests.
Path Parameters
wallet_addressstringThe agent's wallet addressQuery Parameters
limitintegerMax number of results (default: 10)Response
[
{
"request_id": "req_abc123def456",
"status": "repaid",
"agent_wallet": "0x1234...abcd",
"loan_amount": 1000,
"amount_approved": 1000,
"interest_rate": 0.085,
"term_days": 30,
"current_node": null,
"tx_hash": "0xabc...def",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-20T14:00:00Z"
}
]/api/v1/loan/explorerLoan Explorer
Public paginated endpoint to browse all protocol loans. Supports filtering by status. No authentication required.
Query Parameters
pageintegerPage number (default: 1)limitintegerItems per page (default: 20)statusstringFilter by loan statusResponse
{
"loans": [
{
"request_id": "req_abc123",
"agent_wallet": "0x1234...abcd",
"amount": 1000,
"currency": "USDC",
"status": "disbursed",
"interest_rate": 0.085,
"duration_days": 30,
"disbursement_tx_hash": "0xabc...def",
"created_at": "2025-01-15T10:30:00Z"
}
],
"total": 42,
"page": 1,
"limit": 20,
"total_pages": 3
}/api/v1/loan/active/{wallet_address}Get Active Loans
Retrieve all currently active loans for a wallet address. Includes outstanding balance summary.
Path Parameters
wallet_addressstringThe agent's wallet addressResponse
{
"active_loans": [
{
"request_id": "req_abc123def456",
"amount": 1000,
"interest_rate": 0.085,
"duration_days": 30,
"repayment_amount": 1085,
"status": "disbursed",
"disbursement_tx_hash": "0xabc...def",
"created_at": "2025-01-15T10:30:00Z"
}
],
"active_loans_count": 1,
"total_outstanding": 1085,
"wallet_address": "0x1234...abcd",
"agent_id": "agent-001"
}Agents & Rates
/api/v1/agents/{agent_id}/creditworthinessCheck Creditworthiness
Evaluate an agent's creditworthiness based on loan history and risk profile.
Path Parameters
agent_idstringThe unique agent identifierResponse
{
"agent_id": "agent-001",
"credit_score": 750,
"risk_tier": "low"
}/api/v1/interest-ratesInterest Rates
Retrieve current protocol interest rates. Rates are updated dynamically based on protocol utilization.
Response
{
"base_rate": 0.05,
"risk_tiers": {
"low": { "rate": "..." },
"medium": { "rate": "..." },
"high": { "rate": "..." }
},
"yield_strategies": {
"conservative": { "apy": "..." },
"balanced": { "apy": "..." },
"aggressive": { "apy": "..." },
"dynamic": { "apy": "..." }
},
"updated_at": "2025-01-15T00:00:00Z"
}Health Checks
/healthHealth Check
Returns the overall health status of the API and its dependencies.
Response
{
"status": "healthy"
}/health/readyReadiness Check
Kubernetes-style readiness probe. Returns 200 when the service is ready to accept traffic.
Response
{
"status": "ready"
}/health/liveLiveness Check
Kubernetes-style liveness probe. Returns 200 as long as the service process is running.
Response
{
"status": "alive"
}Status Codes & Loan States
Loan Statuses
HTTP Status Codes
Request succeeded
Invalid parameters or request body
Resource not found (invalid request_id, wallet, etc.)
Internal server error
Error Response Format
All error responses follow a consistent format with a detail field describing the error.
{
"detail": "Loan request not found: req_invalid_id"
}