> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jojapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Pay as an AI agent (x402 / MPP)

> AI agents buy access to any JoJ API without an account: pay per request with a wallet, buy a plan and receive an API key, or fund a pay-as-you-go balance. x402 and MPP over plain HTTP.

An AI agent does not sign up. It pays. Every API on the JoJ API marketplace answers keyless requests with a machine-readable **HTTP 402** offer that an agent wallet can settle in one round trip — over **x402** (USDC on Base) or the **Machine Payments Protocol (MPP)**. The paying wallet becomes the agent's identity: what it buys, it keeps.

## Three ways to buy

| Product             | How                                                                           | What you get                                                                                                 |
| ------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| **Pay per request** | Call a priced endpoint with no API key, receive a `402`, pay, repeat the call | The response. Nothing to store. Price per endpoint is fixed and published                                    |
| **Buy a plan**      | `POST https://{api}.jojapi.net/_jojapi/agent/subscribe/{plan}`                | A fresh **API key** bound to a prepaid subscription period (quota, rate limit, everything the plan includes) |
| **Fund a balance**  | `POST https://{api}.jojapi.net/_jojapi/agent/topup`                           | Account-wide pay-as-you-go balance, a PAYG subscription on the named API and its API key                     |

Plan purchases, top-ups and per-request calls all work from the same wallet; the first payment creates the account.

## Discover what is for sale

Every API host publishes its catalog and discovery documents (no auth):

| URL                                            | Content                                                                        |
| ---------------------------------------------- | ------------------------------------------------------------------------------ |
| `https://{api}.jojapi.net/_jojapi/agent/plans` | Plans (price, period, quota, rate limit), endpoints sold per request, policies |
| `https://{api}.jojapi.net/openapi.json`        | OpenAPI with `x-payment-info` on every payable operation                       |
| `https://{api}.jojapi.net/.well-known/x402`    | The x402 discovery document (resource list + ownership proofs)                 |
| `https://agents.jojapi.com/apis`               | Directory of every agent-payable API on the marketplace                        |

`/openapi.json` and `/.well-known/x402` are reserved on every API host and always answered by the gateway itself, without authentication — also when the provider has not enabled agent payments (then without payment annotations). The `{api}` host is the gateway subdomain shown on the API's page (for `jojapi.com/hub/api/web-search` the calls go to `web-search.jojapi.net`).

## Pay per request

1. Call the endpoint without a key: `GET https://{api}.jojapi.net/v1/search?q=…`
2. The gateway answers `402 Payment Required` with:
   * `PAYMENT-REQUIRED` — a base64 x402 v2 `PaymentRequired` object (`accepts[]` with the exact USDC amount, network, asset and `payTo`, plus the `bazaar` and `payment-identifier` extensions)
   * one or more `WWW-Authenticate: Payment …` MPP challenges (methods `evm`, and `stripe` / `tempo` where enabled)
   * a JSON body with `reason: "payment_required"`, `price_usd`, and the catalog link
3. Sign the payment with your wallet and repeat the request with `PAYMENT-SIGNATURE: <base64 PaymentPayload>` (x402) or `Authorization: Payment <credential>` (MPP).
4. The gateway verifies the payment with the facilitator, forwards your request to the API, and **settles only if the upstream answered 2xx-4xx**. The response carries `PAYMENT-RESPONSE` (x402) or `Payment-Receipt` (MPP) with the on-chain transaction.

Upstream `5xx` and gateway errors are never charged. If settlement fails after the upstream answered, the body is withheld and a fresh offer is returned (`reason: "settlement_failed"`) — pay again to retry.

<Tabs>
  <Tab title="TypeScript (@x402/fetch)">
    ```ts theme={null}
    import { wrapFetchWithPayment } from "@x402/fetch";
    // signer = any viem/ethers account holding USDC on Base
    const paidFetch = wrapFetchWithPayment(fetch, signer);
    const res = await paidFetch("https://web-search.jojapi.net/v1/search?q=jojapi");
    console.log(res.headers.get("payment-response"), await res.json());
    ```
  </Tab>

  <Tab title="curl (inspect the offer)">
    ```bash theme={null}
    curl -i https://web-search.jojapi.net/v1/search?q=jojapi
    # HTTP/1.1 402 Payment Required
    # payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOi...
    # www-authenticate: Payment id="…", realm="web-search.jojapi.net", method="evm", intent="charge", …
    ```
  </Tab>
</Tabs>

Identity in a paid call is the wallet that signed it. Per-wallet rate limits apply (default 5 requests/second, 300/minute per API); rate-limited requests are never charged.

## Buy a plan and get an API key

```bash theme={null}
curl -i -X POST https://web-search.jojapi.net/_jojapi/agent/subscribe/pro-monthly
# 402 with the plan price in PAYMENT-REQUIRED / WWW-Authenticate
```

Pay the offer (x402 or MPP) and repeat the `POST` with the credential. Include the `payment-identifier` extension (a client-generated id) — it makes the purchase **idempotent**: repeating the request with the same id returns the same result, key included, even if the first response was lost.

The `200` response contains:

```json theme={null}
{
  "status": "success",
  "api_key": "jk_…",
  "auth": { "header": "X-JoJAPI-Key" },
  "subscription": { "ref": "…", "plan": { "slug": "pro-monthly", "price_usd": 9, "period": "1 MONTH", "quota": [ … ] }, "period_end": "2026-10-08 12:00:00", "renewal": "prepaid" },
  "existing": [ … other active subscriptions of this wallet on this API … ],
  "payment": { "reference": "0x…", "rail": "x402" }
}
```

