Skip to main content

Manual x402 server flow (Python)

This page shows how to respond with 402 Payment Required and build the PAYMENT-REQUIRED header by hand in Python—no x402 server middleware. You decide when payment is required, construct the payment-requirements payload, base64-encode it, and send it in the response. For production you’ll usually use the Flask or FastAPI quickstarts; this tutorial is for agents or environments that need a minimal implementation or want to understand the protocol from the server’s perspective.
This is a 402 response-construction example, not a payment-processing server. It never delivers a paid resource. Requests carrying a payment header receive 501 until a real verification, settlement and recovery implementation replaces the demonstration handler. Header presence is not proof of payment.

1. When to return 402

When a request hits a protected route:
  • If the request does not include a valid PAYMENT-SIGNATURE header (or the payment is invalid/expired), respond with 402 and a PAYMENT-REQUIRED header so the client knows how to pay.
  • If the request does include a valid payment, you (or your facilitator) verify/settle it and then respond with 200 and the resource. Verification and settlement are typically done via the PayAI Facilitator or your own backend; this page focuses only on building the 402 response.

2. Build the payment-requirements payload

The PAYMENT-REQUIRED header must contain base64-encoded JSON. The JSON object has this shape (see x402 Reference §5.1): Each item in accepts describes one payment option. This example uses Base Sepolia and Solana devnet, not mainnet. The client echoes its chosen requirement in accepted within PAYMENT-SIGNATURE.

3. Example: building the payload in Python

Define the payload dict, then encode it as base64 and set the header. Set your own testnet recipient addresses in EVM_ADDRESS and SVM_ADDRESS. Set SVM_FEE_PAYER from the selected facilitator’s current devnet configuration; check supported networks. Missing configuration stops the example; it never substitutes somebody else’s recipient. Address syntax checks do not prove ownership or network compatibility.

4. Send the 402 response with PAYMENT-REQUIRED

Set the PAYMENT-REQUIRED header to the base64 string and return status 402.
The following demonstration handlers return 501 when a payment header is supplied. Do not expose them as payable services. A real server must validate against its own requirements and follow the selected scheme’s verification/settlement sequence before delivering a resource. Preserve uncertain-payment state and follow recovery guidance. Example with Flask (requires Flask):
Example with FastAPI (requires FastAPI):

Summary

For exact field types and facilitator behavior, see the x402 Reference. For a ready-made server, use the Flask or FastAPI quickstarts.

Need help?

Join our Community

Have questions or want to connect with other developers? Join our Discord server.