Skip to main content

Orvion SDK for x402 V2 payment-protected APIs

Project description

Orvion Python SDK

Python SDK for integrating x402 payment-protected APIs with Orvion.

Installation

pip install orvion

# With FastAPI support
pip install orvion[fastapi]

Quick Start

FastAPI Integration

import os
from fastapi import FastAPI, Request
from orvion.fastapi import OrvionMiddleware, require_payment

app = FastAPI()

# Initialize Orvion middleware
app.add_middleware(
    OrvionMiddleware,
    api_key=os.environ["ORVION_API_KEY"],
)

# Protect an endpoint with payment requirement
@app.get("/api/premium/data")
@require_payment()  # Uses price from dashboard
async def premium_data(request: Request):
    # Access payment info
    payment = request.state.payment
    return {
        "data": "Premium content!",
        "paid": payment.amount,
        "transaction_id": payment.transaction_id,
    }

# Override price in code
@app.get("/api/reports/generate")
@require_payment(amount="5.00", currency="USD")
async def generate_report(request: Request):
    return {"report": "..."}

# Require customer identification (no anonymous access)
@app.get("/api/ai/chat")
@require_payment(allow_anonymous=False)
async def ai_chat(request: Request):
    customer_id = request.state.payment.customer_ref
    return {"response": "..."}

Standalone Client

from orvion import OrvionClient

client = OrvionClient(api_key="your_api_key")

# Create a charge
charge = await client.create_charge(
    amount="0.10",
    currency="USD",
    customer_ref="user_123",
    resource_ref="protected_route:abc-123",
)

print(f"Charge ID: {charge.id}")
print(f"Payment URL: {charge.x402_requirements}")

# Verify a payment
result = await client.verify_charge(
    transaction_id="tx_abc123",
    resource_ref="protected_route:abc-123",
)

if result.verified:
    print("Payment verified!")

# Process a facilitator payment (x402 V2)
from orvion import build_evm_authorization, build_evm_payment_payload

authorization = build_evm_authorization(
    from_address="0x...",
    to_address="0x...",
    value="1000000",
    valid_after="1716150000",
    valid_before="1716153600",
    nonce="0x...",
)

payment_payload = build_evm_payment_payload(
    signature="0x...",
    authorization=authorization,
    network="base",
)

result = await client.process_payment(
    transaction_id=charge.id,
    payment_payload=payment_payload,
)

if result.success:
    print(f"Payment confirmed: {result.tx_hash}")

# For Solana, build a payload from a signed transaction
from orvion import build_solana_payment_payload

solana_payload = build_solana_payment_payload(
    transaction="base64_tx",
    network="solana-devnet",
)

Configuration

Environment Variables

Middleware Options

app.add_middleware(
    OrvionMiddleware,
    api_key="your_api_key",
    base_url="https://api.orvion.sh",  # Custom API URL
    cache_ttl_seconds=60,  # Route config cache TTL
    transaction_header="X-Transaction-Id",  # Custom header name
    customer_header="X-Customer-Id",  # Custom header name
)

Decorator Options

@require_payment(
    amount="0.10",  # Override dashboard price
    currency="USD",
    allow_anonymous=False,  # Require customer identification
    customer_resolver=lambda req: req.state.user.id,  # Custom customer ID extraction
    hosted_checkout=True,  # Enable hosted checkout mode (redirects to pay.orvion.sh)
)

Hosted Checkout Mode

For web applications, use hosted checkout mode for a seamless payment experience:

# API endpoint - protected with payment
@app.get("/api/premium")
@require_payment(
    amount="1.00",
    currency="USDC",
    hosted_checkout=True,  # Just add this!
)
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 strips /api prefix automatically:

  • API at /api/premium → Frontend at /premium
  • After payment, users are redirected to /premium?charge_id=xxx&status=succeeded
  • No return_url configuration needed!

Testing

The SDK includes comprehensive testing utilities and is fully tested with pytest.

Testing Utilities

