Quickstart (5 minutes)

Goal

Make a request, receive a 402 challenge, then pay and retry to get a 200 response.

Prerequisites

  • A wallet funded with USDC on Base or Solana (v2 endpoints support both; v1 is Base/EVM-only).

  • A runtime (Node.js 18+ or Python) and a safe place to store a private key (never commit it).

1) Trigger a 402 challenge

Use -i so you can see the PAYMENT-REQUIRED header:

curl -i https://sentiment-api.kytona.com/v2/snapshot/global

You’ll receive 402 Payment Required plus:

  • Header: PAYMENT-REQUIRED (source of truth)

  • Body: a JSON representation of the same requirements (for convenience)

2) Pay and retry (TypeScript, Base/EVM)

npm i @x402/core @x402/evm
import { decodePaymentRequiredHeader } from "@x402/core/http";
import { ExactEvmScheme } from "@x402/evm";

const url = "https://sentiment-api.kytona.com/v2/snapshot/global";

const challenge = await fetch(url);
if (challenge.status !== 402) throw new Error(`Expected 402, got ${challenge.status}`);

let requirements: any = null;
try {
  requirements = await challenge.json();
} catch {
  // Some clients/proxies strip bodies; fall back to decoding the header.
}
if (!requirements?.accepts?.length) {
  const header = challenge.headers.get("PAYMENT-REQUIRED");
  if (!header) throw new Error("Missing PAYMENT-REQUIRED header");
  requirements = decodePaymentRequiredHeader(header);
}

const scheme = new ExactEvmScheme({
  privateKey: process.env.EVM_PRIVATE_KEY!,
  network: "eip155:8453", // Base mainnet
});
const { encodedSignature } = await scheme.sign(requirements);

const paid = await fetch(url, {
  headers: { "PAYMENT-SIGNATURE": encodedSignature },
});
if (!paid.ok) throw new Error(`Paid request failed: ${paid.status} ${await paid.text()}`);

const data = await paid.json();
console.log(data.cryptoPulse.moodIndex);

Solana/SVM (v2 only)

3) Make it cheaper to run (compact trading format)

For trading/bot loops, request the compact payload:

Troubleshooting

  • 400 INVALID_FORMAT: format only supports compact_trading (omit format for the full response).

  • 400 INVALID_COMPACT_FIELDS: use the allowlist shown in Endpoints.

  • 402 even after paying: ensure you are using the v2 header name PAYMENT-SIGNATURE and that you signed the same requirements you were challenged with.

  • 429 RATE_LIMITED: back off and retry after the retry_after value.

Last updated