Authored by: Chris Wajule and Simon Goldberg
This solution demonstrates pay-per-use AI content generation using the x402 payment protocol. Users pay with USDC on Base Sepolia to access Amazon Nova 2 Lite for text and Amazon Nova Canvas for image generation. Two payment architectures are included: the serverless flow where users sign payments via browser wallets, and the agentic flow using the Strands agent powered by Amazon Bedrock AgentCore with CDP AgentKit, both utilizing the x402.org facilitator to verify signatures and settle payments on-chain via EIP-3009 transferWithAuthorization.
- Architecture
- Architecture Comparison
- Deployment
- Using the Platform
- API Reference
- Development and Testing
- Clean Up
- Troubleshooting
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2, 5, 12), Payment Processing (green arrows, steps 3-4, 6, 7-9), and Content Delivery (orange arrows, steps 10-11).
The numbers in the following flow correspond to the serverless stablecoin payment for AI-generated content:
-
Wallet Connection: The user clicks the wallet connect button in the React frontend. The application uses Reown AppKit to display available wallet options. The user selects their wallet and approves the connection request.
-
Initial Request: The user submits a prompt through the chat interface. The application sends a POST request to the
/generateendpoint on Amazon API Gateway without payment credentials. -
Cost Estimation: The Estimator Lambda function uses Amazon Bedrock
CountTokensAPI to calculate input tokens. It estimates output tokens using a conservative formula (minimum 800 tokens with 20% safety margin) and applies Amazon Nova 2 Lite pricing ($0.0003 input, $0.0025 output per 1K tokens). Amazon Nova Canvas returns a fixed $0.04 per image. -
Payment Requirements: The Seller Lambda function detects the missing
PAYMENT-SIGNATUREheader and returnsHTTP 402. The response includes the USDC amount in wei, the seller wallet address, the USDC contract address on Base Sepolia, andEIP-712domain parameters. -
Payment Authorization: The frontend is hosted on AWS Amplify and displays a payment modal with the cost preview. The user confirms and the application generates an
EIP-712typed data signature using the connected wallet. The wallet prompts the user to sign the message. The signature authorizes the USDC transfer with validity timestamps and a unique nonce. -
Payment Submission: The frontend retries the
/generaterequest with theEIP-712signature in thePAYMENT-SIGNATUREheader. The request includes the authorization object (from, to, value, validAfter, validBefore, nonce) and signature. -
Idempotency Check: The Seller Lambda extracts the nonce and checks an in-memory cache to prevent replay attacks. If the nonce exists, it returns
HTTP 409. -
Payment Verification: The AWS Lambda function sends the payment payload to the x402.org facilitator's
/verifyendpoint. The facilitator validates theEIP-712signature against the USDC contract domain on Base Sepolia. -
Payment Settlement: The Lambda calls the facilitator's
/settleendpoint. The facilitator executes the USDC transfer on-chain usingEIP-3009 transferWithAuthorizationand returns the transaction hash. -
Content Generation: The AWS Lambda function invokes the Bedrock Lambda function. For text, it calls Amazon Nova 2 Lite using the
invoke_modelAPI. For images, it invokes Amazon Nova Canvas. -
Response Delivery: The Bedrock Lambda returns the generated content. The Seller Lambda constructs a response with the success message, transaction url (
https://sepolia.basescan.org/tx/{hash}), and generated content. -
Frontend Display: The application displays the payment confirmation, transaction hash, and AI-generated content in the chat interface.
The solution includes three main components: Request Initiation (salmon arrows, steps 1-2), Payment Processing (green arrows, steps 4-11), and Content Delivery (orange arrows, steps 3, 12-14).
The numbers in the following flow correspond to an autonomous agent executing stablecoin payments for AI-generated content:
-
WebSocket Connection: The user connects to the Amazon API Gateway WebSocket endpoint. The Connect Lambda stores the connection ID in Amazon DynamoDB.
-
User Request: The user sends a prompt with a session ID via a WebSocket connection. The Agent Lambda forwards the request to Amazon Bedrock AgentCore Runtime
/invocationsendpoint. The request includes a session ID for isolation. -
Agent Initialization: Amazon Bedrock AgentCore loads the agent configuration and initializes Amazon Bedrock AgentCore Memory for session storage. The agent using Anthropic Claude Sonnet 4.5 as the reasoning engine, receives the prompt and determines the required action.
-
Cost Estimation: The agent invokes the
estimate_image_costtool. The tool calculates the fixed cost ($0.04 USDC for1024x1024standard quality) and generates a unique request ID. The cost, prompt, and authorization status (auth: false) are stored in Amazon Bedrock AgentCore Memory. -
Authorization Check: The agent calls
generate_imagetool. The tool checks the authorization status in session storage and findsauth:false. The tool returnsAUTHORIZE_CHECKstatus directly to the agent without calling the gateway. This confirms user intent to pay and is not part of the x402 flow. The check is automatic but can be an explicit natural language confirmation corresponding to an CDP AgentKit walletβs allowance. -
Payment Authorization: The agent calls
make_payment. The tool verifies sufficient balance exists and setsauth:truein session storage. This marks the user's intent to proceed with payment but does not transfer funds -
Initial x402 Request: The agent calls
generate_imageagain. The tool findsauth:trueand creates an x402 HTTP client using the CDP AgentKit wallet's dynamically exported private key. The client sends a POST request to Amazon API Gateway without anPAYMENT-SIGNATUREheader. -
402 Payment Required: AWS Lambda receives the request and returns
HTTP 402with payment requirements. The response includes the USDC amount in wei, seller wallet address, USDC contract address, andEIP-712domain parameters (name: 'USDC', version: '2', chainId: 84532). -
EIP-712 Signature Generation: The x402 client receives the 402 response and constructs
EIP-712typed data. It signs the data using the CDP AgentKit wallet'sprivate key, base64-encodes the signature payload, and retries the POST request with the signature in thePAYMENT-SIGNATUREheader. -
Payment Verification: Lambda extracts the payment payload from the
PAYMENT-SIGNATUREheader. It checks the nonce against theprocessedPaymentsmap to prevent replay attacks. Lambda sends the signature to the x402.org facilitator's/verifyendpoint, which validates theEIP-712signature against the USDC contract domain on Base Sepolia. -
Payment Settlement: AWS Lambda calls the facilitator's
/settleendpoint. The facilitator executes the USDC transfer on Base Sepolia usingEIP-3009 transferWithAuthorizationand returns the transaction hash. Lambda stores the hash in context, marks the nonce as processed, and returnsHTTP 200with payment confirmation. -
Image Generation: The tool invokes Amazon Nova Canvas model using the
invoke_modelAPI. Nova Canvas generates a1024x1024image based on the prompt. -
Response Delivery: The generated image is stored in Amazon Simple Storage Service , and its unique ID is stored in session storage. The agent returns a success message to the frontend hosted an AWS Amplifywhich includes the base64-encoded image, transaction hash, and a BaseScan explorer link(
https://sepolia.basescan.org/tx/{hash}) for on-chain verification. -
Session Cleanup: The tool clears the current request ID from session storage. This allows new image generation requests while maintaining payment history for the session.
Serverless handles simple, transactional interactions. Users know what they want, need a single piece of content, and prefer explicit control over each payment.
Agentic targets complex, exploratory workflows. Users describe goals in natural language, iterate on content through conversation, or delegate payment decisions within spending limits.
Serverless returns images directly in HTTP response bodies. For small images or when clients handle base64 encoding, this provides the simplest implementation.
Agentic offloads images to Amazon S3 due to WebSocket message size constraints. This adds complexity but enables handling large media files. Presigned URLs provide secure, temporary access.
Serverless implements pay-per-request semantics. Each API call requires separate payment authorization. Users explicitly approve every transaction.
Agentic implements pay-per-session semantics. Users authorize a session budget. The agent manages spending within that limit across multiple operations.
Serverless uses synchronous HTTP request-response patterns. Each request is independent and expects a single response.
Agentic uses asynchronous WebSocket bidirectional streaming. Connections persist across multiple message exchanges. This enables server-initiated messages and incremental response delivery.
Serverless is stateless. AWS Lambda functions have no memory of previous requests. Clients maintain all session context.
Agentic maintains session state through Amazon DynamoDB and Amazon Bedrock AgentCore Memory. The agent remembers conversation history, user preferences, and cumulative spending within a session.
Serverless orchestration is explicit and deterministic. The Seller Lambda follows a fixed sequence: check payment, verify authorization, invoke generation, return results.
Agentic orchestration is autonomous and adaptive. Amazon Bedrock AgentCore Runtime decides which tools to invoke based on user intent. The agent handles variations in request structure and adapts to errors.
Serverless scales horizontally without coordination overhead. Amazon API Gateway and AWS Lambda handle thousands of concurrent requests. Cold starts are the primary latency consideration.
Agentic scalability is constrained by WebSocket connection limits and Amazon Bedrock AgentCore Runtime capacity. Connection pooling and lifecycle management become operational concerns.
Serverless incurs cold start latency when AWS Lambda functions initialize. Subsequent requests to warm functions complete quickly.
Agentic maintains warm WebSocket connections, eliminating connection establishment overhead. However, Amazon Bedrock AgentCore Runtime introduces reasoning latency as Claude Sonnet 4.5 analyzes prompts and plans tool invocations.
- AWS Account with appropriate permissions
- Node.js 18.x or later
- AWS CDK CLI installed (
npm install -g aws-cdk) - AWS CLI configured with credentials
- USDC on Base Sepolia for testing (obtain from Circle Faucet)
- WalletConnect Project ID from Reown Cloud
- CDP API credentials from Coinbase Developer Platform
- Bash shell (Windows users: use WSL or Git Bash)
git clone https://github.com/aws-samples/sample-agentic-serverless-payments.gitNote: Lambda dependencies are bundled automatically by esbuild during CDK deployment. No separate
npm installis required in Lambda directories.
Parameters are sourced from .env files during deployment.
Root directory (for serverless and frontend):
cp .env-sample .envUpdate the root .env file with the following values:
| Variable | Source |
|---|---|
VITE_PAYER_WALLETCONNECT_PROJECT_ID |
Reown Cloud |
SELLER_WALLET_ADDRESS |
Your wallet address to receive USDC |
AGENT_RUNTIME_ARN |
AgentCore Runtime ARN (from Step 3) |
Note: API Gateway URLs (
VITE_AWS_API_GATEWAY_HTTP_URL,VITE_AWS_API_GATEWAY_WEBSOCKET_URL,API_GATEWAY_HTTP_URL) are exported automatically from the CDK stack after deployment. CDP credentials (CDP_API_KEY_NAME,CDP_API_KEY_SECRET) are optional and only required for mainnet deployment (code edits required).
Agentic directory (for agent deployment):
cd agentic
cp .env-sample .env
cd ..Update the agentic/.env file with the following values:
| Variable | Source |
|---|---|
CDP_API_KEY_ID |
Coinbase Developer Platform |
CDP_API_KEY_SECRET |
Coinbase Developer Platform |
CDP_WALLET_SECRET |
Generated CDP wallet secret |
NETWORK_ID |
base-sepolia |
RPC_URL |
https://sepolia.base.org |
USDC_CONTRACT |
0x036CbD53842c5426634e7929541eC2318f3dCF7e |
SELLER_WALLET |
Your wallet address to receive USDC |
GATEWAY_URL |
API Gateway HTTP URL (from Step 3, without trailing slash) |
AWS_REGION |
us-east-1 |
Note: When configuring the Coinbase Developer Platform API Key, enable View, Trade, Transfer, and Export & Manage for Server Wallet.
For complete automated setup:
# 1. Make sure you have copied and configured your .env files
# 2. Run the complete setup
npm run setupThis script handles all installation, deployment, and configuration steps automatically.
npm installnpm run setup-serverlessnpm run setup-agenticnpm run devOpen the URL displayed in the terminal (typically http://localhost:5173).
Option A: AWS CLI
npm run setup-amplifyOption B: Amplify Console (Recommended for CI/CD)
- Go to AWS Amplify Console
- Click Deploy an App
- Connect your Git repository and select the branch
- In Build settings, Amplify auto-detects the
amplify.ymlconfiguration - In Hosting settings β Environment variables, add:
| Variable | Value |
|---|---|
VITE_AWS_API_GATEWAY_HTTP_URL |
Your HTTP API URL from CDK outputs |
VITE_AWS_API_GATEWAY_WEBSOCKET_URL |
Your WebSocket URL from CDK outputs |
VITE_PAYER_WALLETCONNECT_PROJECT_ID |
Your WalletConnect Project ID |
- Click Save and deploy
-
Open the application in your browser at the deployed Amplify URL or
http://localhost:5173for local development. -
Select architecture: Click "Serverless" in the top navigation.
-
Select model: Choose "Nova LLM" for text generation or "Nova Canvas" for image generation.
-
Connect wallet: Click the wallet button (π) to open the WalletConnect modal. Select your wallet and approve the connection. Ensure you are on Base Sepolia network.
-
Submit a prompt: Type your request in the chat input and press Enter or click the send button.
-
Review payment: A modal displays the estimated cost in USDC. Click "Confirm" to proceed.
-
Sign transaction: Your wallet prompts you to sign the EIP-712 message. This authorizes the USDC transfer but does not execute it yet.
-
Receive content: After payment verification and settlement, the AI-generated content appears in the chat along with the transaction URL.
-
Open the application and select "Agentic" in the top navigation.
-
Verify connection: The green indicator (π’) confirms WebSocket connection to the agent.
-
Submit a prompt: Type your image generation request and press Enter.
-
Agent processing: The agent autonomously estimates cost, verifies balance, authorizes payment, and generates content.
-
Receive content: The generated image and transaction confirmation appear in the chat.
User: What can you help me with?
Agent: I can help you with several image-related tasks:
π¨ Image Generation
- Create images using Amazon Nova Canvas based on your text descriptions
- Handle the payment process automatically through x402 protocol
π° Wallet Management
- Check your wallet balance (ETH and USDC)
- Estimate costs for image generation before creating them
π Image Analysis
- Analyze generated images for content monetization opportunities
User: What are my wallet details?
Agent: Here are your wallet details:
Wallet Address: 0xxxx...xxxx
Network: Base Sepolia (Chain ID: 84532)
Current Balances:
- ETH: 0.000000
- USDC: 1.000000
Great! You now have 1 USDC in your wallet, which should be sufficient
for generating images using Nova Canvas. You're all set to create some images!
User: Generate an image of a futuristic city at sunset
Agent: π Success! Your futuristic city at sunset image has been generated successfully!
Image Details:
- Image ID: xxxx-xxxx-xxxx-xxxx
- Cost: $0.0400 USD
- Payment verified on Base Sepolia blockchain
- Transaction: View on BaseScan
https://sepolia.basescan.org/tx/0xxxx...xxxx
[Generated Image]
POST /generate
Headers:
Content-Type: application/jsonPAYMENT-SIGNATURE: Base64-encoded payment payload (required for paid requests)
Request Body:
{
"content": "Your prompt text",
"model": "nova-llm" | "nova-canvas",
"architecture": "serverless"
}Response (402 Payment Required):
{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "192",
"payTo": "0x...",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"description": "AI content generation with nova-llm"
}Response (200 Success):
{
"message": "Payment verified - content generated successfully",
"status": "success",
"content": "Generated text or base64 image data",
"model": "nova-llm",
"transactionUrl": "https://sepolia.basescan.org/tx/0x..."
}Connect: wss://{api-id}.execute-api.{region}.amazonaws.com/prod
Message Format:
{
"input": { "prompt": "Your prompt text" },
"session_id": "unique-session-id"
}Response Types:
type: "complete"- Contains generated content and imagestype: "error"- Contains error message
# Start frontend development server
npm run dev
# Build for production
npm run build
# Preview production build
npm run previewcd cdk
# Build TypeScript
npm run build
# Deploy changes
cdk deploy
# View differences before deployment
cdk diffTo avoid incurring charges, delete all deployed resources.
npm run cleanupDelete resources in reverse order of creation:
1. Delete Amplify app (if deployed):
APP_ID=$(aws amplify list-apps --query "apps[?name=='ai-content-monetization'].appId" --output text)
aws amplify delete-app --app-id $APP_ID2. Delete Agentic CDK stack:
cd agentic/cdk && cdk destroy --force && cd ../..3. Delete Serverless CDK stack:
cd serverless && cdk destroy --force && cd ..4. Delete CloudWatch log groups:
for prefix in "/aws/lambda/AiContent" "/aws/lambda/X402" "/aws/codebuild/X402" "/aws/bedrock-agentcore/runtimes/x402_payment_agent"; do
aws logs describe-log-groups --log-group-name-prefix "$prefix" --query 'logGroups[*].logGroupName' --output text | xargs -n1 aws logs delete-log-group --log-group-name 2>/dev/null
done5. Clean up local files:
rm -rf node_modules/ dist/ serverless/node_modules/ serverless/cdk.out/ serverless/outputs.json serverless/lib/*.js serverless/lib/*.d.ts serverless/bin/*.js serverless/bin/*.d.ts agentic/cdk/node_modules/ agentic/cdk/cdk.out/ agentic/lambda/node_modules/-
Wallet Connection Fails:
- Verify WalletConnect Project ID is configured in
.env - Ensure browser wallet extension is installed
- Check that Base Sepolia network is available in your wallet
- Verify WalletConnect Project ID is configured in
-
Payment Verification Fails:
- Confirm sufficient USDC balance on Base Sepolia
- Verify wallet is connected to Base Sepolia network
- Check browser console for detailed error messages
-
CORS Errors:
- Redeploy CDK stack:
cd serverless && cdk deploy - Verify API Gateway URL matches
.envconfiguration
- Redeploy CDK stack:
-
AccessDeniedException for AgentCore Memory:
- Add the AgentCore Memory permissions to the service role (see Step 6.7)
- Verify the MEMORY_ID is correct in your environment variables
-
CDP Wallet Connection Fails:
- Verify CDP_API_KEY_NAME and CDP_API_KEY_SECRET are correct
- Check that CDP_WALLET_SECRET is properly formatted
- Ensure you have USDC on Base Sepolia
-
Docker Build Fails:
- Check CodeBuild logs in AWS Console for build errors
- Verify ECR push permissions are configured (see Step 6.5)
-
WebSocket Connection Issues:
- Check WebSocket URL in
.envmatches CDK output - Verify DynamoDB connections table exists
- Review CloudWatch logs for Lambda errors
- Check WebSocket URL in
-
Content Generation Fails:
- Verify Bedrock model access is enabled in your AWS account
- Check Lambda execution role has Bedrock permissions
- Review CloudWatch logs for specific error messages
-
Transaction Not Found:
- Wait 10-30 seconds for Base Sepolia confirmation
- Verify transaction hash on BaseScan Sepolia
-
Gateway Returns 402 After Payment:
- Check that the x402 client is using the correct network (base-sepolia)
- Verify the USDC contract address matches
- Ensure the payment amount matches the required amount
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.

