Skip to main content

Orvion SDK for x402 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!")

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.3.2.tar.gz (31.3 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.3.2-py3-none-any.whl (31.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for orvion-0.3.2.tar.gz
Algorithm Hash digest
SHA256 0ada3d7ef723531f06d9870044e7de97f2520d1de8b98b1bbb1a0d7a50ed8d02
MD5 b306b71bb52bb7d9b3219c6465cbbe8c
BLAKE2b-256 ff366d4139f53db32e220a6cb864c27195bfb9ab11189e6cc621625eb3ed4d51

See more details on using hashes here.

File details

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

File metadata

  • Download URL: orvion-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 31.7 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.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b162e07c16b5841fcd39ce2ffccd2552c03883a552fa0c852b711281b023e6fe
MD5 5e79b173f0b1ed0575ecedeb559ec618
BLAKE2b-256 2cb70487db60ddee68c1ef448572d67e9191cdf44a6df6526398544439aa0ee0

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