A Python web service for creating x402-protected payment links. This service allows you to generate unique payment URLs that require cryptocurrency payments before granting access.
- Configure environment:
cp .env.example .env
# Edit .env with your wallet address and settings- Build the image:
docker build -t payment-link .- Run the container:
touch payments.db
docker run -d \
-p 8000:8000 \
-v $(pwd)/payments.db:/app/payments.db \
--env-file .env \
--name payment-link \
payment-linkThe touch command creates an empty database file, and the -v flag mounts it into the container for persistence.
- Verify it's running:
curl http://localhost:8000/Configure the service using environment variables:
| Variable | Default | Description |
|---|---|---|
NETWORK |
base-sepolia |
Blockchain network (base-sepolia for testnet, base for mainnet) |
APP_BASE_URL |
http://localhost:8000 |
Public base URL for generated payment links |
APP_NAME |
Payment Link Service |
Service name displayed in payment UI |
APP_LOGO |
/static/logo.png |
Logo URL for payment UI |
FACILITATOR_URL |
https://x402f1.secondstate.io |
x402 facilitator service endpoint |
MAX_TIMEOUT_SECONDS |
60 |
Payment timeout in seconds |
DATABASE_PATH |
payments.db |
SQLite database file path |
Serves the web UI for creating and paying payment links.
Open in a browser to access the interactive payment interface.
Creates a new payment link with a unique ID.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
float | Yes | Payment amount in USD (must be > 0) |
receiver |
string | Yes | Blockchain address to receive the payment |
Example Request:
curl "http://localhost:8000/create-payment-link?amount=0.01&receiver=0x1234567890abcdef1234567890abcdef12345678"Response:
{
"payment_id": "550e8400-e29b-41d4-a716-446655440000",
"payment_url": "http://localhost:8000/pay/550e8400-e29b-41d4-a716-446655440000",
"amount": "0.01",
"receiver": "0x1234567890abcdef1234567890abcdef12345678"
}x402-protected payment endpoint. This endpoint handles the payment flow.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
payment_id |
string | Unique payment identifier from /create-payment-link |
Behavior:
- If payment is pending (no X-Payment header): Returns HTTP 402 with payment requirements
- If payment is pending (with valid X-Payment header): Processes payment and returns success
- If payment is already completed: Returns the transaction details
Response (Payment Required - 402):
For API clients (non-browser):
{
"x402Version": 1,
"accepts": [...],
"error": "No X-PAYMENT header provided"
}For browsers: Returns an HTML payment page.
Response (Payment Successful - 200):
{
"status": "paid",
"tx": "0x1234567890abcdef..."
}Response (Not Found - 404):
{
"error": "Payment not found"
}Check the current status of a payment.
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
payment_id |
string | Unique payment identifier |
Example Request:
curl "http://localhost:8000/status/550e8400-e29b-41d4-a716-446655440000"Response (Pending):
{
"payment_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": 0.01,
"paid": false,
"tx": null
}Response (Paid):
{
"payment_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": 0.01,
"paid": true,
"tx": "0x1234567890abcdef..."
}Response (Not Found - 404):
{
"error": "Payment not found"
}- Create a payment link:
curl "http://localhost:8000/create-payment-link?amount=0.01"-
Share the
payment_urlwith the payer. When they open it in a browser, they'll see a payment interface. -
After payment, the payer can reload the page to see the confirmation with the transaction hash.
-
Check payment status programmatically:
curl "http://localhost:8000/status/{payment_id}"For local development without Docker:
- Install dependencies:
uv sync- Configure environment:
cp .env.example .env
# Edit .env with your settings- Run the server:
uv run python main.py- Run tests:
uv run pytest tests/ -vThe x402 protocol enables HTTP-native payments:
- Client requests a protected resource
- Server responds with HTTP 402 and payment requirements
- Client makes a blockchain payment and includes proof in the
X-Paymentheader - Server verifies the payment and grants access
This service uses USDC on Base (or Base Sepolia for testing) for payments.