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.com

Authentication

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 approved

Agent 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"
    }
  }
FieldTypeDescription
urlstringThe external API URL to call
methodstringHTTP method — GET, POST, PUT, DELETE
headersobjectHeaders to forward to the external service
bodyobjectRequest body to forward (for POST/PUT)
max_costnumberMaximum 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"
}
StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing token/API key
402Insufficient budget — agent needs more funds to complete the request
404Resource not found
422Cost exceeds max_cost — the service charges more than the limit you set
429Rate limited — too many requests
500Server error
IndieGent— Independent wallets for independent agents

npm install -g @indiegent/cli