# The autonomous pay loop

This page narrates one thing end to end: an AI agent paying for MapMap the way
it calls it, with no human in the loop. It is the practical companion to
[Machine payments (x402)](/docs/x402) and the [MCP server](/docs/mcp), and every
request and response shape below is the real wire format, captured against the
hosted gateway.

There is a runnable version in the repository at
`examples/autonomous-pay-loop/` : a single zero-dependency Node script that runs
every step here live, except the payment itself, which it prints but never
sends.

## The loop

1. **Discover** the tools over the MCP server.
2. **Call** a metered tool with the agent's own `Bearer snk_` key.
3. **See a 402** when there is no way to pay for the next call.
4. **Pay** with an `X-PAYMENT` retry (x402 crypto settlement).
5. **Continue**: poll the balance, then retry, no human involved.

What makes step 4 possible for a brand-new agent is one deployment setting:
`SN_TOPUP_PROVISIONAL_SPEND=true`. It lets an unverified **provisional** key
(the kind you get from a single unauthenticated call) top up and spend the
credit it buys. The payment itself stands in for email verification, so the loop
never has to stop for a person. See [x402](/docs/x402) for what that setting
does and does not enable.

```sh
export BASE=https://api.mapmap.ai
```

## 1. Discover

The hosted MCP server speaks streamable HTTP at `https://mcp.mapmap.ai/mcp`.
After the JSON-RPC `initialize` handshake, `tools/list` returns the catalogue an
agent chooses from: 30-plus tools spanning routing, geocoding, ADR compliance,
map styling and local geometry. See [MCP server](/docs/mcp) for client setup and
the full tool list.

An agent picks a tool and calls it. It does not need the MCP transport to pay:
the metered tools proxy the same gateway REST endpoints, and the payment loop
below is identical whether the call arrives over MCP or over plain HTTP. When an
MCP caller presents its own `Authorization: Bearer snk_…`, every metered call in
the tool bills that key, not the operator's shared key.

## 2. Get a key, then call

One unauthenticated call issues a working key immediately:

```sh
curl -sS -X POST "$BASE/v1/keys" \
  -H "Content-Type: application/json" \
  -d '{"email":"agent@example.com","accept_tos":true,"label":"my-agent"}'
```

```json
{
  "key": "snk_…",
  "key_id": "…-uuid",
  "state": "provisional",
  "calls": 1000,
  "expires_in_h": 72,
  "verify": "link sent to email; clicking upgrades this key to the free tier",
  "tos": "https://api.mapmap.ai/terms"
}
```

The key is `provisional`: 1,000 calls, works right now, no verification needed to
start. The agent calls a metered tool with it:

```sh
curl -sS -G "$BASE/route/v1/driving/-0.1276,51.5072;-1.2577,51.7520" \
  -H "Authorization: Bearer snk_…"
```

```json
{ "code": "Ok", "routes": [{ "distance": 96063.0, "duration": 4599.0, "…": "…" }] }
```

## 3. The 402

Eventually the agent needs to pay: its free allowance runs down, or it simply
decides to pre-fund credit before it does. Rather than wait to be refused
mid-workflow, it asks the top-up endpoint for a quote. With no `X-PAYMENT`
header, `POST /v1/x402/topup` answers the x402 wire 402 that names every rail it
may pay on:

```sh
curl -sS -X POST "$BASE/v1/x402/topup?usd=0.10" \
  -H "Authorization: Bearer snk_…"
```

```json
{
  "x402Version": 1,
  "error": "payment required: $0.10 prepaid credit bundle",
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "100000",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0x…",
      "resource": "https://api.mapmap.ai/v1/x402/topup?usd=0.10",
      "description": "MapMap prepaid credit top-up: $0.10 → ~6.666p of API credit …",
      "mimeType": "application/json",
      "maxTimeoutSeconds": 60,
      "extra": {
        "bundleUsd": "0.10",
        "bundlesUsd": ["0.10", "5", "20", "50"],
        "creditMillipenceEstimate": 6666,
        "fxMicroUsdPerPence": 15000,
        "name": "USD Coin",
        "version": "2"
      }
    },
    { "scheme": "exact", "network": "solana", "maxAmountRequired": "100000", "extra": { "feePayer": "…" }, "…": "…" }
  ],
  "instructions": "Retry with an X-PAYMENT header signing exactly maxAmountRequired. …"
}
```

