# bitcoinrouter.ai for agents

Everything here works over plain HTTP with no browser, so an AI agent with a Lightning wallet can buy its own key. This is the whole flow. The API is documented at [/api.md](https://bitcoinrouter.ai/api.md), these docs are at [/docs.md](https://bitcoinrouter.ai/docs.md), and this section alone is [/agents.md](https://bitcoinrouter.ai/agents.md).

### 1\. Create an account

```
curl -s -X POST https://bitcoinrouter.ai/api/signup/code
# {"account_id": 42, "login_code": "k7mq-3xzp-wq2n-7hd4-vt6s", "session": "..."}
```

-   **Save the login code first.** It is the only way back into the account; there is no recovery. An account that never pays is deleted a week after signup.
-   **Authenticate** every later call with `Authorization: Bearer <session>`; the examples below keep the token in `$SESSION`. Sessions last 30 days; a new one comes from logging in with the account id and the code:

```
curl -s -X POST https://bitcoinrouter.ai/api/login \
  -H 'content-type: application/json' \
  -d '{"identifier": "42", "password": "k7mq-3xzp-wq2n-7hd4-vt6s"}'
```

### 2\. Prepay one turn

A key needs its provider's first payment: $1 at Tinfoil, $5 at TrustedRouter (`GET /api/keys/quote?provider=tinfoil` says exactly what). Pay an invoice from any Lightning wallet:

```
curl -s -X POST https://bitcoinrouter.ai/api/invoices \
  -H "authorization: Bearer $SESSION" -H 'content-type: application/json' \
  -d '{"amount_usd": null, "provider": "tinfoil"}'
# {"payment_id": 7, "invoice": "lnbc...", "amount_usd": 1.0, "amount_sats": 893, ...}

curl -s https://bitcoinrouter.ai/api/payments/7 -H "authorization: Bearer $SESSION"
# {"state": "settled", ...}   poll until it leaves "pending"
```

Invoices expire after ten minutes, and what they pay is [non-refundable](https://bitcoinrouter.ai/docs#refunds). Or connect a wallet that supports Nostr Wallet Connect, and we pull payments from it as the key is used. Pause the account and the unspent part of those goes back to it (see [Refunds](https://bitcoinrouter.ai/docs#refunds)):

```
curl -s -X POST https://bitcoinrouter.ai/api/funding/nwc \
  -H "authorization: Bearer $SESSION" -H 'content-type: application/json' \
  -d '{"uri": "nostr+walletconnect://..."}'

curl -s -X POST https://bitcoinrouter.ai/api/topup \
  -H "authorization: Bearer $SESSION" -H 'content-type: application/json' \
  -d '{"provider": "tinfoil"}'
# {"payment_id": 8}   then poll /api/payments/8 as above
```

### 3\. Create the key

```
curl -s -X POST https://bitcoinrouter.ai/api/keys \
  -H "authorization: Bearer $SESSION" -H 'content-type: application/json' \
  -d '{"provider": "tinfoil"}'
# {"key": {"base_url": "https://inference.tinfoil.sh/v1", ...}, "secret": "tk_..."}
```

The secret is returned once. A 409 carries a stable code: `topup_required` (pay first), `key_limit` (one key without a wallet, ten with one), `wallet_has_debt` (another account funded by your wallet owes money), `account_paused`.

### 4\. Use it

The key works at its provider's OpenAI-compatible base URL and nowhere else. `GET /api/providers` lists providers without auth. For web search, see [Examples](https://bitcoinrouter.ai/docs#examples).

```
export OPENAI_BASE_URL="https://inference.tinfoil.sh/v1"
export OPENAI_API_KEY="tk_..."
# model: deepseek-v4-1-flash
# TrustedRouter: https://api.trustedrouter.com/v1, model anthropic/claude-opus-5.5
```

### 5\. Keep it running

-   `GET /api/me` shows `headroom_usd` (what the keys can still spend), each key's `usage_usd` and its `paused_reason`, and the last payments.
-   **Without a wallet,** a key stops when the prepayment runs out (`paused_reason: "exhausted"`). Pay another invoice, up to $1,000 prepaid per account, and it resumes.
-   **With a wallet,** we pull a refill when `headroom_usd` drops below half of `target_usd` (one turn by default), and collect what is owed after an hour idle. `POST /api/topup` does it on demand.
-   Errors are `{"error": "..."}`. 429 is a rate limit: back off. Dollar fields are JSON numbers, times are milliseconds since the epoch.
