Skip to content

Conversation

@Ilevk
Copy link

@Ilevk Ilevk commented Dec 29, 2025

Description

Add FastAPI and Flask example servers demonstrating x402 payment middleware integration.

FastAPI (examples/python/servers/fastapi/)

  • Payment-gated API server with PaymentMiddlewareASGI
  • Test client using x402HttpxClient
  • Comprehensive README with setup and usage guide

Flask (examples/python/servers/flask/)

  • Payment-gated API server with PaymentMiddleware
  • Test client using x402HttpxClient
  • Comprehensive README with setup and usage guide

Both examples include three endpoints:

Endpoint Payment Required Price
GET /health No -
GET /weather Yes $0.01 USDC
GET /premium/content Yes $0.01 USDC

Tests

Manually tested both servers with the included test clients:

  cd examples/python/servers/fastapi
  uv sync && uv run python main.py

  # In another terminal
  uv run python test_client.py

  Output:
  Wallet address: 0x...

  --- Testing /health (no payment) ---
  Status: 200

  --- Testing /weather (requires payment) ---
  Status: 200

  --- Testing /premium/content (requires payment) ---
  Status: 200

Flask example tested with identical results.

Linting passed for both:

  uv run ruff check .
  # All checks passed!

Checklist

  • I have formatted and linted my code
  • All new and existing tests pass
  • My commits are signed (required for merge) -- you may need to rebase if you initially pushed unsigned commits

@vercel
Copy link

vercel bot commented Dec 29, 2025

@Ilevk is attempting to deploy a commit to the Coinbase Team on Vercel.

A member of the Team first needs to authorize it.

@Ilevk
Copy link
Author

Ilevk commented Dec 29, 2025

@phdargen Hi, I hope you're doing well.
I've just create a PR for FastAPI / Flask examples. please take a look when you're available. many thanks!

Note: The examples require removing the following line from python/x402/pyproject.toml:
"extensions" = "x402/extensions"
Otherwise the uv sync fails because the extensions directory doesn't exist.

by the way I found an issue while testing with the example servers: x402HTTPAdapter doesn't retry correctly when calling multiple different paid endpoints sequentially in the same session. The first paid endpoint works (402 → retry → 200), but subsequent different endpoints return 402 without retry.

  Example:
  session.get("/weather")        # 200 ✅
  session.get("/premium/content") # 402 ❌ (no retry)

That's the reason why I've used x402HttpxClient for the test client code, which works correctly in the same scenario.
Let me know if you'd like me to take a look at fixing this.

@Ilevk
Copy link
Author

Ilevk commented Dec 29, 2025

@phdargen phdargen self-assigned this Dec 29, 2025
@phdargen
Copy link
Contributor

phdargen commented Dec 29, 2025

Hi @Ilevk, thanks a lot for your contribution! Could you please rebase against coinbase:feat/python-v2-sdk? This should fix the failing workflow checks and the problem with the extensions in python/x402/pyproject.toml

@phdargen
Copy link
Contributor

It's great that you created the test_client.py scripts to test your own implementation but these should not be committed.

Each server example should only include server related code. The servers can then be tested by running any of the client examples (including typescript/go)

@phdargen
Copy link
Contributor

by the way I found an issue while testing with the example servers: x402HTTPAdapter doesn't retry correctly when calling multiple different paid endpoints sequentially in the same session. The first paid endpoint works (402 → retry → 200), but subsequent different endpoints return 402 without retry.

  Example:
  session.get("/weather")        # 200 ✅
  session.get("/premium/content") # 402 ❌ (no retry)

That's the reason why I've used x402HttpxClient for the test client code, which works correctly in the same scenario. Let me know if you'd like me to take a look at fixing this.

Good catch, this seems to be the same issue reported here #399. So this bug was already in v1.

Yes, would be great if you could look into it! When you have a fix ready, please open a new PR for this targeting coinbase:feat/python-v2-sdk

@Ilevk Ilevk force-pushed the feat/python-v2-sdk-middleware branch from 7d6bb50 to a348d65 Compare December 30, 2025 14:49
@Ilevk
Copy link
Author

Ilevk commented Dec 30, 2025

@phdargen I've just done rebase and removing .python-version, test_client.py

And could you set me as an assignee for this PR?

@Ilevk
Copy link
Author

Ilevk commented Dec 30, 2025

Good catch, this seems to be the same issue reported here #399. So this bug was already in v1.
Yes, would be great if you could look into it! When you have a fix ready, please open a new PR for this targeting coinbase:feat/python-v2-sdk

You mean that PR 399 would be closed soon?, I'd love to take a look that issue.

