跳到主要内容

Getting Started with Flask

Start accepting x402 payments in your Flask server in 2 minutes.

Example Code

You can find the full code for this example on GitHub.

Step 1: Install Dependencies​

Install the required packages for your Flask server:

pip install x402 flask python-dotenv

Step 2: Set Your Environment Variables​

Create a .env file in your project root:

echo "ADDRESS=0x...\nNETWORK=sui" > .env

Your .env file should look like this:

ADDRESS=0x... # wallet public address you want to receive payments to
NETWORK=sui # recommended for fastest settlement
# Optional: Configure facilitator URL if using custom facilitator
# FACILITATOR_URL=https://x402.blockeden.xyz
Network Options

BlockEden.xyz supports multiple networks:

  • sui (recommended for fastest settlement)
  • ethereum
  • base
  • polygon
  • avalanche

Step 3: Create a New Flask App​

Create an app.py file with the following code:

import os
from typing import Any, Dict

from dotenv import load_dotenv
from flask import Flask, jsonify
from x402.flask.middleware import PaymentMiddleware
from x402.types import TokenAmount, TokenAsset, EIP712Domain

# Load environment variables
load_dotenv()

# Get configuration from environment
ADDRESS = os.getenv("ADDRESS")
NETWORK = os.getenv("NETWORK", "sui")

if not ADDRESS:
raise ValueError("Missing required environment variables")

app = Flask(__name__)

# Initialize payment middleware
payment_middleware = PaymentMiddleware(app)

# Apply payment middleware to specific routes
payment_middleware.add(
path="/weather",
price="$0.001",
pay_to_address=ADDRESS,
network=NETWORK,
)

# Apply payment middleware to premium routes
payment_middleware.add(
path="/premium/*",
price=TokenAmount(
amount="10000",
asset=TokenAsset(
address="0x...", # USDC contract address for your network
decimals=6,
eip712=EIP712Domain(name="USDC", version="2"),
),
),
pay_to_address=ADDRESS,
network=NETWORK,
)


@app.route("/")
def index() -> Dict[str, str]:
"""Root endpoint"""
return jsonify({
"message": "x402 Payment Server",
"status": "running",
})


@app.route("/weather")
def get_weather() -> Dict[str, Any]:
"""Get weather data - requires payment"""
return jsonify({
"report": {
"weather": "sunny",
"temperature": 70,
"location": "San Francisco",
}
})


@app.route("/premium/content")
def get_premium_content() -> Dict[str, Any]:
"""Get premium content - requires payment"""
return jsonify({
"content": "This is premium content",
"type": "article",
"timestamp": "2025-01-01T00:00:00Z",
})


@app.route("/premium/analytics")
def get_premium_analytics() -> Dict[str, Any]:
"""Get premium analytics - requires payment"""
return jsonify({
"analytics": {
"users": 1000,
"revenue": 50000,
"growth": 25.5,
}
})


if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=4021,
debug=True,
)

Step 4: Run the Server​

Start your Flask server:

python app.py

Or use Flask's built-in development server:

flask --app app run --port 4021
Your Flask server is now accepting x402 payments!

Your server will be available at http://localhost:4021.

Step 5: Test the Server​

You can test payments against your server locally using HTTP clients like curl, Postman, or by building a Python client application.

Coming Soon

Client implementation guides for httpx and requests libraries will be available soon.

Manual Testing with curl​

# This will return a 402 Payment Required response
curl http://localhost:4021/weather

# The response will include payment details in headers

Payment Configuration Options​

The PaymentMiddleware.add() method accepts flexible payment configurations:

Simple Dollar Amount​

# Initialize payment middleware
payment_middleware = PaymentMiddleware(app)

payment_middleware.add(
path="/weather",
price="$0.001",
pay_to_address=ADDRESS,
network="sui",
)

@app.route("/weather")
def get_weather():
return jsonify({"weather": "sunny"})

Token Amount with Specific Asset​

from x402.types import TokenAmount, TokenAsset, EIP712Domain

payment_middleware.add(
path="/premium/data",
price=TokenAmount(
amount="10000",
asset=TokenAsset(
address="0x...", # Token contract address
decimals=6,
eip712=EIP712Domain(name="USDC", version="2"),
),
),
pay_to_address=ADDRESS,
network="sui",
)

@app.route("/premium/data")
def get_premium_data():
return jsonify({"data": "Premium content"})

Multiple Routes with Same Payment​

You can protect multiple routes with wildcard paths:

# Protect all /premium routes with the same payment requirement
payment_middleware.add(
path="/premium/*",
price="$0.05",
pay_to_address=ADDRESS,
network="sui",
)

@app.route("/premium/content")
def premium_content():
return jsonify({"content": "Premium content"})

@app.route("/premium/analytics")
def premium_analytics():
return jsonify({"analytics": {...}})

Advanced Features​

Custom Payment Verification Callback​

Add custom logic when payments are verified:

# Note: Custom payment verification callbacks may vary based on
# the x402 library version. Check the official documentation for
# the exact callback mechanism supported by your version.

payment_middleware.add(
path="/weather",
price="$0.001",
pay_to_address=ADDRESS,
network="sui",
)

@app.route("/weather")
def get_weather():
# Payment has been verified if this handler is reached
# Add your custom logic here
return jsonify({"weather": "sunny"})

Error Handling​

Add custom error handling for payment failures:

from flask import request
from x402.exceptions import X402PaymentError

@app.errorhandler(X402PaymentError)
def handle_payment_error(error):
return jsonify({
"error": "Payment required",
"details": str(error),
"path": request.path,
}), 402

