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.

Handle the payment response

After a successful x402 payment, Prudra adds a PAYMENT-RESPONSE header to the 200 response. This header contains settlement details encoded as a base64 JSON object. An agent that needs to verify on-chain settlement should read this header.

The PAYMENT-RESPONSE header

The header value is a base64-encoded JSON string:
const paymentResponse = response.headers.get('payment-response');
if (paymentResponse) {
  const settlement = JSON.parse(
    Buffer.from(paymentResponse, 'base64').toString()
  );
  console.log(settlement);
}
Decoded:
{
  "txHash": "0xabc123def456...",
  "settlementPending": false,
  "network": "base-mainnet",
  "paidAt": "2026-04-30T09:00:00.000Z"
}

Response fields

FieldTypeDescription
txHashstringThe on-chain transaction hash. Verify on a Base block explorer.
settlementPendingbooleantrue if the on-chain transaction hasn’t been submitted yet. false if confirmed.
networkstringThe chain where settlement occurred (e.g. "base-mainnet")
paidAtstringISO timestamp when the payment was verified by Prudra

Settlement timing

x402 settlement is asynchronous. Prudra verifies the ERC-3009 signature before your handler runs, but the on-chain transaction submission happens after the response is sent. Typical flow:
  1. Agent sends PAYMENT-SIGNATURE
  2. Prudra verifies signature (milliseconds)
  3. Your handler runs
  4. Prudra returns 200 with PAYMENT-RESPONSE header (settlementPending: true initially)
  5. Prudra submits ERC-3009 authorization to Base (seconds later)
  6. Transaction confirms on Base (~2 seconds)
  7. txHash is now verifiable on-chain
In most cases, settlementPending is already false by the time the agent reads the response, because Prudra starts settlement immediately after verification.

If settlement fails

If the on-chain transaction fails (rare — this can happen if the authorization expired before submission or gas estimation failed):
  • The Payment record in Prudra’s database still exists (the signature was valid)
  • Prudra’s operations team is automatically notified
  • The vault and work output are unaffected
  • Contact support@prudra.com with the txHash for investigation
For the agent, this is indistinguishable from a pending settlement. The work is complete and the vault is accessible regardless.

Reading the response in the full flow

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

const agentWallet = new ethers.Wallet(process.env.AGENT_PRIVATE_KEY!);

// 1. Get 402 challenge
const r1 = await fetch('https://your-api.com/analyse', { method: 'POST', ... });
// r1.status === 402

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

const r2 = await fetch('https://your-api.com/analyse', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'PAYMENT-SIGNATURE': xPaymentHeader },
  body: JSON.stringify({ text: 'analyse this' }),
});
// r2.status === 200

// 3. Read the result
const result = await r2.json();
console.log('Vault ID:', result.vaultId);

// 4. Read settlement details
const paymentResponseHeader = r2.headers.get('payment-response');
if (paymentResponseHeader) {
  const settlement = JSON.parse(Buffer.from(paymentResponseHeader, 'base64').toString());
  
  if (settlement.settlementPending) {
    console.log('Settlement in progress — txHash will be confirmed shortly');
  } else {
    console.log('Settled on-chain:', settlement.txHash);
  }
}