from orvion.testing import mock_orvion, fake_payment

# Mock all Orvion calls
with mock_orvion(always_approve=True):
    response = client.get("/api/premium/data")
    assert response.status_code == 200

# Create fake payment for testing
request.state.payment = fake_payment(
    amount="0.10",
    currency="USD",
    transaction_id="test_tx_123",
)

Running Tests

# Install dev dependencies
pip install -e ".[dev,fastapi]"

# Run all tests
pytest

# Run tests with coverage
pytest --cov=orvion --cov-report=html

# Run specific test categories
pytest tests/unit/          # Unit tests only
pytest tests/integration/   # Integration tests only
pytest tests/e2e/          # E2E tests (requires ORVION_STAGING_API_KEY)

# Run with linting and type checking
ruff check orvion tests
mypy orvion

Test Structure

The SDK uses a three-layer testing approach:

  • Unit Tests (tests/unit/) - Pure logic tests for matcher, cache, and models
  • Integration Tests (tests/integration/) - HTTP mocking with respx for client and middleware
  • E2E Tests (tests/e2e/) - Smoke tests against staging API

HTTP Mocking with RESPX

The SDK uses respx for HTTP mocking in integration tests:

import respx
from httpx import Response

# Mock API endpoints
with respx.mock(base_url="https://api.orvion.sh") as mock:
    mock.post("/v1/charges").mock(
        return_value=Response(
            200,
            json={
                "id": "custom_charge",
                "amount": "1.00",
                "currency": "USD",
                "status": "pending",
            },
        )
    )
    
    charge = await client.create_charge(amount="1.00", currency="USD")
    assert charge.id == "custom_charge"

FastAPI Middleware Testing

Test FastAPI middleware with TestClient:

from fastapi import FastAPI
from fastapi.testclient import TestClient
from orvion.fastapi import OrvionMiddleware, require_payment

app = FastAPI()
app.add_middleware(OrvionMiddleware, api_key="test_key")

@app.get("/api/premium/data")
@require_payment()
async def premium_data(request: Request):
    return {"data": "premium", "payment": request.state.payment}

# Test
client = TestClient(app)
response = client.get(
    "/api/premium/data",
    headers={"X-Payment-Transaction": "valid_tx_123"}
)
assert response.status_code == 200
assert response.json()["payment"] is not None

Telemetry

Opt-in telemetry is available for monitoring SDK usage:

from orvion import OrvionClient
from orvion.telemetry import TelemetryConfig

client = OrvionClient(
    api_key="your_key",
    telemetry=TelemetryConfig(
        enabled=True,
        service_name="my-app",
        service_version="1.0.0",
    ),
)

Privacy: Telemetry is opt-in and never collects PII (no customer refs, transaction IDs, or amounts).

Code Quality

The SDK maintains high code quality standards:

# Format code
black orvion tests

# Sort imports
isort orvion tests

# Type checking
mypy orvion

# Linting
ruff check orvion tests

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

orvion-0.5.0.tar.gz (34.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

orvion-0.5.0-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

Details for the file orvion-0.5.0.tar.gz.

File metadata

  • Download URL: orvion-0.5.0.tar.gz
  • Upload date:
  • Size: 34.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for orvion-0.5.0.tar.gz
Algorithm Hash digest
SHA256 4224453f985bdd9f7207a180c61acf2c568aa10f88b987d91309590ac982a63d
MD5 02ac30f9176ac90019c9420c88380bc5
BLAKE2b-256 3ed7da62ae85be3cb4c730b8282fd522c94fabed45156ad6f686e5aba68fe0bb

See more details on using hashes here.

File details

Details for the file orvion-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: orvion-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 35.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for orvion-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 96d32384890cf14c62e313291e5ed8b91d9db32bcd1ba066c7f3191a1a331955
MD5 b46070039119fff9f1a2b4391a9b657b
BLAKE2b-256 118aafcb640de26f598f68a91c7d72abc8682d39988644b8b18df226eda0ac91

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page