TransX402 Docs
Onboarding

Sandbox

Complete guide to testing in the TransX402 sandbox environment — fund wallets, make test payments, and validate your integration.

What is the Sandbox?

The sandbox is a testing environment that lets you test your TransX402 integration without using real money. By default it targets CAMP Testnet — a public testnet chain (https://testnet-rpc.onchainfolio.com/rpc) with test IDRX and Permit2. The facilitator sponsors settle gas; merchants fund wallets with test IDRX and ETH via the treasury faucet (/sandbox/fund).

Optional: run a local Anvil Base fork with SANDBOX_FUNDING_MODE=anvil and docker compose --profile anvil up (developer tooling only — not the default).

npm packages require Node.js 20.19+ (^20.19.0 || ^22.13.0 || >=24). Browser Path 4 needs MetaMask (or another EIP-1193 wallet) plus test ETH for the first Permit2 approve.

Sandbox vs Production

AspectSandbox (CAMP Testnet)Production
Secret key prefixipk_sandbox_ipk_live_
Publishable key prefixipk_pub_sandbox_ipk_pub_live_
ChainCAMP TestnetBase mainnet
IDRXTest IDRX on CAMPReal IDRX
Gas (settle)Sponsored by facilitatorSponsored by facilitator
FundingTreasury faucetReal deposits
DashboardShows sandbox transactionsShows real transactions
WebhooksFires to merchant's webhook URLSame
Facilitator (hosted)api.transx402.comapi.transx402.com

Getting Started

1. Get a Sandbox API Key

When you register at dashboard.transx402.com, a secret sandbox API key is automatically created. You can also create additional sandbox keys (secret or publishable) on the API Keys page:

ipk_sandbox_abc123def456...

Keep secret keys on the server / in WordPress. CDN paywalls need a publishable ipk_pub_sandbox_... key and Allowed Origins.

2. Fund a Test Wallet

Before making test payments, fund a wallet with test IDRX (and ETH for gas on browser Path 4). There are two ways:

Via Dashboard

Go to the Sandbox page in the dashboard. Use the Fund IDRX and Fund ETH cards (amounts go to your registered merchant wallet), then click the fund button on each card.

On CAMP Testnet (treasury funding), the faucet can transfer both test IDRX and native ETH. The first browser payment may prompt a MetaMask Spending Cap (approve Permit2); later payments are signature-only.

Via API

IDRX:

curl -X POST https://api.transx402.com/sandbox/fund \
  -H "X-API-Key: ipk_sandbox_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xYourWalletAddress...",
    "amount": "10000"
  }'

ETH (optional token — omit for IDRX):

curl -X POST https://api.transx402.com/sandbox/fund \
  -H "X-API-Key: ipk_sandbox_abc123..." \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xYourWalletAddress...",
    "amount": "0.01",
    "token": "ETH"
  }'

Response:

{
  "txHash": "0x...",
  "address": "0xYourWalletAddress...",
  "amount": "0.01",
  "token": "ETH",
  "balance": "10000000000000000"
}

Use a secret sandbox key on /sandbox/fund. Fund the payer wallet (the MetaMask account that will pay), not only the merchant wallet.

Testing Payments

Basic Testing Flow

  1. Install integration — follow the Quickstart recipe for Next.js, WordPress, or CDN
  2. Fund wallet — fill the payer wallet with IDRX (and ETH) via the Dashboard Sandbox page or /sandbox/fund
  3. Access content — open the paywalled page or call client.fetch("/api/premium")
  4. Pay — click "Pay with IDRX", connect MetaMask on CAMP Testnet, and sign
  5. Verify — check the payment in the dashboard or via the /payments API

Testing with the JS Library (server settlement)

import { createBrowserClient } from "@transx402/client/browser";
 
// No browser API key. Merchant backend settles via @transx402/server.
const client = createBrowserClient({
  environment: "camp", // "local" | "camp" | "base"
  settlement: "server",
  configProxyPath: "/api/transx402", // GET /api/transx402/config
});
 
