ByAUJay
Summary: In this post, we’ll explore how your team can roll out an x402-paywalled API in just one weekend. We’ll dive into middleware that fits right into popular stacks, the specific HTTP headers you need to use, and tips on generating and validating receipts. Plus, we’ll cover the operational safeguards that enterprises look for. It’s a straightforward, copy-paste guide for decision-makers who want to implement pay-per-call monetization without the hassle of accounts, OAuth, or a billing backend.
Shipping an x402‑Paywalled API in a Weekend: Middleware, Headers, and Receipts
Decision-makers have been telling us they want to tap into usage-based revenue, but without the hassle of building a whole billing team. Well, good news is on the horizon! By late 2025, that dream becomes a reality with x402--a super handy HTTP-native payment protocol that brings the 402 Payment Required status back to life. This means clients can pay for API calls using USDC and other tokens, and even retry the same request with proof.
Coinbase has taken the lead in managing the core specifications, and Cloudflare rolled out top-notch support in September 2025. Now, the ecosystem is buzzing with production facilitators, SDKs, and server middleware across various stacks. Check it out here!
Here’s the quickest route we’ve discovered to take you from a “free endpoint” to “revenue per request.” With specific header contracts, base64 payloads, and receipt patterns, you’ll be all set to roll this out by the weekend!
Why x402 now (and what changed in 2025)
- So, HTTP had a 402 Payment Required status hanging around, but no one really figured out how to use it. The x402 spec lays out a nice little handshake: the server sends back a 402 with some machine-readable payment details; then clients handle the payment and retry with an X-PAYMENT header. The servers check it out (either on their own or through a facilitator) and then respond with a 200 status, possibly throwing in some settlement details. You can dive into more about it here.
- Coinbase's hosted “facilitator” really makes things smooth for businesses. They offer fee-free USDC on Base, with optional KYT/OFAC checks, SLAs, and REST endpoints for verification and settlement. Plus, Cloudflare jumped in with Workers/Agents integration and co-launched the x402 Foundation back in September 2025. For more info, check it out here.
- When it comes to tokens and networks, you get USDC straight out of the box using EIP-3009 “transferWithAuthorization” on the EVM, and there’s Solana support too! Community and self-hosted facilitators are also out there to expand chain coverage. You can read more about that here.
Bottom line: you can charge for each call without needing accounts, keys, or dealing with PCI scope--and you don’t even have to run any blockchain nodes.
The 48‑hour plan
- Friday PM: Set up your API so it sends out a standards-compliant 402 along with the “accepts[]” payment options; also, get that middleware going.
- Saturday: Introduce X-PAYMENT validation through a facilitator; make sure to return those X-PAYMENT-RESPONSE receipts and integrate some logs/metrics.
- Sunday: Focus on pricing policy, idempotency, credit bundles, and tighten up production (think rate limits, CORS, and caching).
We’ll walk you through what to send and check at each step of the way.
Step 1 -- Emit a standards‑compliant 402
When a client tries to access a protected endpoint without the proper credentials, here's how to respond:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": "Unauthorized",
"message": "You need to provide valid authentication credentials to access this resource."
}
Make sure to let them know they need to provide the right authentication details to get through. This keeps things clear and sets the right expectations.
HTTP/1.1 402 Payment Required
Content-Type: application/json
Cache-Control: no-store
X-Request-Id: 7b2a6d3e-7a3f-4b25-86b1-0c19c6f9c2f1
{
"x402Version": 1,
"error": "payment_required",
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1000000", // 1 USDC (6 decimals)
"resource": "https://api.example.com/v1/premium/search",
"description": "Search 100 docs",
"mimeType": "application/json",
"payTo": "0x1234...cAFE",
"asset": "0xa0b86991c6218b36c1d19d4a2e9eb0cE3606eB48", // USDC (example)
"extra": {
"eip712": {"name": "USD Coin", "version": "2"},
"validForSeconds": 300
}
}
]
}
- To get started, you'll need a few required fields:
x402Versionandaccepts[]. Within a requirement, you might typically see common fields likescheme,network,maxAmountRequired(in atomic units), andresource. When it comes to EVM flows, you usually havepayTo, theasset(token address), and the EIP‑712 metadata for those USDC signatures. Check it out here: (github.com) - It's a good idea to kick things off conservatively with just one accept option (think Base + USDC) and give yourself a 5-minute time frame. Once you’re comfortable, feel free to add Solana or any other chains you want down the line using the same endpoint. You can dive deeper into this over at (docs.cdp.coinbase.com).
Tip: If your endpoint is also used by browsers, make sure to check for Accept: text/html. This way, you can display a purchase page while still returning a JSON 402 for those programmatic clients. Luckily, middleware templates already take care of this split for you. Check it out over at (deepwiki.com).
Step 2 -- Let clients pay and retry with X‑PAYMENT
Clients whip up a signed authorization (gasless in EVM thanks to EIP‑3009) and shoot it over as a base64‑encoded JSON in the X‑PAYMENT header when they retry. Here’s how it looks:
GET /v1/premium/search?q=vector+db HTTP/1.1
Host: api.example.com
X-PAYMENT: eyJ4NDAyVmVyc2lvbiI6MSwic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiYmFzZSIsInBheWxvYWQiOnsiYXV0aG9yaXphdGlvbiI6eyJmcm9tIjoiMHhQQVlFUiIsInRvIjoiMHhQQVlFRSIsInZhbHVlIjoiMTAwMDAwIiwidmFsaWRBZnRlciI6IjE3NDg3NjI4MDQiLCJ2YWxpZEJlZm9yZSI6IjE3NDg3NjMxMDQiLCJub25jZSI6IjB4YWJjLi4uIn0sInNpZ25hdHVyZSI6IjB4NTU1Li4uIn19fQ==
What’s inside after base64:
When you decode a base64 string, you end up with the original binary data that was encoded. Base64 is often used to encode data so that it can be easily transmitted over channels that only support text. It’s handy for things like embedding images in HTML or sending files in emails.
Here’s a quick rundown of what base64 is:
- Encoding: Turns binary data (like images, documents, etc.) into a text string.
- Decoding: Converts that text back into the original binary data.
- Use Cases: Commonly used for images in HTML, email attachments, and data transfers.
How to decode base64:
To decode a base64 string, you can use various programming languages. Here are a few examples:
Python:
import base64
# Your base64 string
encoded_data = "SGVsbG8sIFdvcmxkIQ=="
decoded_data = base64.b64decode(encoded_data)
print(decoded_data.decode('utf-8'))
JavaScript:
let encodedData = "SGVsbG8sIFdvcmxkIQ==";
let decodedData = atob(encodedData);
console.log(decodedData);
Example:
- Base64 String:
SGVsbG8sIFdvcmxkIQ== - Decoded Output:
Hello, World!
Base64 Online Decoder
If you prefer a quick solution, check out this base64 decoder where you can simply paste your string and get the result instantly!
In short, decoding base64 data is straightforward and can be done in various programming environments or even online tools. Happy decoding!
{
"x402Version": 1,
"scheme": "exact",
"network": "base",
"payload": {
"authorization": {
"from": "0xPAYER",
"to": "0xPAYEE",
"value": "1000000",
"validAfter": "1748762804",
"validBefore": "1748763104",
"nonce": "0x…32 bytes…"
},
"signature": "0x…EIP-712 signature…"
}
}
- Header Name and Encoding: We’re talking about X‑PAYMENT here, which is basically a base64-encoded JSON. If you’re dealing with EVM payloads, you’ll be using the EIP‑3009 TransferWithAuthorization for USDC. The cool part? You don’t need any native gas since the facilitator takes care of that. Check it out on GitHub.
- SDK Support: The good news is that many SDKs do the heavy lifting for you! For example, you can use thirdweb’s
wrapFetchWithPayment, Coinbase’sfetchWithX402, or Cloudflare’sx402‑fetchfor Workers and Agents. Dive into more details on Thirdweb’s portal.
Step 3 -- Verify and settle (server or facilitator)
When X-PAYMENT is on your server:
- First things first, check and confirm your requirements (like resource, network, and maxAmountRequired).
- Now, let’s move on to verifying authorization and settling up:
- Local: You’ll need to call the token’s
transferWithAuthorization(EIP‑3009) or use the Solana transfer, then just hang tight for the confirmation. - Facilitator: Here, you’ll want to POST the header along with your requirements to
/verifyand/settle, then wait for the response. You can find more details in the docs here.
- Local: You’ll need to call the token’s
Coinbase Facilitator Endpoints:
Coinbase offers a bunch of awesome API endpoints that help you interact with their platform. Here’s a quick rundown of the main ones you’ll be using:
1. Market Data Endpoints
These endpoints let you grab real-time market data. Perfect for keeping tabs on prices, trading volumes, and more. Check out the details:
- Current Price: Get the latest price of a specific cryptocurrency.
- Endpoint:
GET /v2/prices/:currency_pair
- Endpoint:
- Historic Rates: Want to see how a cryptocurrency has performed over time? This is your go-to.
- Endpoint:
GET /v2/prices/:currency_pair/historic
- Endpoint:
2. Account Management Endpoints
Need to manage your Coinbase account? These endpoints have you covered:
- Get Accounts: Fetch all the accounts linked to your Coinbase profile.
- Endpoint:
GET /v2/accounts
- Endpoint:
- Create A Charge: Need to request payment from someone? This endpoint makes it super easy.
- Endpoint:
POST /v2/charges
- Endpoint:
3. Transaction Endpoints
When it comes to transactions, you’ll want to utilize these:
- List Transactions: View all your transactions in one place.
- Endpoint:
GET /v2/accounts/:account_id/transactions
- Endpoint:
- Send Money: Ready to send some crypto to a friend? This endpoint’s got your back.
- Endpoint:
POST /v2/accounts/:account_id/transactions
- Endpoint:
4. Webhook Endpoints
Setting up webhooks can help you stay in the loop with real-time updates:
- Webhook Configurations: Set up and manage your webhook settings.
- Endpoint:
POST /v2/webhook_configurations
- Endpoint:
5. Security Endpoints
Keeping your account secure is a top priority:
- Two-Factor Authentication: Enable or disable 2FA for added security.
- Endpoint:
POST /v2/2fa
- Endpoint:
Remember, when working with these endpoints, you'll need to handle authentication and error responses properly. Always test your calls to ensure everything’s working smoothly!
For more details on each endpoint and their specific parameters, check out the Coinbase API documentation.
- POST /v2/x402/verify -- This one’s all about checking the payload to make sure it meets the necessary requirements.
- POST /v2/x402/settle -- Here, you’ll be submitting the on-chain transfer and getting back a settlement result, which includes the transaction hash, network info, payer details, and amount. Check it out for more info at docs.cdp.coinbase.com.
Why We Recommend a Facilitator for Weekend Shipping:
- You get to skip the hassle of managing blockchain connectivity, gas fees, and reorgs.
- Our CDP facilitator on Base is totally fee-free for USDC and even offers optional compliance checks. Check it out here: (docs.cdp.coinbase.com)
Step 4 -- Return a receipt via X‑PAYMENT‑RESPONSE
After everything’s been verified and settled, don't forget to add a machine-readable receipt header:
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Expose-Headers: X-PAYMENT-RESPONSE
X-PAYMENT-RESPONSE: eyJzdWNjZXNzIjp0cnVlLCJ0cmFuc2FjdGlvbiI6IjB4OGYzZC4uLiIsIm5ldHdvcmsiOiJiYXNlIiwicGF5ZXIiOiIweFBBWUVSIiwicmVzb3VyY2UiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbS92MS9wcmVtaXVtL3NlYXJjaCIsImFtb3VudCI6IjEwMDAwMCIsInNldHRsZWRBdCI6MTc0ODc2MzEwOS4xOTV9
I'm sorry, but it looks like you've only provided a single word. Could you please share the text you'd like me to rewrite?
{
"success": true,
"transaction": "0x8f3d…",
"network": "base",
"payer": "0xPAYER",
"resource": "https://api.example.com/v1/premium/search",
"amount": "1000000",
"settledAt": 1748763109.195
}
The header name and the base64 JSON pattern come from the x402 spec. By exposing it through CORS, browser clients can take a closer look at the proofs. Check it out on GitHub!
If you're into multi-credit purchases (like snagging 5 calls at once), make sure to return an X-PAYMENT “token” in the response. This token acts as a reusable credit, so you can use it in future calls until your credits run dry. Check out the details here: (docs.proxy402.com)
Drop‑in middleware for popular stacks
We suggest kicking things off with framework packages instead of diving into writing the protocol from scratch.
- Node/Express: You can use
x402-expressor create a light custom middleware that:- If there’s no
X-PAYMENT, it should return the 402 JSON response mentioned earlier. - If there is an
X-PAYMENT, it will post the header and requirement to your payment facilitator, manage the result, and set theX-PAYMENT-RESPONSE. (deepwiki.com)
- If there’s no
- Cloudflare Workers (Hono): Check out
x402-honoalong withx402-fetchto secure routes and fetch paywalled content from agents. (developers.cloudflare.com) - Client: You’ve got options like
thirdweb’swrapFetchWithPaymentor Coinbase’sfetchWithX402(whether you’re using React hooks or just plain JavaScript). These tools automatically spot a 402 error, create a payment payload, and attempt to retry. (portal.thirdweb.com)
A Minimalist Express-Style Server Guard
Creating a lightweight server guard can really streamline your Express app. Let’s dig into how you can set one up with just the essentials.
What’s a Server Guard?
Simply put, a server guard checks incoming requests and makes sure everything’s in order before they reach your server. This helps keep your app secure and running smoothly.
Setting Up Your Guard
Here’s a simple way to create a server guard in your Express app. You’ll want to create a middleware function that will intercept requests, allowing you to add any checks or logging you need.
const express = require('express');
const app = express();
// Middleware function
function serverGuard(req, res, next) {
// Check for specific headers or parameters
const token = req.headers['authorization'];
if (!token) {
return res.status(403).json({ message: 'Forbidden: No token provided' });
}
// You can add more checks here...
// If everything is good, move on to the next middleware/route
next();
}
// Use the server guard middleware
app.use(serverGuard);
// A sample route
app.get('/', (req, res) => {
res.send('Hello, world!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
How It Works
- Middleware Function: The
serverGuardfunction runs every time a request hits your server. Here, we're checking for an authorization token in the headers. - Checking Tokens: If the token isn’t there, we send a 403 Forbidden response. Otherwise, we call
next()to pass control to the next middleware or route. - Logging and Security: You can easily expand this guard to include more checks, like logging requests or validating input parameters.
Conclusion
And there you have it! A super simple Express-style server guard to help keep your app secure. You can tweak it as needed, adding more checks or logging to fit your specific use case. Happy coding!
// pseudo‑impl: use official packages in production
app.use("/v1/premium/search", async (req, res, next) => {
const requirement = mkRequirement({ maxCents: 100 }); // 1 USDC
const header = req.get("X-PAYMENT");
if (!header) return res.status(402).json(mk402(requirement));
const verify = await fetch(FACILITATOR + "/v2/x402/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ paymentHeader: header, requirement })
}).then(r => r.json());
if (!verify.valid) {
return res.status(402).json(mk402(requirement, verify.error));
}
const settle = await fetch(FACILITATOR + "/v2/x402/settle", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ paymentHeader: header, requirement })
}).then(r => r.json());
res.set("Access-Control-Expose-Headers", "X-PAYMENT-RESPONSE");
res.set("X-PAYMENT-RESPONSE", b64(settle));
return next(); // continue to handler that returns the actual resource
});
Pricing and SKUs that work in practice
- Begin by setting a clear price for each call--think $0.01, which translates to 1,000,000 atomic units since USDC has 6 decimals. It's super important to make sure clients never go over the maxAmountRequired. Check out the details on this GitHub link.
- Offer bundled credits! You can create options for 5 or 20-call bundles, and provide a response token that clients can use until they hit that credit limit of zero. Just remember to keep the lifespan of the token limited to minimize any risks. More info can be found in the docs here.
- For dynamic pricing, your middleware should be able to calculate the maxAmountRequired for each request, depending on the model or the number of tokens. Just make sure to tie the payment to the specific resource URL. This helps stop any misuse across different APIs. You can find more on this topic over on GitHub.
Receipts your finance and security teams will accept
Return at least three proof layers:
- You can get on-chain proof by using the transaction hash along with the network through X-PAYMENT-RESPONSE.
- It’s a good idea to include request binding, which combines the resource URL and X-Request-Id, all in one receipt object.
- An optional step is to have your server sign the service receipt: just sign a compact receipt hash with your server key. This helps create solid, unchangeable audit trails.
For those multi-party workflows where agents are reaching out to suppliers, it's worth looking into the fresh concept of “verifiable delivery” receipts. These receipts link “what was delivered” with “what was paid,” creating a solid connection between the two. Some projects are actually blending x402 payments with cryptographic delivery attestations. This way, buyers can easily prove that the response aligns with their declared policies. Check it out here: (build.avax.network).
Retention Policy
Keep the decoded receipt JSON and raw headers for anywhere between 7 to 90 days, depending on what your audit needs are. Don't forget to index them by the transaction hash and request ID!
Security and fraud controls you can implement in hours
- Keep those validity windows tight: Make sure to check
validAfterandvalidBeforefor EIP-3009 authorizations and turn away any old authorizations. (docs.icpay.org) - Idempotency is key: Create a hash using
(payer, resource, value, nonce)and reject any duplicates to stop double-spend attempts on the same call. - Stay compliant: Route all checks through a facilitator to screen for KYT/OFAC, making sure everything lines up with enterprise policies. (docs.cdp.coinbase.com)
- CORS and header exposure: Set
Access-Control-Expose-Headers: X-PAYMENT-RESPONSEso that browsers can access receipts easily. (build.avax.network) - CDN behavior: For 402s, use
Cache-Control: no-storeto prevent caching, and mark 200s as public/private depending on how sensitive the data is; but keep X-PAYMENT-RESPONSE out of the cache. - Replay isolation: Make sure to include the resource in both the requirement and the receipt; verify that the retry is using the exact same method, path, and query that was used to generate the 402. (github.com)
Observability: the dashboards you’ll want on Monday
Log these fields on both 402 and 200:
- request_id, method, path, canonical_query
- payer, network, amount_atomic
- facilitator: name/version, verify_ms, settle_ms
- tx_hash, settled_at, success
- sku, credits_remaining (if applicable)
Export your data to your SIEM and BI systems. Keep an eye on the alert for any spikes in verify/settle failure rates, as well as those “verify valid but settle failed” occurrences. These usually indicate gas conditions, especially when it comes to self‑settling.
Production choices: facilitator vs. self‑hosted vs. hybrid
- Hosted (CDP): If you're looking for speed and efficiency, this one's a winner. You’ll get the quickest time-to-value with solid enterprise compliance, plus you can use Base and Solana without any fees on USDC when you're on Base. It’s a fantastic go-to for pilots and bigger enterprise rollouts. Check out the details here.
- Community/self-hosted: Want to take control? You can add EVMs, Solana variants, or even your own custom tokens. This option gives you the flexibility to manage latency and routing as you see fit. Just make sure your facilitator is on top of implementing and supporting the discovery, verify, and settle endpoints. You can find more info here.
- Client SDK landscape: There’s a lot going on with the Client SDKs! Thirdweb’s got your back with support for over 170 EVMs (either permit or 3009), plus they offer Coinbase hooks for embedded wallets and Workers/Agents wrappers tailored for Cloudflare. Dive into the details here.
L402 vs. x402 (and when each fits)
Lightning Labs’ L402 (which you might know as LSAT) is really leading the charge in 402-style API monetization through the use of Macaroons and the Lightning Network. If you're already set up with Lightning infrastructure and appreciate the flexibility that Macaroon caveats offer, you'll find this to be a solid match for your needs.
On the other hand, x402 is designed with EVM/Solana in mind, focusing on USDC-first, HTTP-header payloads, and facilitator patterns that help keep blockchain complexity low for web backends. Some teams find it beneficial to run both: using L402 for Bitcoin and Lightning users while tapping into x402 for stablecoin transactions to Base/Solana. You can check it out on their GitHub!
Edge and agents: why this matters to AI roadmaps
Cloudflare Workers/Agents and MCP stacks are now equipped with x402, which means agents can independently purchase data, tools, and model inferences while providing verifiable receipts. This upgrade eliminates the hassle of “bring-your-own-API-key” and allows you to meter each call right at the edge. Check it out here: (developers.cloudflare.com)
Common pitfalls (we keep seeing) and exact fixes
- Atomic vs. decimal mismatch: Always make sure to compute USDC in server-side 6-decimal atomic units. Trusting client-side decimals is a no-go. Also, bind
maxAmountRequiredin atomic form. (github.com) - Wrong chain identifiers: Stick to the canonical network strings like "base", "base‑sepolia", and "solana". Make sure to validate these before verification. (docs.cdp.coinbase.com)
- Missing header exposure: If you don't include
Access-Control-Expose-Headers, clients in the browser won't be able to readX-PAYMENT-RESPONSE. This can lead to some pretty fragile UIs. (build.avax.network) - Over-caching 402s: Don't forget to add
Cache-Control: no-storeon 402 responses. If you skip this, CDNs might keep the paywall hanging around even after the payment goes through. - Long validity windows: Aim for a validity of 5 minutes or less; rotate your nonces regularly and make sure to include the resource in your signed scope to dodge any cross-endpoint replay issues. (docs.icpay.org)
A concrete weekend checklist
Friday (3-5 hours)
- Choose a facilitator: use CDP for the Base mainnet and go with the community for Base Sepolia dev. If you’re opting for CDP, don’t forget to grab those API keys! Check out the details here.
- Wrap your protected routes with middleware that sends back that 402 JSON mentioned earlier; make sure to unit-test
accepts[]. You can find more info on this here.
Saturday (4-6 hours)
- Add a handler for X-PAYMENT:
- First, post to
/verify, then move on to/settle. Don't forget to handle the possible failure modes like invalid signature, expired requests, or underpayment. You can check out the details here.
- First, post to
- Return X-PAYMENT-RESPONSE:
- Make sure to include the transaction hash and resource in the response. Also, expose the header via CORS. For more info, take a look at this link: documentation.
- Wire up metrics and structured logs:
- It's important to set this up for better tracking and debugging later on.
Sunday (3-5 hours)
- Pricing policy: We’re looking at a flat rate plus bundles. Let’s make sure to document SKUs and their credit lifetimes. You can check out more details here.
- Hardening: We need to set up some rate limits, prevent caching on 402, implement bounded time windows, and use idempotency keys. Plus, let's make sure we have a graceful fallback to 402 in case of any facilitator errors.
- Smoke tests: We’ll kick things off with the
wrapFetchWithPaymentfunction from thirdweb and a browser client. First, we’ll run our tests in Base Sepolia, and then we’ll switch over to the Base mainnet. More on that can be found here.
Server and client snippets you can adapt
Protecting a FastAPI Endpoint (Sketch)
When you're working with FastAPI, safeguarding your endpoints is super important. Here’s a quick guide on how to do that.
1. Using OAuth2 with Password (and hashing)
First off, let's set up OAuth2 using a password flow. This helps ensure that only the right users can access your endpoint.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
async def login(form: OAuth2PasswordRequestForm = Depends()):
# Here you'd validate the username and password
# After validation, return a token
return {"access_token": "some-token", "token_type": "bearer"}
2. Protecting Your Endpoint
Now that we have the login set up, let’s protect an endpoint by requiring a valid token.
@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
# You’d verify the token here
return {"token": token}
3. Handling Token Verification
Remember to implement the logic for checking if the token is valid. This step is crucial to keep your app secure.
from fastapi import Security
async def get_current_user(token: str = Depends(oauth2_scheme)):
# Decode and verify the token
if not is_valid_token(token):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return token
4. Using the get_current_user Function
You can now use this function in any of your endpoints that need protection.
@app.get("/users/me", response_model=User)
async def read_users_me(current_user: str = Depends(get_current_user)):
return {"user": current_user}
5. Conclusion
In a nutshell, protecting your FastAPI endpoints involves a few simple steps: setting up OAuth2, defining your protected routes, and ensuring your token verification logic is solid.
With these pieces in place, you’ll take a big step towards securing your application! If you want a deeper dive, check out the FastAPI documentation.
from fastapi import FastAPI, Request, Response
import httpx, base64, json, os
app = FastAPI()
FAC = os.getenv("X402_FACILITATOR") # e.g., https://api.cdp.coinbase.com
def mk_req():
return {
"x402Version": 1,
"accepts": [{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1000000",
"resource": "https://api.example.com/v1/premium/search",
"payTo": "0x1234...cAFE",
"asset": "0xA0b8...6eB48",
"extra": {"eip712": {"name":"USD Coin","version":"2"}}
}]
}
@app.get("/v1/premium/search")
async def premium_search(req: Request):
xpay = req.headers.get("x-payment")
if not xpay:
return Response(json.dumps(mk_req()), 402, media_type="application/json")
payload = {"paymentHeader": xpay, "requirement": mk_req()["accepts"][0]}
async with httpx.AsyncClient() as c:
v = (await c.post(f"{FAC}/v2/x402/verify", json=payload)).json()
if not v.get("valid", False):
return Response(json.dumps(mk_req() | {"error": v.get("error","invalid_payment")}), 402)
s = (await c.post(f"{FAC}/v2/x402/settle", json=payload)).json()
res = Response(json.dumps({"result": "ok", "items": []}), media_type="application/json")
res.headers["Access-Control-Expose-Headers"] = "X-PAYMENT-RESPONSE"
res.headers["X-PAYMENT-RESPONSE"] = base64.b64encode(json.dumps(s).encode()).decode()
return res
Client (Browser) Using Thirdweb’s x402 Wrapper:
When you're diving into the world of Thirdweb’s x402 wrapper, here's how you can get started with your client (a.k.a. your browser).
Step 1: Install the Wrapper
Before anything else, you need to bring in the wrapper. You can do this easily with npm:
npm install @thirdweb-dev/sdk
Step 2: Set Up Your Project
Make sure to initialize your project if you haven’t already. You can create a new JavaScript or TypeScript file, and import the necessary modules:
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
Step 3: Create a New Instance
Now that you've got everything set up, it's time to create an instance of the SDK. You’ll need your wallet provider and your chain ID:
const sdk = new ThirdwebSDK(yourWalletProvider, yourChainId);
Step 4: Interact with the Wrapper
Once you're all set, you can start interacting with the x402 wrapper! This allows you to make calls to various contracts and manage your assets effortlessly.
const contract = sdk.getContract(contractAddress);
const result = await contract.call("functionName", params);
Useful Links
Final Thoughts
And there you have it! Getting started with Thirdweb’s x402 wrapper is pretty straightforward. Just follow these steps and you’ll be on your way to building amazing decentralized applications! If you run into any issues, don’t hesitate to check the documentation or reach out to the community. Happy coding!
import { wrapFetchWithPayment } from "thirdweb/x402";
import { createThirdwebClient } from "thirdweb";
import { inAppWallet } from "thirdweb/wallets";
const client = createThirdwebClient({ clientId: process.env.THIRDWEB_ID! });
const wallet = inAppWallet();
const paidFetch = wrapFetchWithPayment({ client, wallet });
const r = await paidFetch("https://api.example.com/v1/premium/search?q=vector+db");
const receipt = atob(r.headers.get("X-PAYMENT-RESPONSE")!);
// use receipt in your audit log UI
Both snippets follow the usual 402 → X‑PAYMENT → X‑PAYMENT‑RESPONSE sequence outlined by x402. You can check it out here.
Enterprise answers to common objections
- “Do we need wallets?” Don’t worry about managing those pesky keys; you can just embed wallets or use agent wallets instead. Facilitators will cover the gas costs for EIP‑3009 transactions, so buyers just need to sign off on authorizations. (docs.cdp.coinbase.com)
- “Which networks and tokens are actually supported?” Right now, we’ve got the Base mainnet (USDC, and fee-free through CDP), Base Sepolia for testing, and Solana (thanks to facilitators). Plus, if you have self-hosted or community facilitators, they can add more EVMs as needed. (docs.cdp.coinbase.com)
- “Is this only for crypto‑native teams?” Not at all! With Workers/Agents and React hooks, we keep the crypto stuff under wraps. Your team can just work with HTTP and headers like they normally do. (developers.cloudflare.com)
Final notes before you ship
- Make sure to specify decimals (atomic units), chains, and those 5-minute validity windows clearly.
- Always link the payment to the resource URL and the method used; don't forget to log the request ID into the receipt object.
- Begin with just one facilitator and a single token (like USDC on Base), track the conversion, and then scale up from there.
x402 has really come into its own lately--thanks to standard headers, hosted facilitators, and edge-native wrappers, you can easily add metered revenue to your existing APIs without needing to overhaul your authentication process. If you're looking for assistance with setting up 402s, fine-tuning pricing, or creating verifiable receipts and dashboards, 7Block Labs can get it done in just days instead of months.
References and further reading
- Check out Coinbase x402, which covers specs, headers, facilitator APIs, and how it all works. You can dive into the details here.
- Looking for network and token support? This includes USDC through EIP‑3009, along with Base/Solana and facilitator models. Get all the info here.
- Don't miss the Cloudflare and Coinbase partnership, which brings Workers/Agents integration into play as of September 23, 2025. More info can be found here.
- Want to understand the HTTP 402 background? MDN has you covered. Check it out here.
- Explore the X‑PAYMENT and X‑PAYMENT‑RESPONSE header patterns along with some credit token examples. You can find these details here.
- Lastly, for some context on L402 (Lightning), don’t forget to check it out on GitHub here.
Like what you're reading? Let's build together.
Get a free 30-minute consultation with our engineering team.
Related Posts
ByAUJay
Building Supply Chain Trackers for Luxury Goods: A Step-by-Step Guide
How to Create Supply Chain Trackers for Luxury Goods
ByAUJay
Building 'Private Social Networks' with Onchain Keys
Creating Private Social Networks with Onchain Keys
ByAUJay
Tokenizing Intellectual Property for AI Models: A Simple Guide
## How to Tokenize “Intellectual Property” for AI Models ### Summary: A lot of AI teams struggle to show what their models have been trained on or what licenses they comply with. With the EU AI Act set to kick in by 2026 and new publisher standards like RSL 1.0 making things more transparent, it's becoming more crucial than ever to get this right.

