Three ways to buy
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):/openapi.json, /.well-known/x402 and /favicon.ico (the API’s logo) 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).
Private APIs are closed to agents. Their hosts answer 403 api_private on the catalog and purchase routes, list no payable resources in /.well-known/x402, carry no x-payment-info in /openapi.json, and keyless calls get 401. Unlisted APIs are purchasable on their host but do not appear in the directory, which lists approved (public) APIs only. An agent that subscribed before an API became private keeps its keys and can renew, like any existing subscriber.
Pay per request
- Call the endpoint without a key:
GET https://{api}.jojapi.net/v1/search?q=… - The gateway answers
402 Payment Requiredwith:PAYMENT-REQUIRED— a base64 x402 v2PaymentRequiredobject (accepts[]with the exact USDC amount, network, asset andpayTo, plus thebazaarandpayment-identifierextensions)- one or more
WWW-Authenticate: Payment …MPP challenges (methodsevm, andstripe/tempowhere enabled) - a JSON body with
reason: "payment_required",price_usd, and the catalog link
- Sign the payment with your wallet and repeat the request with
PAYMENT-SIGNATURE: <base64 PaymentPayload>(x402) orAuthorization: Payment <credential>(MPP). - 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) orPayment-Receipt(MPP) with the on-chain transaction.
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.
- TypeScript (@x402/fetch)
- curl (inspect the offer)
Buy a plan and get an API key
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:
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 are not available to agents: paid plans, per-request calls and priced pay-as-you-go plans only (a pay-as-you-go plan without a priced tier counts as free). A wallet costs nothing to create, so free plans keep the marketplace’s usual abuse protection (one verified human account).
Renewal
Plans bought by agents are prepaid periods; nothing is charged automatically. When the period ends, requests with that key answer402 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
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.
A top-up is offered only where the balance can be spent: on API hosts that sell a pay-as-you-go plan (a top-up there opens that API’s PAYG subscription by itself, no subscribe needed) and on the directory host with subscribe naming such APIs. Naming an API without a pay-as-you-go plan answers 409 no_payg_plan before any payment.
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/linksigned by the existing wallet (SIGN-IN-WITH-Xheader) 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
402withextensions["sign-in-with-x"], sign the SIWE / SIWS message, repeat withSIGN-IN-WITH-X: <base64 proof>. Nonces are single-use, 5 minutes.
The same routes exist under
https://agents.jojapi.net/apis/{api-slug}/…, and account routes without an API under https://agents.jojapi.net/.
Payment rails
Legacy x402 v1 (
X-PAYMENT) is not supported.
Errors
Refunds
On-chain payments are final. You are never charged for upstream5xx 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.