const response = await client.fetch("/api/premium");

You may also set facilitatorUrl to override the preset host; the config section still follows environment. Server constructors require environment and/or facilitatorUrl. Chain params come only from GET /config (or your config proxy).

environmentFacilitatorNotes
localhttp://localhost:3402Docker / local API
camphttps://api.transx402.comHosted CAMP testnet sandbox
basehttps://api.transx402.comRequires ipk_live_... on the server

Browser wallets use Path 4: one-time on-chain Permit2 approve (user pays gas), then signature-only payments. Agents use Path 3 (createAgentClient) with sponsored approve via signTransaction — MetaMask cannot do Path 3.

CDN paywall uses the browser bundle: TransX402.paywall({ apiKey: "ipk_pub_sandbox_...", environment: "camp", ... }). WordPress does not use the CDN; it bundles the client and settles in PHP.

Testing with cURL

# 1. Check health
curl https://api.transx402.com/health
 
# 2. Public chain / token config (no API key)
curl https://api.transx402.com/config
 
# 3. Fund test wallet
curl -X POST https://api.transx402.com/sandbox/fund \
  -H "X-API-Key: ipk_sandbox_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"address": "0xTestWallet", "amount": "10000"}'
 
# 4. Check payments
curl https://api.transx402.com/payments \
  -H "X-API-Key: ipk_sandbox_abc123..."

amount on /sandbox/fund for IDRX is whole IDRX (same as whole IDR). Default cap is 100000 per request — do not send "1000000". Payment records from GET /payments use 2-decimal base units (Rp 5,000 → "500000").

Differences from Production

Your integration code is the same for sandbox and production. Swap key family and environment:

// Sandbox / CAMP — server settlement (browser)
const sandbox = createBrowserClient({
  environment: "camp",
  settlement: "server",
  configProxyPath: "/api/transx402",
});
 
// Production / Base — same, with server env TRANSX402_API_KEY=ipk_live_...
const live = createBrowserClient({
  environment: "base",
  settlement: "server",
  configProxyPath: "/api/transx402",
});

CDN paywall: ipk_pub_sandbox_ + environment: "camp" → ipk_pub_live_ + environment: "base".

Local Development with Anvil (optional)

Anvil is not the default sandbox. Use it only when you want an offline Base fork:

# In .env:
# SANDBOX_FUNDING_MODE=anvil
# SANDBOX_RPC_URL=http://host.docker.internal:8546   # or host-mapped Anvil
 
docker compose --profile anvil up -d

Anvil listens on port 8546 locally. /sandbox/wallets and /sandbox/reset work only in Anvil mode.

Built-in Anvil test wallets

curl http://localhost:3402/sandbox/wallets \
  -H "X-API-Key: ipk_sandbox_abc123..."

These are Anvil's deterministic accounts. Private keys only work on the Anvil chain.

Reset Anvil

curl -X POST http://localhost:3402/sandbox/reset \
  -H "X-API-Key: ipk_sandbox_abc123..."

This re-forks Anvil from the latest Base mainnet block. All previous Anvil sandbox transactions are lost; IDRX and Permit2 contracts remain available. Do not call reset against hosted CAMP Testnet expecting a chain re-fork.

Why Anvil Fork (optional)?

Anvil ForkCAMP Testnet (default)
Real IDRX contractYes (forked Base state)Deployed test IDRX
Real Permit2 contractYesPrefer canonical 0x0000…BA3
Shared with teamNo (local)Yes
Fundinganvil_deal + auto Permit2 approveTreasury ERC-20 transfer
CI / offlineGood after forkNeeds RPC reachability

Testing Tips

  1. Always test in sandbox first before switching to production
  2. Use webhooks to verify payment notifications are sent correctly
  3. Test error scenarios — insufficient balance, missing Permit2 approval
  4. Check the dashboard — payments should appear on the Payments page
  5. Wallet — MetaMask (EIP-1193). The client does not include WalletConnect or Coinbase Wallet SDKs