Buy credits · get a spend key

One dollar, one signature, one key.

$1.00 USDC on Base mainnet buys 400 credits; an MCP tool call costs 3 credits (about 133 calls). The key you get back works in any MCP client. No account, no card, no ETH: just USDC on Base. Not sure yet? 20 free tool calls per UTC day, no key or wallet needed.

Free: discovery + 20 tool calls per UTC day, no key needed Then: from $0.01 USDC per call (Base mainnet; $0.02 for a verified answer with a signed attestation) via x402, or from 3 credits per call with a spend key Pricing Buy credits ($1.00 = 400) Set up your client
Plain terms

What you are buying

Credits are prepaid call units on the hosted naxytra runtime and MCP server. A top-up is $1.00 USDC on Base mainnet (one x402 payment) and grants 400 credits; 1 credit = $0.0025. An MCP tool call costs 3 credits ($0.0075, versus $0.01 paying per call); other runtime tasks cost 1-8 credits by tier. A failed call never consumes credits.

  • The spend key (xytara_spend_<hex>) is what your MCP client sends with each call: Authorization: Bearer <key>, or X-Naxytra-Key, or ?key= on the MCP URL for clients that cannot set headers.
  • The key is shown once, at purchase. It is not stored by this page and cannot be re-displayed; anyone holding it can spend the credits, so keep it secret and ask support to revoke it if it leaks.
  • Before you buy: 20 free tool calls per UTC day, no key or wallet needed. The MCP server reports the remaining free calls in each result's _meta["naxytra.com/allowance"].
  • Credits are tied to the paying wallet address and are not transferable. An unused balance can be refunded within 14 days to the address that paid.
  • Card checkout is coming.

Refund policy · Terms of service · Full pricing

Base Sepolia

Testnet and trying it out

Credit top-ups are Base mainnet only: Base Sepolia (testnet) top-ups are not enabled, because free test USDC must not buy credits spendable on real provider work. To try the tools without paying, use the free daily allowance: connect any MCP client with no key and make up to 20 calls per UTC day. Pay-per-call x402 on Base Sepolia ($0.001 per call) remains available for agents that want to exercise the payment path with test USDC.

Connect a client (no key needed) · curl quickstart · Base Sepolia USDC faucet

Pay in your browser · $1.00 USDC on Base

Pay $1.00 USDC on Base and get a key

Connect an injected wallet (MetaMask, Coinbase Wallet, Rabby), sign one gasless USDC authorization, and the runtime returns your spend key with 400 credits. You need $1.00 of USDC on Base mainnet and nothing else: no ETH for gas, no account. The signature is a transfer authorization for exactly 1000000 USDC base units ($1.00) to 0x7cd2E0Ed2721319B20FAac4109774d030833F84D; the runtime's own 402 challenge is authoritative and is what this page signs.

  1. Connect your wallet and switch it to Base (chain 8453) if asked.
  2. Sign the $1.00 USDC authorization when your wallet shows it (EIP-712 "TransferWithAuthorization" on the USD Coin contract).
  3. Copy your key. It is shown once; this page does not store it and never puts it in a URL.
Check balance

How many credits are left on a key?

Paste a spend key. It is sent only to the runtime's balance endpoint (GET https://xytara.onrender.com/v1/credits/balance) as the Authorization header; it does not leave your browser otherwise and is not stored.

same check from a terminal
curl -s https://xytara.onrender.com/v1/credits/balance \
  -H "Authorization: Bearer YOUR_KEY"
# -> {"ok":true,"account_id":"0x...","available_units":400,"credits_per_call":3,...}
CLI alternative · agent operators with a wallet key

Buy from a script instead

If your agent already holds a funded wallet, do the same three requests from Node: fetch the 402, sign the EIP-712 authorization, POST it with the PAYMENT-SIGNATURE header. The response's spend_credential.bearer_token is the key; store it with the same care as the wallet key. The public integration guide at github.com/naxytra/naxytra-mcp shows the same flow inside an MCP client.

buy-credits.mjs (BUYER_PRIVATE_KEY=0x... node buy-credits.mjs)
// Buy 400 credits ($1.00 USDC on Base mainnet) from a wallet key and print the spend key.
// Node 20+. npm i viem@2.21.55   (BUYER_PRIVATE_KEY holds USDC on Base; no ETH is needed, the facilitator pays gas)
import { privateKeyToAccount } from "viem/accounts";
import { randomBytes } from "node:crypto";

const TOPUP = "https://xytara.onrender.com/x402/credits/topup";
const account = privateKeyToAccount(process.env.BUYER_PRIVATE_KEY);

// 1. Unpaid POST -> 402 with the exact terms (network, asset, amount, payTo).
const quote = await fetch(TOPUP, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" });
if (quote.status !== 402) throw new Error("expected 402, got " + quote.status + " " + (await quote.text()));
const { payment_required } = await quote.json();
const accept = payment_required.accepts.find((a) => a.network === "eip155:8453" && a.scheme === "exact");

// 2. Sign one gasless USDC authorization (EIP-3009 TransferWithAuthorization, EIP-712).
const now = Math.floor(Date.now() / 1000);
const authorization = {
  from: account.address,
  to: accept.payTo,
  value: accept.amount,
  validAfter: "0",
  validBefore: String(now + (accept.maxTimeoutSeconds || 300) - 30),
  nonce: "0x" + randomBytes(32).toString("hex")
};
const signature = await account.signTypedData({
  domain: { name: accept.extra.name, version: accept.extra.version, chainId: 8453, verifyingContract: accept.asset },
  types: {
    TransferWithAuthorization: [
      { name: "from", type: "address" }, { name: "to", type: "address" }, { name: "value", type: "uint256" },
      { name: "validAfter", type: "uint256" }, { name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" }
    ]
  },
  primaryType: "TransferWithAuthorization",
  message: { ...authorization, value: BigInt(authorization.value), validAfter: 0n, validBefore: BigInt(authorization.validBefore) }
});
const paymentSignature = Buffer.from(JSON.stringify({ x402Version: 2, accepted: accept, payload: { signature, authorization } })).toString("base64");

// 3. Paid POST -> 200 with the spend key (shown once) and the credit grant.
const paid = await fetch(TOPUP, { method: "POST", headers: { "content-type": "application/json", "PAYMENT-SIGNATURE": paymentSignature }, body: "{}" });
const result = await paid.json();
if (!paid.ok) throw new Error(paid.status + " " + result.reason + (result.detail ? ": " + result.detail : ""));
console.log("spend key (shown once, keep it secret):", result.spend_credential.bearer_token);
console.log("credits available:", result.balance.available_units);

On PowerShell set the key as its own statement: $env:BUYER_PRIVATE_KEY = "0x..."; node buy-credits.mjs. The xytara npm client's guided path (xytara first-run --execute-with-credits) spends credits on the runtime once you have a key.

One minute more

Next: set up your client

Paste the key into the box on the setup page and copy the snippet for your client: Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, LangChain, the OpenAI Agents SDK, or an x402-native client that pays per call without a key.

Set up your client · Support