Skip to main content

Frequently Asked Questions

Quick answers to common questions about x402 escrow payments.

Costs & Fees

How much gas does this cost?

Users pay $0 in gas. The system uses ERC-3009 transferWithAuthorization signatures, which are completely gasless for users.
WhoGas Cost
User (Payer)$0 - only signs messages
API Provider$0 - facilitator covers everything
Facilitator~$0.01-0.05 per session (covered by facilitator)
This is one of the main benefits of x402 escrow - users never need ETH for gas.

Is there a fee on top of payments?

All fees are currently sponsored by Agentokratia. We cover gas costs and charge no platform fee. Any future fee changes will be announced well in advance.

What’s the minimum I can charge per request?

Technically 0.0001USDC(1/100thofacent).However,werecommend0.0001 USDC (1/100th of a cent). However, we recommend 0.001+ for practical pricing.

Tokens & Networks

Can I use this with other tokens besides USDC?

Currently, USDC only. USDC was chosen because:
  • Stable value (no price volatility)
  • Widely held and understood
  • Native support for gasless transfers (ERC-3009)
  • Available on Base with high liquidity
Other stablecoins may be supported in the future.

Which networks are supported?

NetworkChain IDStatus
Base Sepolia84532Live (Testnet)
Base Mainnet8453Coming Soon
We chose Base for its low gas costs and Coinbase ecosystem integration.

Can I use this on Ethereum mainnet?

Not currently. Ethereum mainnet gas costs would make small payments impractical. Base offers the same security with ~100x lower fees.

Security & Reliability

What if the facilitator goes down?

Your funds are safe. User deposits are held in the on-chain escrow smart contract, not by the facilitator. If the facilitator is unavailable:
  1. No new sessions can be created
  2. Existing session charges won’t be captured
  3. Users can call reclaim() directly on the contract after authorizationExpiry
  4. API providers can implement fallback logic (serve for free, use cached responses, etc.)
// Server-side fallback during outage
x402.onError(async (ctx, error) => {
  if (error.status === 503) {
    // Facilitator down - decide how to handle
    console.log('Facilitator unavailable, serving request for free');
    return { proceed: true }; // Continue without payment
  }
});

What if I accidentally double-charge a user?

Impossible by design. Each request includes a unique requestId (UUID). The facilitator enforces idempotency - the same requestId can only be charged once.
// These two calls charge only once
await escrowFetch(url, { requestId: 'request-123' });
await escrowFetch(url, { requestId: 'request-123' }); // No additional charge

Can users dispute or chargeback payments?

No chargebacks. Unlike credit cards, cryptocurrency payments are final. The session token serves as cryptographic proof that the user authorized the payment. This is actually a benefit for API providers - no chargeback fraud risk.

Is the escrow contract audited?

The escrow contract is built on Base’s Commerce Payments Protocol, a production-grade payment infrastructure:
  • Open source: View the smart contract on GitHub
  • ERC-3009: Gasless approvals via transferWithAuthorization
  • Time-locked: Explicit authorization windows with enforced expiry
  • Battle-tested: Based on patterns used in traditional payment processing
Formal audit documentation will be published before mainnet launch.

Sessions & Payments

How long do sessions last?

Default is 1 hour, configurable up to 24 hours:
const { fetch: escrowFetch } = createEscrowFetch(walletClient, {
  sessionDuration: 7200, // 2 hours
});
After expiry, users can reclaim unused funds.

What happens to unused funds?

Users get 100% of unused funds back. After authorizationExpiry:
  1. User (or anyone) can call reclaim() on the contract
  2. Remaining balance returns to user’s wallet
  3. Facilitator captures any pending charges first

Can I refund a user?

There are two types of “getting money back”:
TypeWhat it isHow
ReclaimUnused balance (never captured)User calls reclaim() on contract
RefundAlready-captured funds🔜 Coming soon via API
Currently:
  • Users automatically reclaim unused session balance via contract
  • Refund API coming soon
See Refund vs Reclaim for details.

What if a user’s session runs out of balance mid-request?

The request will fail with insufficient_balance. Handle it gracefully:
const response = await escrowFetch(url);
if (!response.ok) {
  const { reason } = await response.json();
  if (reason === 'insufficient_balance') {
    // Prompt user to create new session with more funds
    await escrowFetch(url, { session: 'new' });
  }
}

Integration

Do I need an API key?

Servers: Yes, to authenticate with the facilitator for verification and settlement. Clients: No, clients just need a wallet to sign sessions. Get your API key at facilitator.agentokratia.com.

Does this work with React/Next.js/Vue/etc?

Yes! The SDK is framework-agnostic. It works with any JavaScript environment that has:
  • A wallet connection (viem WalletClient)
  • Fetch API (or polyfill)
See our React example for integration patterns.

Can I use this server-side (Node.js)?

For protecting APIs: Yes, the server SDK works in any Node.js environment. For making payments as a client: You’d need a wallet with a private key. Not recommended for servers due to security implications of storing private keys.

How do I test without real money?

Use Base Sepolia testnet:
  1. Get your API key from facilitator.agentokratia.com (same key works on all networks)
  2. Get testnet USDC from a faucet
  3. Configure your app for Sepolia:
import { baseSepolia } from 'viem/chains';

const walletClient = createWalletClient({
  chain: baseSepolia,
  transport: http(),
});

Troubleshooting

Why am I getting “User rejected” errors?

The user clicked “Reject” in their wallet’s signature prompt. This is expected behavior when users cancel. Handle it gracefully:
try {
  await escrowFetch(url);
} catch (err) {
  if (err.message?.includes('User rejected')) {
    showToast('Transaction cancelled');
    return;
  }
  throw err;
}

Why is my session expired immediately?

Check that your system clock is accurate. Session expiry is based on Unix timestamps. If your clock is significantly off, sessions may appear expired.

How do I debug payment issues?

Enable logging with hooks:
const { fetch: escrowFetch, x402 } = createEscrowFetch(walletClient);

x402.onBeforePaymentCreation(async (ctx) => {
  console.log('[x402] Payment required:', ctx.paymentRequirements);
});

x402.onAfterPaymentCreation(async (ctx) => {
  console.log('[x402] Payment created:', ctx.paymentPayload);
});

Still Have Questions?