Overview
This guide shows how to use Magic’s Express Server Wallet to pay for x402-protected API endpoints. x402 is an open payment protocol by Coinbase that uses the HTTP402 Payment Required status code to enable instant, gasless stablecoin payments over HTTP. Your server signs the payment via the TEE and the x402 facilitator handles settlement — the private key never leaves the TEE.
Prerequisites
Before starting, ensure you have:- A Magic Secret Key — from your Magic Dashboard
- An OIDC Provider ID — configured for your auth provider (setup guide)
- A user JWT from your authentication provider
- USDC on Base Sepolia in the user’s wallet (for testing)
How It Works
- Your server authenticates the user and obtains a JWT
- JWT is sent to Magic’s TEE to get (or create) the user’s EOA
- Your server makes a request to an x402-protected endpoint
- The server responds with HTTP 402 and payment requirements
- The x402 client signs a gasless USDC transfer (EIP-3009) via the TEE
- The request is retried with the payment signature
- A facilitator settles the payment on-chain
x402 payments are gasless for the payer. The protocol uses EIP-3009
transferWithAuthorization, which means only a typed data signature is needed — no ETH required for gas. The facilitator submits the on-chain transaction.TEE Request Helper
All TEE calls use the same authentication headers. Create a reusable helper for your server-side code.TypeScript
Get or Create a Wallet
Fetch the user’s wallet address. If one doesn’t exist, it will be created automatically.TypeScript
Creating a TEE-Backed Account
The x402 SDK expects a viemAccount object that can sign typed data. Create a custom account that delegates signing to the TEE.
TypeScript
Setting Up the x402 Client
Register the TEE-backed account with the x402 client and create a payment-enabled fetch wrapper.TypeScript
Making Paid Requests
UsefetchWithPayment just like the regular fetch API. If the server responds with 402, the x402 client automatically handles the payment flow via the TEE.
TypeScript
- Receives the 402 response with payment requirements
- Signs a gasless USDC transfer via the TEE
- Retries the request with the payment signature in the header
- Returns the successful response
Setting Up a Test Server
To test the payment flow, set up a simple Express server that requires x402 payment.TypeScript
The testnet facilitator at
https://x402.org/facilitator requires no API keys or signup. For production, switch to the Coinbase CDP facilitator with network eip155:8453 (Base mainnet).Switching to Production
To move from testnet to mainnet, update the network and facilitator:TypeScript
Key Dependencies
| Package | Purpose |
|---|---|
viem | Ethereum client, account utilities, and typed data hashing |
@x402/fetch | Wraps fetch with automatic x402 payment handling |
@x402/evm | EVM payment scheme for x402 |
@x402/core | Core x402 client and server utilities |
@x402/express | Express middleware for x402-protected endpoints |
TEE Endpoints Used
| Endpoint | Purpose |
|---|---|
POST /v1/wallet | Get or create an EOA wallet |
POST /v1/wallet/sign/data | Sign a raw data hash (EIP-712 typed data hash) |
Troubleshooting
TEE returns 401 or 403
TEE returns 401 or 403
Symptoms: Authentication errors when calling TEE endpoints.Solutions:
- Verify the JWT token is valid and not expired
- Check that
X-Magic-Secret-Keymatches your dashboard credentials - Ensure the OIDC Provider ID is correct
- Confirm your domain is allowlisted in the Magic Dashboard
Payment signature rejected
Payment signature rejected
Symptoms: The facilitator rejects the payment signature.Solutions:
- Ensure the wallet has sufficient USDC on the correct network (Base Sepolia for testing, Base mainnet for production)
- Verify the TEE is signing the correct EIP-712 hash
- Check that the
signHashViaTeefunction is correctly reconstructing the signature from r, s, v components
402 response not handled
402 response not handled
Symptoms: The fetch call returns a raw 402 response instead of automatically paying.Solutions:
- Make sure you’re using
fetchWithPayment(the wrapped version), not the nativefetch - Verify the x402 client has a scheme registered for the server’s network
- Check that
ExactEvmSchemeis imported from@x402/evm/exact/client(not/server)
Wrong network error
Wrong network error
Symptoms: Payment fails with a network mismatch error.Solutions:
- Use
eip155:84532for Base Sepolia oreip155:8453for Base mainnet - The client scheme must match the network the server is requesting payment on
Resources
Express API Docs
Learn about Magic’s Express Server Wallet API
x402 Documentation
Official x402 protocol documentation
x402 GitHub
Reference implementations and examples
x402 Foundation
Protocol specification and facilitator info