Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.prudra.dev/llms.txt

Use this file to discover all available pages before exploring further.

Agent quickstart

This guide makes a paid API call using the x402 protocol in stub mode — no real USDC required.

Prerequisites

  • A Prudra API key (prv_test_sk_...)
  • Node.js with @prudra/payments and ethers installed
  • A running Prudra-protected server (use example-01 or your own)

Step 1: Start a server with PAYMENT_STUB_MODE

PRUDRA_API_KEY=prv_test_sk_... \
PAYMENT_STUB_MODE=true \
npx tsx example-01-basic-paywall.ts
# Server running on :4001
With PAYMENT_STUB_MODE=true, the server accepts any payment signature — you don’t need real USDC.

Step 2: Make the first request (expect 402)

curl -X POST http://localhost:4001/summarise \
  -H "Content-Type: application/json" \
  -d '{"text": "Summarise this"}'
You receive a 402 with the challenge headers:
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: <base64-encoded challenge>
WWW-Authenticate: Payment realm="..." id="..." request="..." expires="..."

Step 3: Pay and retry (TypeScript)

import { ethers } from 'ethers';
import {
  signX402Payment,
  decodePaymentRequirements,
  selectPaymentOption,
} from '@prudra/payments';

const agentWallet = new ethers.Wallet(
  '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
  // ↑ test-only private key — never use in production
);

// Step 1: Hit endpoint, get 402
const r1 = await fetch('http://localhost:4001/summarise', {
  method:  'POST',
  headers: { 'Content-Type': 'application/json' },
  body:    JSON.stringify({ text: 'Summarise this' }),
});
// r1.status === 402

// Step 2: Decode challenge and sign
const requirements = decodePaymentRequirements(r1.headers.get('payment-required')!);
const option = selectPaymentOption(requirements, 'USDC');
const { xPaymentHeader } = await signX402Payment(agentWallet, option);

// Step 3: Retry with signature
const r2 = await fetch('http://localhost:4001/summarise', {
  method:  'POST',
  headers: {
    'Content-Type':    'application/json',
    'PAYMENT-SIGNATURE': xPaymentHeader,
  },
  body: JSON.stringify({ text: 'Summarise this' }),
});
// r2.status === 200

const result = await r2.json();
console.log('Vault ID:', result.vaultId);
console.log('Result:', result);

What you get back

{
  "vaultId": "vlt_clx1abc123",
  "summary": "This is a summary...",
  "payment": {
    "protocol": "x402",
    "txHash":   "0xabc...",
    "amount":   "0.01"
  }
}
The vaultId gives you access to the full vault contents — documents and files generated by the server.

Next steps