Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
df70fee
chore: renamed python/x402 to python/legacy
CarsonRoscoe Dec 15, 2025
7794f32
feat: initial Python core SDK
CarsonRoscoe Dec 22, 2025
c4557f6
feat: added core HTTP wrappers
CarsonRoscoe Dec 22, 2025
ef96c6f
feat: added core types
CarsonRoscoe Dec 22, 2025
5ee3754
feat: added evm mechanism for exact v1/v2
CarsonRoscoe Dec 22, 2025
152800c
feat: added httpx client
CarsonRoscoe Dec 22, 2025
a641a21
feat: added requests client
CarsonRoscoe Dec 22, 2025
2bf5e58
feat: added fastapi middleware
CarsonRoscoe Dec 22, 2025
6c3fc09
feat: added flask middleware
CarsonRoscoe Dec 22, 2025
61beb96
feat: added integration tests
CarsonRoscoe Dec 22, 2025
deaa295
feat: added Python SDK to e2e tests
CarsonRoscoe Dec 22, 2025
3ca67a4
python-v2: fix workflow checks (#863)
phdargen Dec 29, 2025
1392ed1
Fix syntax errors and missing imports in manual integration example (…
sohw400 Jan 5, 2026
dc8fc0e
feat: add Python SDK v2 server examples (FastAPI, Flask) (#879)
Ilevk Jan 5, 2026
8872120
feat: add Python v2 client examples (httpx & requests) (#857)
1bcMax Jan 5, 2026
f03cf15
feat(python): Make v2 framework and client dependencies optional extr…
vvsotnikov Jan 6, 2026
6367b43
python-v2: add svm mechanism (#904)
phdargen Jan 7, 2026
8bbd5d0
V2 python bazaar (#929)
phdargen Jan 8, 2026
7443a9b
Add advanced Python client examples (#947)
1bcMax Jan 13, 2026
575b197
Python-v2: facilitator example + e2e (#950)
phdargen Jan 13, 2026
2174331
add paywall builder (#953)
phdargen Jan 14, 2026
79617e9
Add Python custom client example (#954)
1bcMax Jan 14, 2026
3ce5c7d
feat(v2-sdk): support async dynamic hooks for price and metadata (#900)
shuhei0866 Jan 14, 2026
303bed8
python-v2: make create_facilitator_config work with both V1 and V2 (#…
phdargen Jan 15, 2026
2131a51
feat: add Python SDK v2 server advanced example (FastAPI) (#952)
Ilevk Jan 15, 2026
923c714
fix: python v2 x402HTTPAdapter retry logic (#978)
Ilevk Jan 16, 2026
77991f7
Python-v2: async lifecycle hooks (#975)
phdargen Jan 16, 2026
cae0546
Update Python SDK Docs for v2 (#976)
manifoldfrs Jan 21, 2026
b6d8343
fix: Python facilitator e2e code
CarsonRoscoe Jan 21, 2026
5347407
fix: lint
CarsonRoscoe Jan 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/check_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
run: uv sync --all-extras --dev

- name: Run Tests
run: uv run python -m pytest
run: uv run pytest

lint-python:
runs-on: ubuntu-latest
Expand Down
166 changes: 96 additions & 70 deletions docs/core-concepts/bazaar-discovery-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,14 @@ Fetch the list of available x402 services using the facilitator client:
import { HTTPFacilitatorClient } from "@x402/core/http";
import { withBazaar } from "@x402/extensions";

// Create facilitator client with Bazaar discovery extension
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator"
});
const client = withBazaar(facilitatorClient);

// Fetch all available services
const response = await client.extensions.discovery.listResources({ type: "http" });

// NOTE: in an MCP context, you can see the full list then decide which service to use

// Find services under $0.10
// Filter services under $0.10
const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals)

Expand All @@ -115,28 +111,26 @@ const affordableServices = response.items.filter(item =>

{% tab title="Python" %}
```python
from x402.facilitator import FacilitatorClient

# Set up facilitator client (defaults to https://x402.org/facilitator)
facilitator = FacilitatorClient()
from x402.http import FacilitatorConfig, HTTPFacilitatorClient

# Fetch all available services
response = await facilitator.list()
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)

# NOTE: in an MCP context, you can see the full list then decide which service to use
response = await facilitator.list_resources(type="http")

# Find services under $0.10
# Filter services under $0.10
usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
max_price = 100000 # $0.10 in USDC atomic units (6 decimals)

affordable_services = [
item
for item in response.items
if any(
payment_req.asset == usdc_asset
and int(payment_req.max_amount_required) < max_price
for payment_req in item.accepts
)
item
for item in response.items
if any(
payment_req.asset == usdc_asset
and int(payment_req.max_amount_required) < max_price
for payment_req in item.accepts
)
]
```
{% endtab %}
Expand Down Expand Up @@ -185,28 +179,40 @@ console.log("Response data:", response.data);

{% tab title="Python" %}
```python
from x402.client import X402Client
import asyncio

from eth_account import Account

# Set up your payment account
account = Account.from_key("0xYourPrivateKey")
client = X402Client(account)
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client

# Select a service from discovery
selected_service = affordable_services[0]

# Select the payment method of your choice
selected_payment_requirements = selected_service.accepts[0]
input_schema = selected_payment_requirements.output_schema.input
async def main() -> None:
account = Account.from_key("0xYourPrivateKey")
client = x402Client()
register_exact_evm_client(client, EthAccountSigner(account))

# Make the request
response = client.request(
method=input_schema.method,
url=input_schema.resource,
params={"location": "San Francisco"} # Based on input_schema
)
# Select a service from discovery (from Step 1)
selected_service = affordable_services[0]

# Select the payment method of your choice
selected_payment_requirements = selected_service.accepts[0]
input_schema = selected_payment_requirements.output_schema.input

# Make the request using httpx client
async with x402HttpxClient(client) as http:
response = await http.request(
method=input_schema.method,
url=input_schema.resource,
params={"location": "San Francisco"} # Based on input_schema
)
await response.aread()
print(f"Response data: {response.json()}")

print(f"Response data: {response}")

asyncio.run(main())
```
{% endtab %}
{% endtabs %}
Expand Down Expand Up @@ -272,44 +278,64 @@ app.use(paymentMiddleware(routes, server));

{% tab title="Python" %}
```python
from x402.middleware.fastapi import payment_middleware
from x402.facilitators import cdp_facilitator

app.middleware("http")(
payment_middleware(
routes={
"/weather": {
"price": "$0.001",
"network": "eip155:8453",
"resource": "0xYourAddress",
"description": "Get current weather data for any location",
"extensions": {
"bazaar": {
"discoverable": True,
"inputSchema": {
"queryParams": {
"location": {
"type": "string",
"description": "City name or coordinates",
"required": True
}
}
},
"outputSchema": {
"type": "object",
"properties": {
"temperature": {"type": "number"},
"conditions": {"type": "string"},
"humidity": {"type": "number"}
}
from fastapi import FastAPI

from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.middleware.fastapi import PaymentMiddlewareASGI
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer

app = FastAPI()

# Create facilitator client (CDP mainnet)
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://api.cdp.coinbase.com/platform/v2/x402")
)

# Create resource server and register EVM scheme
server = x402ResourceServer(facilitator)
server.register("eip155:8453", ExactEvmServerScheme())

# Define routes with Bazaar discovery metadata
routes: dict[str, RouteConfig] = {
"GET /weather": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
pay_to="0xYourAddress",
price="$0.001",
network="eip155:8453",
),
],
mime_type="application/json",
description="Get current weather data for any location",
extensions={
"bazaar": {
"discoverable": True,
"inputSchema": {
"queryParams": {
"location": {
"type": "string",
"description": "City name or coordinates",
"required": True,
}
}
}
},
"outputSchema": {
"type": "object",
"properties": {
"temperature": {"type": "number"},
"conditions": {"type": "string"},
"humidity": {"type": "number"},
},
},
}
},
facilitator=cdp_facilitator
)
)
),
}

app.add_middleware(PaymentMiddlewareASGI, routes=routes, server=server)
```
{% endtab %}

Expand Down
32 changes: 32 additions & 0 deletions docs/core-concepts/network-and-token-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,38 @@ schemes := []ginmw.SchemeConfig{
}
```
{% endtab %}

{% tab title="Python" %}
```python
from x402.http import FacilitatorConfig, HTTPFacilitatorClient, PaymentOption
from x402.http.types import RouteConfig
from x402.mechanisms.evm.exact import ExactEvmServerScheme
from x402.server import x402ResourceServer

# Create facilitator client for your network
facilitator = HTTPFacilitatorClient(
FacilitatorConfig(url="https://your-facilitator.com")
)

# Create server and register EVM scheme for your network
server = x402ResourceServer(facilitator)
server.register("eip155:43114", ExactEvmServerScheme()) # Avalanche mainnet

# Now use any CAIP-2 network identifier in your routes:
routes: dict[str, RouteConfig] = {
"GET /api/data": RouteConfig(
accepts=[
PaymentOption(
scheme="exact",
price="$0.001",
network="eip155:43114", # Avalanche mainnet
pay_to="0xYourAddress",
),
],
),
}
```
{% endtab %}
{% endtabs %}

**Key Points:**
Expand Down
Loading
Loading