Should I create a new Issue about that with referencing original issue or do you want me to just continue with this Issue(#398)?

@Ilevk Ilevk requested a review from phdargen December 30, 2025 14:59
@@ -0,0 +1 @@
ADDRESS=
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest renaming to EVM_ADDRESS in anticipation of svm mechanism to be added soon and adding facilitator URL

Suggested change
ADDRESS=
EVM_ADDRESS=
FACILITATOR_URL=https://x402.org/facilitator

Copy link
Author

@Ilevk Ilevk Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated files here 7e1f56a

0xsarawut

This comment was marked as spam.

Comment on lines +2 to +3
name = "x402-v2-flask-example"
version = "0.1.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what name and version convention we should use here, will check with @CarsonRoscoe once he is back

version = "0.1.0"
description = "Example of using a Flask server with x402 middleware"
readme = "README.md"
license = { text = "MIT" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x402 uses Apache-2.0, not MIT. We don't have license in other examples, maybe better to just remove

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed it here 0ff914c

Comment on lines 12 to 22
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Typing :: Typed",
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think classifiers is not needed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed it here 0ff914c

Comment on lines 51 to 58
accepts=[
PaymentOption(
scheme="exact",
pay_to=ADDRESS,
price="$0.01",
network=NETWORK,
)
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest to add description and mime_type to each endpoint

Suggested change
accepts=[
PaymentOption(
scheme="exact",
pay_to=ADDRESS,
price="$0.01",
network=NETWORK,
)
]
accepts=[
PaymentOption(
scheme="exact",
pay_to=ADDRESS,
price="$0.01",
network=NETWORK,
)
]
description="Weather report",
mime_type="application/json",

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added descriptions and mime_type, here d905e0b

@coinbase coinbase deleted a comment from 0xsarawut Dec 30, 2025
@coinbase coinbase deleted a comment from 0xsarawut Dec 30, 2025
@phdargen
Copy link
Contributor

Thanks @Ilevk, the examples look good! Just a few minor comments, see above

@phdargen
Copy link
Contributor

Once the svm mechanism is ready, we might want to add a solana PaymentOption as well

@phdargen
Copy link
Contributor

For typescript v2 we also have advanced examples that show usage of bazaar (not yet implemented for python), hooks, dynamic price/payTo and custom money definition.

Would be nice to add this for python as well (as much as currently possible), you can pick either fastapi or flask to implement this as you prefer

@phdargen
Copy link
Contributor

Another thing would be a custom example that demonstrates how to implement x402 payment handling manually without using pre-built middleware packages

@phdargen
Copy link
Contributor

Good catch, this seems to be the same issue reported here #399. So this bug was already in v1.
Yes, would be great if you could look into it! When you have a fix ready, please open a new PR for this targeting coinbase:feat/python-v2-sdk

You mean that PR 399 would be closed soon?, I'd love to take a look that issue.

Should I create a new Issue about that with referencing original issue or do you want me to just continue with this Issue(#398)?

PR 399 is quite old and seems inactive, so likely we will have to close it. In any case, PR 399 targets the legacy implementation. The most important thing is that we fix it for the new v2 implementation.

So as a first step, I would suggest you open a new PR targeting the coinbase:feat/python-v2-sdk branch with the fix for the v2 implementation only.
No need to open a new issue or reference an existing one as python v2 in not live yet, just in development.

We can then decide later if and how we fix the legacy implementation as well

@Ilevk Ilevk force-pushed the feat/python-v2-sdk-middleware branch from 738726b to c26875c Compare December 31, 2025 11:26
@Ilevk Ilevk force-pushed the feat/python-v2-sdk-middleware branch from c26875c to 7e1f56a Compare December 31, 2025 11:27
@Ilevk
Copy link
Author

Ilevk commented Dec 31, 2025

Let me check the other comments tomorrow. thanks for comments Happy new year!

For typescript v2 we also have [advanced examples (https://github.com/coinbase/x402/tree/main/examples/typescript/servers/advanced) that show usage of bazaar (not yet implemented for python), hooks, dynamic price/payTo and custom money definition.
Would be nice to add this for python as well (as much as currently possible), you can pick either fastapi or flask to implement this as you prefer

@Ilevk
Copy link
Author

Ilevk commented Jan 5, 2026

Hi @phdargen, I've been thinking about an advanced example. I'd be nice to contribute. but should I put together same PR?, actually I wouldn't like to keep this PR in review.

so why don't we finish this PR first, after that I'll create a new PR for advanced examples with new issue.
or you would think put together same PR, just let me know. I'm going to take a look advanced examples you mentioned.

@phdargen
Copy link
Contributor

phdargen commented Jan 5, 2026

Agreed @Ilevk, let's get this in first. Would also be useful for me to have the basic server example in the feat/python-v2-sdk branch to do some manual testing

Please open a new PR for the advanced and/or custom examples when you are ready, no need to open new issues.
I will update the TODO list accordingly

@phdargen phdargen merged commit 167ee41 into coinbase:feat/python-v2-sdk Jan 5, 2026
12 of 13 checks passed
@phdargen
Copy link
Contributor

phdargen commented Jan 5, 2026

Merged and updated the TODO list @Ilevk: #841 (comment)

Note that I also added a new TODO item for fixing the x402HTTPAdapter retry logic (as discussed above) and assigned it to you. No problem at all if you are too busy or would rather take on something else, just let me know and I am happy to assign myself

@Ilevk
Copy link
Author

Ilevk commented Jan 5, 2026

@phdargen I’ll first take a look at the advanced example, and then I’ll check the x402HTTPAdapter case. and I've updated my TODO list as well in 841 PR

I really appreciate it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants