Skip to main content
Learn how to access x402-protected content on Pinata.

Overview

When attempting to access x402-protected content without a payment payload, the gateway returns payment requirements. After making a payment, requesters receive a payment proof that grants access to the content.

The Payment Flow

The content creator provides their dedicated Pinata gateway URL. Replace your-gateway.mypinata.cloud in examples with the actual gateway domain provided.

Step 1: Request the Content

Make a GET request to the x402 gateway URL:
curl https://your-gateway.mypinata.cloud/x402/cid/bafkreih...

Step 2: Receive Payment Requirements (402 Response)

The gateway returns HTTP 402 with payment details:
{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "10000",
      "resource": "https://your-gateway.mypinata.cloud/x402/cid/bafkreih...",
      "description": "Access fee",
      "mimeType": "application/json",
      "payTo": "0x6135561038E7C676473431842e586C8248276AED",
      "maxTimeoutSeconds": 60,
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "extra": {
        "name": "USD Coin",
        "version": "2"
      }
    }
  ],
  "error": "Provide a valid X-Payment header to access this content"
}
Key Fields:
  • network: Blockchain network (e.g., base)
  • asset: Token contract address (USDC on Base)
  • payTo: Recipient wallet address (content creator receives payment here)
  • maxAmountRequired: Payment amount in smallest unit (e.g., 10000 = 0.01 USDC)

Step 3: Access Content with Payment Proof

After successful payment, include the X-Payment header in the request:
curl https://your-gateway.mypinata.cloud/x402/cid/bafkreih... \
  -H "X-Payment: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3..."
The gateway will:
  1. Validate the X-Payment header
  2. Verify the payment proof
  3. Check that amount, recipient, and network match
  4. Serve the private content
Successful Response:
HTTP/200 OK
Content-Type: application/json

{
  "your": "content"
}

Using x402 Libraries

The x402 protocol has client libraries that automate the payment flow. First, set up your wallet:

Setting Up Your Wallet

The x402 libraries require a Viem account or Coinbase Developer Platform wallet:

Option 1: Viem Local Account

import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");

Option 2: Coinbase CDP Wallet

import { Coinbase, Wallet } from "@coinbase/coinbase-sdk";

const coinbase = new Coinbase({
  apiKeyName: "YOUR_API_KEY_NAME",
  privateKey: "YOUR_PRIVATE_KEY",
});

const wallet = await Wallet.create();
const account = await wallet.getDefaultAddress();

Using the Libraries

Once you have your wallet set up, use the x402 libraries to access paid content:

x402-fetch

import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";

// Set up your wallet
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const fetchWithPayment = wrapFetchWithPayment(fetch, account);

// Automatically handles 402 response and payment
const response = await fetchWithPayment(
  "https://your-gateway.mypinata.cloud/x402/cid/bafkreih..."
);

const content = await response.json();
console.log(content);

x402-axios

import { wrapAxiosWithPayment } from "x402-axios";
import axios from "axios";
import { privateKeyToAccount } from "viem/accounts";

// Set up your wallet
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const axiosWithPayment = wrapAxiosWithPayment(axios, account);

// Automatically handles 402 response and payment
const response = await axiosWithPayment.get(
  "https://your-gateway.mypinata.cloud/x402/cid/bafkreih..."
);

console.log(response.data);

Technical Details (Optional)

Pinata uses Coinbase Facilitator to process x402 payments, which provides access to Coinbase’s Discovery Bazaar network for broader content discovery.

Understanding Payment Amounts

USDC uses 6 decimals, so amounts use the token’s smallest unit:
USD AmountmaxAmountRequiredCalculation
$0.0110000$0.01 × 1,000,000
$0.10100000$0.10 × 1,000,000
$1.001000000$1.00 × 1,000,000
$10.0010000000$10.00 × 1,000,000
Formula: USD Amount × 1,000,000 = token amount

Error Handling

402 Payment Required

Payment has not been made yet. Follow the payment flow above.

403 Forbidden

Payment proof is invalid or expired. Make a new payment.

404 Not Found

The CID doesn’t exist or isn’t attached to a payment instruction.

500 Internal Server Error

Gateway or facilitator error. Contact the content creator.

Network Support

NetworkStatusTokenUse Case
Base (Mainnet)✅ AvailableUSDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)Production
Base Sepolia (Testnet)✅ AvailableUSDC (0x036CbD53842c5426634e7929541eC2318f3dCF7e)Testing

Best Practices

  1. Handle 402 responses gracefully: Display payment requirements clearly
  2. Use the x402 libraries: They handle the complex payment flow automatically
  3. Test on Base Sepolia first: Verify integration before using mainnet
  4. Store payment proofs: If accessing content multiple times (check expiry)
  5. Monitor USDC balance: Ensure sufficient funds for payments

Example: Complete Integration

import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";

// Set up your wallet
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);

// Access paid content
async function accessPaidContent(cid: string) {
  try {
    const url = `https://your-gateway.mypinata.cloud/x402/cid/${cid}`;

    const response = await fetchWithPayment(url);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const content = await response.json();
    console.log("Content accessed successfully:", content);

    return content;
  } catch (error) {
    console.error("Failed to access content:", error);
    throw error;
  }
}

// Usage
accessPaidContent("bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4");

Resources

Support

Need help accessing paid content? Contact the content creator or reach out to [email protected].