Use the key like any consumer: `X-JoJAPI-Key: jk_…` or `Authorization: Bearer jk_…`. **The key is bound to that subscription.** Buying a second plan of the same API creates a second subscription with its own key — nothing is cancelled; `existing` lists what you already hold. Pass `{"replace": "<subscription ref>"}` in the body to cancel one on purpose (no refund of the remaining period).

Free plans need no payment but a wallet signature — see Sign-In-With-X below.

### Renewal

Plans bought by agents are **prepaid periods**; nothing is charged automatically. When the period ends, requests with that key answer `402` with `reason: "renewal_required"` and an offer for the plan price. Pay it against `POST https://{api}.jojapi.net/_jojapi/agent/renew` (send the key too) and a new period starts from now, counters reset. Early renewal is refused with `not_expired`.

## Fund a pay-as-you-go balance

```bash theme={null}
curl -i -X POST https://web-search.jojapi.net/_jojapi/agent/topup \
  -H 'content-type: application/json' \
  -d '{"amount_usd": 25, "subscribe": [{"api": "web-search"}]}'
```

The offer is for exactly `amount_usd`. On payment the balance is credited to the paying wallet's account, a PAYG subscription is created on each API in `subscribe` (its first PAYG plan unless `plan` is given) and the response returns the key for each **newly created** subscription. Later top-ups from the same wallet land on the same account and return only key hints (`…ab12`), never the key again.

The balance is account-wide: every PAYG key of the account spends it. When it runs out, requests answer `402` with `reason: "insufficient_balance"` and a top-up offer bound to that account — anyone may pay it, the credit goes to the account of the key, and the paying wallet is **not** linked to it.

## Identity, wallets and Sign-In-With-X

* One wallet = one account. The identity key is chain-agnostic on EVM (the same address on Base, Polygon or Arbitrum is one account); Solana addresses are separate identities.
* Nothing is ever merged by guesswork. To use two wallets on one account, link them with a **double signature**: `POST …/_jojapi/agent/identities/link` signed by the existing wallet (`SIGN-IN-WITH-X` header) with the second wallet's proof in the body (`{"link": <siwx proof>}`).
* Identity-only routes use **Sign-In-With-X** (CAIP-122): request the route, receive `402` with `extensions["sign-in-with-x"]`, sign the SIWE / SIWS message, repeat with `SIGN-IN-WITH-X: <base64 proof>`. Nonces are single-use, 5 minutes.

| Route                                                          | Purpose                                                                     |
| -------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `GET …/_jojapi/agent/me`                                       | Account, identities, balance, subscriptions with key hints, recent payments |
| `POST …/_jojapi/agent/keys/rotate` `{"subscription": "<ref>"}` | New key for one subscription; the old key stops working                     |
| `POST …/_jojapi/agent/identities/link` / `unlink`              | Manage wallets                                                              |
| `POST …/_jojapi/agent/subscribe/{free-plan}`                   | Claim a free plan                                                           |

The same routes exist under `https://agents.jojapi.com/apis/{api-slug}/…`, and account routes without an API under `https://agents.jojapi.com/`.

## Payment rails

| Rail        | Header pair                                                                | Networks / methods                                                                                                             |
| ----------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **x402 v2** | `PAYMENT-REQUIRED` → `PAYMENT-SIGNATURE` → `PAYMENT-RESPONSE`              | `exact` scheme, USDC on Base (`eip155:8453`); more networks as listed in `accepts[]`                                           |
| **MPP**     | `WWW-Authenticate: Payment` → `Authorization: Payment` → `Payment-Receipt` | `evm` (EIP-3009 `authorization` credentials, settled through the x402 facilitator); `stripe` (cards) and `tempo` where enabled |

Legacy x402 v1 (`X-PAYMENT`) is not supported.

## Errors

| Status | `reason`                                    | Meaning                                                                                                                                          |
| ------ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| 401    | `api_key_required`                          | The endpoint is not sold per request; use a key (buy a plan or fund a balance)                                                                   |
| 402    | `payment_required`                          | Offer attached; pay and repeat                                                                                                                   |
| 402    | `payment_invalid` (+ `error`)               | The facilitator rejected the payment — `error` carries its code (e.g. `insufficient_funds`, `invalid_payment_requirements`, `duplicate_payment`) |
| 402    | `renewal_required`                          | Prepaid period ended; pay the renewal offer                                                                                                      |
| 402    | `insufficient_balance`                      | Top-up offer attached                                                                                                                            |
| 402    | `settlement_failed`                         | Settlement failed after the upstream answered; body withheld, pay again                                                                          |
| 402    | `sign_in_required`                          | Identity route: sign the SIWx challenge                                                                                                          |
| 409    | `duplicate_payment` / `payment_in_progress` | The same payment authorization was already used or is being processed                                                                            |
| 429    | `rate_limited`                              | Per-wallet or per-IP limit; nothing was charged                                                                                                  |

## Refunds

On-chain payments are final. You are never charged for upstream `5xx` or gateway errors; you are charged for `4xx` answers from the API (a wrong parameter is still a served request). Disputes are handled as balance credits on the agent's account — contact the marketplace with the payment reference.