@app.errorhandler(Exception)
def handle_general_error(error):
app.logger.error(f"Unexpected error: {error}")
return jsonify({
"error": "Internal server error",
}), 500

CORS Configuration​

Enable CORS for cross-origin requests:

from flask_cors import CORS

# Enable CORS for all routes
CORS(app, resources={
r"/*": {
"origins": ["http://localhost:3000", "https://yourdomain.com"],
"allow_headers": ["Content-Type", "Authorization"],
"methods": ["GET", "POST", "OPTIONS"],
}
})

Install flask-cors:

pip install flask-cors

Request Context Access​

Access payment information in your route handlers:

from flask import g

@app.route("/weather")
@require_payment(
price="$0.001",
pay_to_address=ADDRESS,
network="sui",
facilitator_config=facilitator_config,
)
def get_weather():
# Access payment details from Flask's g object
payment_info = getattr(g, "x402_payment", None)

return jsonify({
"report": {"weather": "sunny", "temperature": 70},
"payment": {
"tx_hash": payment_info.tx_hash if payment_info else None,
}
})

Logging Configuration​

Set up proper logging for production:

import logging
from logging.handlers import RotatingFileHandler

if not app.debug:
# Create logs directory if it doesn't exist
if not os.path.exists('logs'):
os.mkdir('logs')

# Configure file handler
file_handler = RotatingFileHandler(
'logs/x402_server.log',
maxBytes=10240000,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)

app.logger.setLevel(logging.INFO)
app.logger.info('x402 payment server startup')

Production Deployment​

Before deploying to production:

  1. Switch to production network (e.g., sui instead of sui-testnet)
  2. Use environment variables for all sensitive data
  3. Disable debug mode (debug=False)
  4. Use a production WSGI server (Gunicorn, uWSGI)
  5. Enable HTTPS (use a reverse proxy like nginx)
  6. Set up proper logging and monitoring
  7. Configure CORS for your production domains

Production Example​

import os
import logging
from logging.handlers import RotatingFileHandler

from dotenv import load_dotenv
from flask import Flask, jsonify
from flask_cors import CORS
from x402.flask.middleware import PaymentMiddleware

load_dotenv()

app = Flask(__name__)
app.config['DEBUG'] = False

# CORS configuration
CORS(app, resources={
r"/*": {
"origins": os.getenv("ALLOWED_ORIGINS", "").split(","),
"allow_headers": ["Content-Type", "Authorization"],
"methods": ["GET", "POST", "OPTIONS"],
}
})

# Logging configuration
if not app.debug:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler(
'logs/x402_server.log',
maxBytes=10240000,
backupCount=10
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)

# Initialize payment middleware
payment_middleware = PaymentMiddleware(app)

payment_middleware.add(
path="/api/data",
price="$0.01",
pay_to_address=os.getenv("ADDRESS"),
network="sui", # Production Sui network
)

@app.route("/api/data")
def get_data():
app.logger.info("Delivering protected data")
return jsonify({"data": "Protected content"})

if __name__ == "__main__":
app.run(
host="0.0.0.0",
port=int(os.getenv("PORT", "4021")),
debug=False,
)

Deploy with Gunicorn​

For production, use Gunicorn:

pip install gunicorn

gunicorn app:app \
--workers 4 \
--bind 0.0.0.0:4021 \
--timeout 120 \
--access-logfile logs/access.log \
--error-logfile logs/error.log

Deploy with uWSGI​

Alternatively, use uWSGI:

pip install uwsgi

uwsgi --http 0.0.0.0:4021 \
--wsgi-file app.py \
--callable app \
--processes 4 \
--threads 2

Troubleshooting​

Common Issues​

Payment verification fails

  • Verify your BLOCKEDEN_API_KEY is correct
  • Check that the wallet address format matches the network
  • Ensure the facilitator URL is accessible

CORS errors

  • Install and configure flask-cors
  • Ensure CORS middleware is configured before routes
  • Check allowed origins configuration

Network mismatch

  • Ensure client and server use the same network
  • Check that the token address is valid for the network

Module import errors

  • Ensure you installed x402 package
  • Verify your Python version is 3.8 or higher

Decorator order matters

  • @require_payment should be the closest decorator to the function
  • Example correct order:
    @app.route("/weather")
    @require_payment(...)
    def get_weather():
    ...

Port already in use

  • Change the port in app.run() configuration
  • Kill any existing processes: lsof -ti:4021 | xargs kill

Why Choose Flask?​

Flask is an excellent choice for x402 payment servers:

  • Lightweight: Minimal and unopinionated framework
  • Flexible: Easy to extend with plugins
  • Easy to learn: Simple, intuitive API
  • Large community: Extensive documentation and third-party extensions
  • Production-ready: Battle-tested in thousands of applications

Flask vs FastAPI​

FeatureFlaskFastAPI
PerformanceGoodExcellent
Async SupportVia extensionsBuilt-in
Type SafetyOptionalBuilt-in
Auto DocsVia extensionsBuilt-in
Learning CurveEasyModerate
MaturityVery matureModern

Choose Flask if you:

  • Want a simple, familiar framework
  • Don't need async features
  • Prefer flexibility over structure
  • Are building a traditional web app

Choose FastAPI if you:

  • Need high performance
  • Want built-in async support
  • Prefer type safety
  • Want automatic API documentation

Next Steps​

Need Help?​

Join Our Community

Have questions or want to connect with other developers?

Join Discord