Python SDK
The Orvion Python SDK provides seamless integration with FastAPI for creating payment-protected API endpoints using the x402 protocol.
Quick Start
1. Install the SDK
pip install orvion
2. Add Middleware
from fastapi import FastAPIfrom orvion.fastapi import OrvionMiddlewareimport osapp = FastAPI()# Add the Orvion middlewareapp.add_middleware(OrvionMiddleware,api_key=os.environ["ORVION_API_KEY"])
3. Protect Endpoints
from orvion.fastapi import require_paymentfrom fastapi import Request# Define a protected endpoint with pricing@app.get("/api/premium/data")@require_payment(amount="0.10", currency="USDC")async def premium_data(request: Request):return {"data": "Premium content!","paid": request.state.payment.amount}
Pre-built Payment Router (NEW in v0.2)
Eliminate boilerplate by using the pre-built payment router:
from orvion import OrvionClientfrom orvion.fastapi import create_payment_routerclient = OrvionClient(api_key=os.environ["ORVION_API_KEY"])# Add all payment endpoints with one line!app.include_router(create_payment_router(client),prefix="/api/payments",)# This adds:# POST /api/payments/confirm - Confirm wallet payment# POST /api/payments/cancel/{id} - Cancel pending charge# GET /api/payments/state/{id} - Get charge state for UI# GET /api/payments/charge/{id} - Get full charge details
OrvionMiddleware
The middleware handles route registration, payment verification, and request state management.
Configuration
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| api_key | str | Optional | Your Orvion API key (required) | — |
| base_url | str? | Optional | Custom API base URL (default: https://api.orvion.sh) | — |
| cache_ttl_seconds | float | Optional | Route cache TTL (default: 60.0) | — |
| transaction_header | str | Optional | Header for transaction ID (default: 'X-Transaction-Id') | — |
| customer_header | str | Optional | Header for customer ID (default: 'X-Customer-Id') | — |
| register_on_first_request | bool | Optional | Auto-register routes on first request (default: True) | — |
@require_payment Decorator
Mark endpoints as payment-protected with configurable pricing.
Parameters
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
| amount | str? | Optional | Price per request (e.g., '0.10') | — |
| currency | str | Optional | Currency code (default: 'USD') | — |
| name | str? | Optional | Friendly name for dashboard/402 response | — |
| description | str? | Optional | Description shown in 402 response | — |
| allow_anonymous | bool? | Optional | Allow requests without customer ID (default: True) | — |
| customer_resolver | Callable? | Optional | Function to extract customer ID from request | — |
| hosted_checkout | bool | Optional | Enable hosted checkout mode - redirects to pay.orvion.sh (default: False) | — |
| return_url | str? | Optional | Return URL for hosted checkout. Auto-derived using convention: /api/foo → /foo | — |
Always place @require_payment under @app.get/@app.post. The decorator order matters!
Examples
# Basic usage@app.get("/api/basic")@require_payment(amount="0.01", currency="USDC")async def basic_endpoint(request: Request):return {"data": "..."}# With metadata@app.get("/api/premium")@require_payment(amount="1.00",currency="USDC",name="Premium API Access",description="Full access to premium features",)async def premium_endpoint(request: Request):return {"data": "..."}# Require customer identification@app.get("/api/user-data")@require_payment(amount="0.05",currency="USDC",allow_anonymous=False,customer_resolver=lambda req: req.headers.get("X-User-Id"),)async def user_data(request: Request):return {"user": request.state.payment.customer_ref}# Hosted checkout mode - redirects to pay.orvion.sh@app.get("/premium")@require_payment(amount="1.00",currency="USDC",hosted_checkout=True,)async def premium_hosted(request: Request):return {"message": "Premium content after hosted checkout!"}
New Client Methods (v0.2)
The SDK now includes powerful client methods for payment operations:
from orvion import OrvionClientasync with OrvionClient(api_key="your-api-key") as client:# Health check & API key validationhealth = await client.health_check()print(f"Organization: {health.organization_id}")# Create a chargecharge = await client.create_charge(amount="0.10",currency="USDC",)# Get charge state (optimized for UI widgets)state = await client.get_charge_state(charge.id)print(f"Status: {state.status}")# Confirm wallet paymentresult = await client.confirm_payment(transaction_id=charge.id,tx_hash="blockchain_tx_signature...",)# Cancel a pending chargecancelled = await client.cancel_charge(charge.id)
Accessing Payment Info
After successful payment verification, payment details are available on request.state.payment:
@app.get("/api/premium")@require_payment(amount="0.10", currency="USDC")async def premium(request: Request):payment = request.state.paymentreturn {"transaction_id": payment.transaction_id,"amount": payment.amount,"currency": payment.currency,"customer_ref": payment.customer_ref,}
Route Registration
Routes are automatically registered with Orvion when your app starts.
Explicit Startup Registration
For immediate registration at startup, use sync_routes() in your lifespan:
from contextlib import asynccontextmanagerfrom orvion import OrvionClientfrom orvion.fastapi import OrvionMiddleware, sync_routes@asynccontextmanagerasync def lifespan(app: FastAPI):client = OrvionClient(api_key=os.environ["ORVION_API_KEY"])# Verify API key on startuphealth = await client.health_check()if health.api_key_valid:print(f"✓ Connected to org: {health.organization_id}")# Register routescount = await sync_routes(app, client)print(f"✓ Registered {count} protected routes")yieldawait client.close()app = FastAPI(lifespan=lifespan)app.add_middleware(OrvionMiddleware,api_key=os.environ["ORVION_API_KEY"],register_on_first_request=False, # Already synced)
Complete Example
from fastapi import FastAPI, Requestfrom orvion import OrvionClientfrom orvion.fastapi import (OrvionMiddleware,require_payment,create_payment_router,)import osapp = FastAPI(title="My Premium API")client = OrvionClient(api_key=os.environ["ORVION_API_KEY"])# Add middlewareapp.add_middleware(OrvionMiddleware, api_key=os.environ["ORVION_API_KEY"])# Add pre-built payment routerapp.include_router(create_payment_router(client), prefix="/api/payments")# Free endpoint@app.get("/")async def root():return {"message": "Welcome! Visit /api/premium for paid content."}# Premium endpoint - 0.01 USDC@app.get("/api/premium")@require_payment(amount="0.01",currency="USDC",name="Premium Content",)async def premium(request: Request):return {"message": "Welcome to premium!","paid": request.state.payment.amount,}
Hosted Checkout Mode
For web applications where users interact via browser, use hosted checkout mode:
# API endpoint - protected with payment@app.get("/api/premium")@require_payment(amount="1.00",currency="USDC",hosted_checkout=True, # Redirect to pay.orvion.sh)async def premium_api(request: Request):return {"message": "Premium content!"}# Frontend page - serves the UI@app.get("/premium")async def premium_page():return FileResponse("static/premium.html")
Automatic URL Convention
The SDK uses a convention-based approach for seamless UX:
- API at
/api/premium→ Frontend at/premium - The
/apiprefix is automatically stripped - Users are redirected to the frontend page after payment (not the API)
No return_url configuration needed! Just add hosted_checkout=True and follow the convention.
# That's all you need! No return_url required.@app.get("/api/premium")@require_payment(amount="1.00", currency="USDC", hosted_checkout=True)async def premium(request: Request):return {"data": "premium"}# Flow:# 1. User on /premium clicks "Pay" → redirects to /api/premium# 2. SDK creates charge, redirects to pay.orvion.sh# 3. After payment, user returns to /api/premium?charge_id=xxx# 4. SDK verifies, then redirects to /premium?charge_id=xxx&status=succeeded# 5. Frontend shows success message
Before using hosted checkout, configure allowed domains in Settings → Domains to enable return URL validation.
See the Hosted Checkout Guide for complete documentation.
Related Documentation
- Protected Routes Overview - General protected routes guide
- Hosted Checkout - Redirect-based payment flow for web apps
- Python SDK - Full Python SDK reference
- API Reference - API endpoints and schemas