Two rails, Base and Solana, the same USDC atomic amount on both, so the agent
pays on whichever chain it holds USDC. The EVM `extra` carries the EIP-712
domain (`name`, `version`) the payment is signed against; the Solana `extra`
carries the `feePayer` the facilitator sponsors. `$0.10` is the micro-bundle
that clears stock client spend caps; the other bundles buy proportionally more
credit per settlement.

Why buy prepaid credit rather than pay per call? Standard-class calls cost a
fraction of a penny, below what a per-call facilitator fee would be, so one
settlement funds thousands of calls at true tiered list prices. Truck and ADR
calls can also be paid inline per call; the mechanics are identical and covered
in [x402](/docs/x402).

## 4. Pay

The agent signs an x402 `PaymentPayload` for the rail it chose and retries with
it base64-encoded in the `X-PAYMENT` header. On the EVM rail:

```json
{
  "x402Version": 1,
  "scheme": "exact",
  "network": "base",
  "payload": {
    "signature": "0x…",
    "authorization": {
      "from": "0x<funded wallet>",
      "to": "0x<payTo from the 402>",
      "value": "100000",
      "validAfter": "0",
      "validBefore": "<unix now + 60>",
      "nonce": "0x<32-byte random>"
    }
  }
}
```

```sh
export PAYMENT=$(printf '%s' "$PAYLOAD_JSON" | base64)
curl -sS -X POST "$BASE/v1/x402/topup?usd=0.10" \
  -H "Authorization: Bearer snk_…" \
  -H "X-PAYMENT: $PAYMENT"
```

Sign **exactly** `maxAmountRequired`; a mismatched value is refused before any
facilitator round-trip. Client libraries in the
[x402 project](https://github.com/coinbase/x402) build and sign the payload for
you, an `x402-fetch` wrapper wired with an EVM signer picks the Base entry, one
wired with a Solana signer picks the Solana entry.

The gateway claims the authorization's nonce, verifies the payment with its
facilitator, and **awaits settlement**. Credit is minted only when settlement
returns `success`, never on verify alone. On success it credits the estimated
amount to the identity ledger and answers:

```json
{
  "status": "credited",
  "creditedMillipence": 6666,
  "balanceMillipence": 6666,
  "tx": "0x…",
  "network": "base",
  "fxMicroUsdPerPence": 15000
}
```

Credit is idempotent by the payment's nonce and settlement transaction, so a
lost response never costs a second payment: **poll `GET /v1/keys/self` before
ever re-paying.** Because `SN_TOPUP_PROVISIONAL_SPEND` is on, this credit is
immediately spendable even though the key was never email-verified.

## 5. Continue

The agent polls its balance, a quota-free endpoint it can hit freely, and,
once credit has landed, retries the original request unchanged:

```sh
curl -sS "$BASE/v1/keys/self" -H "Authorization: Bearer snk_…"
```

```json
{
  "key_id": "…-uuid",
  "state": "provisional",
  "monthly_quota": 1000,
  "used_this_month": 3,
  "remaining": 997,
  "credits_pence": 6,
  "credits_millipence": 6666
}
```

Each metered call now draws its class price from the ledger: standard routing
and data from 0.05p, truck/ADR premium from 1p, with no further 402 until the
balance runs low. The efficient loop watches `credits_millipence`, tops up on a
low-water mark, and never hits a 402 mid-workflow. Only successful calls are
charged; a 4xx releases the debit. See [Pricing](/pricing) for the schedules.

That is the whole loop: discover, call, pay, continue, with no human at any
step.

## Run it

```sh
cd examples/autonomous-pay-loop
node autonomous-pay-loop.mjs
```

The script runs discovery, key issuance, the metered call, the 402 and the
balance poll live against the hosted gateway. The payment step is printed as an
exact request shape and deliberately not sent, so the example moves no funds. To
settle a real top-up, sign the payload with a funded wallet using an x402
client.

## Next steps

- [Machine payments (x402)](/docs/x402): the full 402 contract, both rails, the top-up bridge
- [MCP server](/docs/mcp): connect any MCP client and the per-caller billing seam
- [Pricing](/pricing): per-call prices, classes, and top-up bundles
- [Quickstart](/docs/quickstart): issue a key and make your first call
