API Reference
Full REST API for managing agent wallets programmatically. Everything the dashboard and CLI can do, the API can do.
Base URL
https://api.indiegent.comAuthentication
All protected endpoints require either a JWT token or an API key.
# JWT token (from login)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# API key (from dashboard or CLI)
X-API-Key: ig_live_abc123def456...Auth Endpoints
POST /auth/wallet
Authenticate with an Ethereum wallet using SIWE (Sign In With Ethereum).
POST /auth/wallet
Content-Type: application/json
{
"message": "indiegent.com wants you to sign in...",
"signature": "0xabc123..."
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": {
"id": "uuid",
"wallet_address": "0x..."
}
}POST /auth/register
Register with email and password.
POST /auth/register
Content-Type: application/json
{
"email": "dev@example.com",
"password": "secure-password-here"
}POST /auth/login
Log in with email and password.
POST /auth/login
Content-Type: application/json
{
"email": "dev@example.com",
"password": "secure-password-here"
}POST /auth/device
Start an OAuth device flow (used by the CLI).
POST /auth/device
→ { "device_code": "abc123", "user_code": "XYZW-1234", "verification_url": "..." }POST /auth/device/poll
Poll for CLI device authorization.
POST /auth/device/poll
{ "device_code": "abc123" }
→ { "token": "eyJ..." } // once approvedAgent Wallets
GET /agents
List all agent wallets with live USDC balances.
GET /agents
Authorization: Bearer eyJ...
→ {
"agents": [
{
"id": "uuid",
"name": "Research Bot",
"wallet_address": "0x7a3f...",
"usdc_balance": "25000000",
"spending_cap": 50000000,
"active": true,
"auto_topup_threshold": 5000000,
"auto_topup_amount": 20000000,
"created_at": 1711000000
}
]
}POST /agents
Create a new agent wallet. Generates a keypair and encrypts the private key.
POST /agents
{
"name": "Research Bot",
"spending_cap": 50000000
}
→ {
"id": "uuid",
"name": "Research Bot",
"wallet_address": "0x7a3f..."
}GET /agents/:id
Get a single agent with its live balance.
PUT /agents/:id
Update agent configuration (name, spending cap, auto-topup settings).
PUT /agents/:id
{
"name": "Research Bot v2",
"spending_cap": 100000000,
"auto_topup_threshold": 10000000,
"auto_topup_amount": 50000000,
"auto_topup_source": "0xYourWallet..."
}DELETE /agents/:id
Deactivate an agent. Automatically drains all USDC back to your wallet. The encrypted key remains exportable.
Agent Policy
GET /agents/:id/policy
Get the spending policy for an agent. Policies control which services the agent can access, daily/monthly budget limits, and per-call caps.
GET /agents/:id/policy
→ {
"policy": {
"spending_cap": 50000000,
"daily_limit": 10000000,
"monthly_limit": null,
"per_call_max": 1000000,
"allowed_services": ["exa", "openai", "anthropic"],
"blocked_services": [],
"require_session": false
}
}PUT /agents/:id/policy
Update the spending policy for an agent.
PUT /agents/:id/policy
{
"daily_limit": 5000000,
"per_call_max": 500000,
"allowed_services": ["exa", "openai"],
"require_session": true
}
→ { "policy": { ... } }Advanced: Key Export
For most use cases, API keys (see below) are the recommended way to authenticate agents. These endpoints are for advanced users who need direct access to the underlying wallet keypair — for example, to run an agent outside of IndieGent or to self-custody the key.
POST /agents/:id/key
Export the decrypted private key for an agent wallet.
POST /agents/:id/key
→ { "private_key": "0x4c8a..." }Treat this like a password. Anyone with this key can move funds. Use API keys for normal operations.
GET /agents/:id/env
Get environment variables for injecting into a self-hosted agent process.
GET /agents/:id/env
→ {
"INDIEGENT_AGENT_KEY": "0x4c8a...",
"INDIEGENT_AGENT_ADDRESS": "0x7a3f..."
}Funding & Draining
POST /agents/:id/fund
Record a funding event. On first fund, triggers automatic gas (ETH) sponsorship.
POST /agents/:id/fund
{
"tx_hash": "0xabc123...",
"amount": "25000000"
}
→ {
"funded": true,
"gas_sponsored": true,
"gas_tx_hash": "0xdef456..."
}POST /agents/:id/drain
Drain all USDC from an agent wallet back to your wallet.
POST /agents/:id/drain
→ {
"drained": true,
"amount": "25000000",
"tx_hash": "0xghi789..."
}Transactions
GET /agents/:id/transactions
Get transaction history for a specific agent. Supports pagination.
GET /agents/:id/transactions?limit=20&offset=0
→ {
"transactions": [
{
"id": "uuid",
"tx_hash": "0xabc...",
"type": "fund",
"from_address": "0xYour...",
"to_address": "0xAgent...",
"amount": "25000000",
"token": "USDC",
"timestamp": 1711000000
}
],
"total": 42
}Transaction types: fund, payment, drain, auto_topup, gas_sponsor, onramp
GET /transactions
Get transactions across all agents. Same pagination and format.
Fiat On-Ramp
POST /agents/:id/onramp
Create a Coinbase Onramp session. Returns a URL to the Coinbase hosted UI where users can buy USDC with a credit/debit card. Purchased USDC is sent directly to the agent's wallet.
POST /agents/:id/onramp
{
"amount": 50 // optional — pre-fills USD amount
}
→ {
"sessionId": "uuid",
"onrampUrl": "https://pay.coinbase.com/buy/select-asset?sessionToken=..."
}Open onrampUrl in a browser window. Zero fees for USDC on Base.
Payment Sessions
Sessions let agents batch multiple API calls into a single on-chain settlement. Instead of one USDC transfer per API call (~2s + gas each), the agent deposits once and makes instant off-chain debits for each call.
POST /sessions
Open a new payment session. Deposits USDC from the agent wallet to the platform.
POST /sessions
{
"agent_wallet_id": "uuid",
"deposit_amount": 5.00,
"duration": 3600 // optional — seconds, default 1h, max 24h
}
→ {
"session": {
"id": "uuid",
"deposit_amount": 5000000,
"used_amount": 0,
"remaining": 5000000,
"call_count": 0,
"status": "open",
"deposit_tx_hash": "0xabc...",
"expires_at": 1711003600,
"expires_in": 3600
}
}Using a Session
Pass the X-Session-Id header when calling service endpoints. Each call is debited instantly from the session balance — no on-chain transaction.
POST /services/exa/search
X-Session-Id: <session_id>
X-Agent-Wallet: <wallet_id>
{
"query": "latest AI research papers"
}
→ {
...,
"_indiegent": {
"payment": "session",
"session_id": "uuid",
"session_remaining": "$4.9900",
"cost": "$0.0100"
}
}Without X-Session-Id, the service falls back to per-call on-chain payment.
GET /sessions
List all sessions with usage stats.
GET /sessions/:id
Get session detail including deposit, usage, and remaining balance.
POST /sessions/:id/close
Close a session. Unused balance is refunded to the agent wallet on-chain.
POST /sessions/:id/close
→ {
"session": {
"id": "uuid",
"status": "closed",
"deposit_amount": 5000000,
"used_amount": 500000,
"refunded": 4500000,
"call_count": 50,
"refund_tx_hash": "0xdef..."
}
}Sessions auto-expire after their duration. Expired sessions can still be closed to trigger a refund.
API Keys
POST /api-keys
Generate a new API key. The raw key is returned once — it's hashed before storage and can never be retrieved again.
POST /api-keys
{ "name": "CI/CD Pipeline" }
→ {
"id": "uuid",
"name": "CI/CD Pipeline",
"key": "ig_live_abc123def456..."
}Keys prefixed with ig_live_ are for production. ig_test_ for testnet.
GET /api-keys
List all API keys (raw keys are not returned, only metadata).
DELETE /api-keys/:id
Revoke an API key immediately.
Balance
GET /balance
Aggregate balance overview across all agent wallets.
GET /balance
→ {
"total_usdc": "170200000",
"total_agents": 3,
"active_agents": 3,
"agents": [
{
"id": "uuid",
"name": "Research Bot",
"usdc_balance": "25000000"
},
...
]
}External Fetch
The external fetch endpoint is the core of IndieGent's value: call any paid API and let IndieGent handle the payment automatically. IndieGent detects the payment protocol (402 responses, usage-based billing, API key auth), pays from your agent's budget, and returns the response.
POST /external/fetch
Proxy a request to any external service. IndieGent intercepts payment challenges, handles them using the agent's balance, and returns the service's response transparently.
POST /external/fetch
Authorization: Bearer ig_live_abc123...
X-Agent-Wallet: research-bot
X-Session-Id: <session_id> # optional — use session balance instead of per-call payment
Content-Type: application/json
{
"url": "https://api.exa.ai/search",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"query": "latest AI research papers",
"num_results": 10
},
"max_cost": 0.05
}
→ {
"status": 200,
"headers": { ... },
"body": {
"results": [ ... ]
},
"_indiegent": {
"cost": "$0.0100",
"payment_method": "session",
"session_remaining": "$4.9900",
"service": "exa.ai",
"agent": "research-bot"
}
}| Field | Type | Description |
|---|---|---|
url | string | The external API URL to call |
method | string | HTTP method — GET, POST, PUT, DELETE |
headers | object | Headers to forward to the external service |
body | object | Request body to forward (for POST/PUT) |
max_cost | number | Maximum USD the agent is allowed to spend on this call. Request fails if the service charges more. |
Example with curl:
curl -X POST https://api.indiegent.com/external/fetch \
-H "Authorization: Bearer ig_live_abc123..." \
-H "X-Agent-Wallet: research-bot" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/v1/data",
"method": "GET",
"max_cost": 0.10
}'If an X-Session-Id header is provided, the cost is debited from the session balance instantly (no on-chain transaction). Without it, IndieGent falls back to a direct on-chain USDC payment from the agent's budget.
Organizations
POST /org
Create an organization. The authenticated user becomes the owner.
POST /org
{
"name": "Acme AI Labs"
}
→ {
"org": {
"id": "uuid",
"name": "Acme AI Labs",
"owner_id": "uuid",
"created_at": 1711000000
}
}GET /org
Get your organization's details.
POST /org/invite
Invite a team member by email. They receive an invitation to join the organization.
POST /org/invite
{
"email": "teammate@example.com",
"role": "member"
}
→ { "invited": true, "email": "teammate@example.com" }Roles: owner, admin, member, viewer
GET /org/members
List all members in your organization.
PUT /org/members/:id/role
Change a member's role. Only owners and admins can do this.
PUT /org/members/:id/role
{
"role": "admin"
}DELETE /org/members/:id
Remove a member from the organization.
Departments
Departments let you group agents for budgeting and reporting. Each agent can belong to one department.
POST /departments
Create a department.
POST /departments
{
"name": "Engineering",
"budget_limit": 500000000
}
→ {
"department": {
"id": "uuid",
"name": "Engineering",
"budget_limit": 500000000,
"agent_count": 0,
"created_at": 1711000000
}
}GET /departments
List all departments with agent counts and spend summaries.
PUT /departments/:id
Update a department's name or budget limit.
PUT /departments/:id
{
"name": "Engineering (Core)",
"budget_limit": 750000000
}DELETE /departments/:id
Delete a department. Agents in the department are moved to "Unassigned" — they are not deleted.
Analytics
Reporting endpoints for spend tracking and usage analysis. All accept optional query parameters for date range filtering: from and to (ISO 8601 or unix timestamp).
GET /analytics/overview
High-level summary: total spend, call count, active agents, and period-over-period change.
GET /analytics/overview?from=2026-03-01&to=2026-03-26
→ {
"total_spend": 12500000,
"call_count": 4230,
"active_agents": 8,
"period_change": "+12.5%"
}GET /analytics/timeseries
Spend and call volume over time. Returns daily or hourly data points depending on the date range.
GET /analytics/timeseries?from=2026-03-01&to=2026-03-26&granularity=daily
→ {
"points": [
{ "date": "2026-03-01", "spend": 450000, "calls": 152 },
{ "date": "2026-03-02", "spend": 520000, "calls": 178 },
...
]
}GET /analytics/by-service
Spend breakdown by external service (e.g., Exa, OpenAI, Anthropic).
GET /analytics/by-agent
Spend breakdown by agent.
GET /analytics/by-department
Spend breakdown by department.
Discovery
GET /.well-known/agent-pay.md
AI-readable payment instruction document. Services include this URL in 402 responses so agents know how to pay. See Agent Pay Standard.
GET /.well-known/agent-pay.json
Machine-structured version with contract addresses, env var names, and example 402 response format.
Errors
All errors return JSON with an error field:
{
"error": "Agent wallet not found"
}| Status | Meaning |
|---|---|
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing token/API key |
| 402 | Insufficient budget — agent needs more funds to complete the request |
| 404 | Resource not found |
| 422 | Cost exceeds max_cost — the service charges more than the limit you set |
| 429 | Rate limited — too many requests |
| 500 | Server error |