x402 lets a client pay for a request with stablecoins. BazaarLink accepts x402 payments, settled through OKX's x402 facilitator on X Layer, to register an agent account and to top up an existing balance. This page describes the two routes exactly as they behave.
The 402 flow
Both routes follow the same three steps: ask, sign, resend.
Send the request without a payment. The server answers 402 Payment Required with a JSON body: x402Version, resource, and accepts (network, asset, amount, payTo, maxTimeoutSeconds).
Sign a payment authorization for one entry in accepts with your own wallet key.
Send the same request again with the base64-encoded payment payload in the X-PAYMENT header. The header name payment-signature is accepted as an alias.
Read the requirements from the response
Take network, asset and amount from the 402 response instead of hard-coding them. amount is in the asset's smallest unit (6 decimals for USDT0). Send the same JSON body in both requests.
POST /api/v1/agents/register/x402 creates an agent account, an API key and an initial balance in one paid request. It needs no API key and no login.
Request body
namerequired
string
Agent name, 1 to 100 characters.
description
string
Optional description, up to 4000 characters.
amountUsdrequired
number
Amount to pay in US dollars, a positive number. It is clamped to the allowed range (currently $1 to $50) before the 402 is built, so read the amount from the response.
Unknown fields are rejected with 400 bad_request.
1. Ask without paying
The response is 402 with the payment requirements. Nothing is created yet.
Sign with your own wallet, then send the same request with the X-PAYMENT header. The curl command shows the request; the TypeScript example below produces the header value.
This example uses the @okxweb3/x402 client packages and viem; you can sign with the OKX Wallet or any wallet key. The private key stays on your machine; only the signed authorization is sent.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { x402Client } from"@okxweb3/x402-core/client";
importtype { Network } from"@okxweb3/x402-core/types";
import { toClientEvmSigner } from"@okxweb3/x402-evm";
import { ExactEvmScheme } from"@okxweb3/x402-evm/exact/client";
import { privateKeyToAccount } from"viem/accounts";
constURL = "https://bazaarlink.ai/api/v1/agents/register/x402";
constHEADERS = { "content-type": "application/json" };
constBODY = JSON.stringify({ name: "my-agent", amountUsd: 1.1 });
// 1. Ask without paying. The 402 body lists what the server accepts.const challenge = awaitfetch(URL, { method: "POST", headers: HEADERS, body: BODY });
if (challenge.status !== 402) thrownewError("unexpected status " + challenge.status);
const paymentRequired = await challenge.json();
// 2. Sign the payment authorization with your own wallet key.const privateKey = readSecret("payer-private-key") as`0x${string}`; // from your own secret store, never from source codeconst signer = toClientEvmSigner(privateKeyToAccount(privateKey));
const client = newx402Client().register(
paymentRequired.accepts[0].networkasNetwork,
newExactEvmScheme(signer),
);
const payload = await client.createPaymentPayload(paymentRequired);
const xPayment = Buffer.from(JSON.stringify(payload), "utf8").toString("base64");
// 3. Send the same request again with the signed payment.const res = awaitfetch(URL, { method: "POST", headers: { ...HEADERS, "x-payment": xPayment }, body: BODY });
const account = await res.json(); // 201: api_key, credits, claim_token, payment ...console.log(res.status, account.credits_usd);
Keep the wallet private key in an environment variable or a secret store, never in source code.
Registration response
A successful registration returns 201 with these fields. The API key appears only here, so store it right away.
A successful top-up returns 200 with status credited, the new balance in US dollars, the txHash, and paidUsd, creditedUsd and serviceFeeUsd (what you paid, what was credited, and the platform top-up fee).
1
2
3
4
5
6
7
8
9
10
11
HTTP/1.1200 OK
Content-Type: application/json
{"status":"credited","balance":12.5,"txHash":"0xTX_HASH","paidUsd":1.1,"creditedUsd":1,"serviceFeeUsd":0.1}
1
2
3
4
5
6
7
8
9
// Same three steps against /api/x402/topup; only the URL, body and auth header change.constURL = "https://bazaarlink.ai/api/x402/topup";
constHEADERS = {
"content-type": "application/json",
authorization: "Bearer " + process.env.BAZAARLINK_API_KEY,
};
constBODY = JSON.stringify({ amountUsd: 1.1 });
// ...reuse the challenge / sign / resend code from the registration example.// 200 -> { "status": "credited", "balance": 12.5, "txHash": "0x...", "paidUsd": 1.1, "creditedUsd": 1, "serviceFeeUsd": 0.1 }
Read the current limits
GEThttps://bazaarlink.ai/api/x402/topup
GET /api/x402/topup returns minUsd, maxUsd and network without authentication.
1
curl https://bazaarlink.ai/api/x402/topup
1
{"minUsd":1,"maxUsd":50,"network":"eip155:196"}
Duplicate and repeated payments
A signed authorization can be used once. The server recognizes a repeated payment before it contacts the payment network, so a retry never charges you twice.
Top-up: resending a payment that was already credited returns 200 with status already_credited.
Registration: for 15 minutes the same signed payment returns the same 201 response, API key included, so a network failure can be retried safely. After that the response is 200 with status already_registered and the payment txHash, and the API key is not shown again.
Error responses
The x402 routes return errors as { "error": { "message", "code" } }. Two responses differ: 410 uses { "error", "code" } and 429 uses { "error" } with a Retry-After header.
HTTP
Code
Meaning
400bad_request
The body is not valid: wrong type, missing name, or an unknown field.
400topup_unavailable
Top-up is not available for this account.
401unauthenticated
Top-up only: no valid API key or session.
402(payment requirements body)
No usable payment yet. The body holds the requirements, so sign and resend. It is also returned when the payment does not match the requirements or fails verification.
402payment_amount_too_low
The settled amount is lower than the amount requested.
403geo_blocked
x402 is not available from your region.
410agent_register_discontinued
Agent registration is switched off.
429(Retry-After header)
Too many registrations from the same network source. Wait for the seconds given in Retry-After.
502facilitator_error
The payment could not be verified or settled. Try again later.
502settlement_error
The payment was received but could not be credited. Resend the same payment instead of signing a new one.
502registration_error
The payment was received but the account could not be created. Resend the same payment instead of signing a new one.
503disabled / runtime_disabled
x402 is switched off or not configured right now.
503asset_unavailable / dedup_unavailable
A dependency (asset configuration, duplicate check or top-up check) is unavailable. Try again later.
503signup_disabled / agent_register_unavailable
Registration is temporarily disabled or unavailable.
Hand the account to a person
Send upgrade_url from the response to the account owner. After they sign in and claim it, the API key and balance move to their account. Claim before claim_expires.
1
https://bazaarlink.ai/claim?token=<claim_token>
Network and asset
Today this is USDT0 on X Layer, settled through OKX's x402 facilitator. A platform top-up fee applies, so the balance you receive is lower than the amount you pay (see pricing). Payments settle on-chain and cannot be reversed, so check the amount and network before you sign.