# a402 Python SDK

ASGI middleware that gates FastAPI/Starlette endpoints behind [a402](https://github.com/pixel8labs/a402) HTTP payments. The seller never handles keys or crypto — the facilitator does.

## Install

```bash
pip install a402
# With FastAPI extras:
pip install "a402[fastapi]"
```

## Usage

```python
import os
from fastapi import FastAPI
from a402 import A402Middleware, A402Config

app = FastAPI()

app.add_middleware(
    A402Middleware,
    # facilitator_url is optional — defaults to a402's hosted facilitator.
    # Set it only to self-host or point at a staging facilitator.
    config=A402Config(api_key=os.environ["A402_KEY"]),
    routes=[
        {"method": "GET", "path": "/v1/financials", "price": "$0.05"},
        {"path": "/v1/quote", "price": "$0.01"},  # method defaults to GET
    ],
)

@app.get("/v1/financials")
async def get_financials():
    return {"ticker": "NVDA", "revenue": "$60.9B"}
```

### `@pay` decorator

Attach pricing metadata to a route function. Must still be listed in the `routes` dict.

```python
from a402 import pay

@app.get("/v1/report")
@pay("$0.10")
async def get_report():
    return {"report": "..."}
```

## How it works

1. A request arrives with no `X-PAYMENT` header. The middleware calls `POST /facilitator/challenge` with the seller's API key and route price. The 402 response contains an `accepts` array describing the EIP-3009 USDC authorization the client must sign.

2. The client signs the authorization off-chain and retries with an `X-PAYMENT` header (base64-encoded JSON).

3. The middleware decodes the header and calls `POST /facilitator/settle`. On success (HTTP 200) the real handler runs and the response carries `X-PAYMENT-RESPONSE` (base64 settlement receipt). On 402/403 the status and body are forwarded to the client.

The settlement uses EIP-3009 (`transferWithAuthorization`) — the on-chain transfer is confirmed before the 200 is returned, so a 200 from the middleware means funds are settled on the source chain. Cross-chain consolidation via CCTP may still be in progress (check `mintTxHash`).

## Route config keys

| Key | Type | Default |
|-----|------|---------|
| `price` | `"$0.05"` or `0.05` | required |
| `description` | `str` | `"Access to METHOD /path"` |
| `resource` | `str` | `"METHOD /path"` |
