> ## Documentation Index
> Fetch the complete documentation index at: https://docs.amrood.io/llms.txt
> Use this file to discover all available pages before exploring further.

# HTTP 402 Paywall

> x402-style per-call API monetization with INR

# HTTP 402 Paywall

Amrood supports an x402-style payment protocol over HTTP — any API can charge per-call in INR, and AI agents with Amrood wallets can pay automatically. This brings the machine-to-machine payment model of x402 to fiat currency.

## How It Works

```mermaid theme={null}
sequenceDiagram
    participant Agent as AI Agent
    participant API as Paywalled API
    participant Amrood as Amrood Network

    Agent->>API: 1. GET /premium-data
    API-->>Agent: 2. HTTP 402 + X-AMROOD-PAY header
    Agent->>Amrood: 3. Pay ₹5 to @databot (with nonce)
    Amrood-->>Agent: 4. Transaction ID
    Agent->>API: 5. GET /premium-data + X-AMROOD-PAYMENT header
    API->>Amrood: 6. Verify payment via /v1/transactions/{id}/verify
    Amrood-->>API: 7. { verified: true }
    API-->>Agent: 8. 200 OK (premium data)
```

### Step by step

1. Agent makes a normal HTTP request to an API endpoint
2. Server returns **HTTP 402 Payment Required** with an `X-AMROOD-PAY` header containing payment instructions (amount, payee, nonce)
3. Agent pays the specified payee via Amrood's `POST /v1/agents/{id}/pay` endpoint, using the nonce as the payment reference
4. Amrood returns a transaction ID
5. Agent retries the original request with an `X-AMROOD-PAYMENT` header containing the transaction proof
6. Server verifies the payment via Amrood's verification endpoint
7. Amrood confirms the payment is valid
8. Server returns the requested resource

## For API Developers (Server Side)

Install the `amrood-paywall` package:

```bash theme={null}
pip install amrood-paywall
```

Add a one-line decorator to any FastAPI endpoint:

```python theme={null}
from fastapi import FastAPI, Request
from amrood_paywall import amrood_pay

app = FastAPI()

@app.get("/api/premium-data")
@amrood_pay(amount="5.00", pay_to="databot")
async def get_premium_data(request: Request):
    return {"data": "premium content worth paying for"}
```

Set the `AMROOD_AGENT_KEY` environment variable to your agent's API key so the server can verify incoming payments.

### How the decorator works

1. On first request (no payment proof), returns HTTP 402 with:
   ```
   X-AMROOD-PAY: base64({ "payTo": "databot", "amount": "5.00", "asset": "INR", "nonce": "uuid" })
   ```
2. On retry with `X-AMROOD-PAYMENT` header, verifies the payment via `GET /v1/transactions/{txn_id}/verify`
3. If verified, passes the request through to your endpoint
4. Nonces are tracked to prevent replay attacks (one payment = one access)

### Configuration

```python theme={null}
@amrood_pay(
    amount="10.00",      # Amount in INR
    pay_to="myagent",    # Your agent handle or ID
)
```

| Environment Variable | Description                                              |
| -------------------- | -------------------------------------------------------- |
| `AMROOD_AGENT_KEY`   | Your agent's API key (required for payment verification) |
| `AMROOD_API_URL`     | API base URL (default: `https://api.amrood.io`)          |

## For AI Agents (Client Side)

### Using the MCP tool

The `amrood_http_pay` tool handles the entire 402 flow automatically:

```text theme={null}
> Fetch data from https://api.example.com/premium-data

Claude: The API requires payment of ₹5.00 to @databot.
        Paid ₹5.00 automatically. Here's the data: { ... }
```

### Using the API directly

If you're building a custom client:

```python theme={null}
import httpx, json, base64

# Step 1: Make the request
resp = httpx.get("https://api.example.com/premium-data")

if resp.status_code == 402:
    # Step 2: Parse payment instructions
    pay_header = resp.headers["x-amrood-pay"]
    instructions = json.loads(base64.b64decode(pay_header))
    # { "payTo": "databot", "amount": "5.00", "asset": "INR", "nonce": "uuid" }

    # Step 3: Pay via Amrood
    pay_resp = httpx.post(
        f"https://api.amrood.io/v1/agents/{agent_id}/pay",
        headers={"x-agent-key": agent_key},
        json={
            "to": instructions["payTo"],
            "amount": float(instructions["amount"]),
            "reference": instructions["nonce"],
        },
    )
    txn_id = pay_resp.json()["payment_id"]

    # Step 4: Retry with payment proof
    proof = base64.b64encode(json.dumps({
        "version": 1,
        "transactionId": txn_id,
        "fromAgent": agent_id,
        "nonce": instructions["nonce"],
    }).encode()).decode()

    result = httpx.get(
        "https://api.example.com/premium-data",
        headers={"x-amrood-payment": proof},
    )
    print(result.json())
```

## Transaction Verification API

The verification endpoint allows API servers to confirm that a payment was made:

```bash theme={null}
GET /v1/transactions/{txn_id}/verify?expected_payee=databot&expected_amount=5.00&nonce=uuid
```

Headers:

```
x-agent-key: agk_live_xxx  (payee's agent key)
```

Response:

```json theme={null}
{
  "verified": true,
  "transaction_id": "pay_abc123",
  "from": "clientbot",
  "to": "databot",
  "amount": "5.00",
  "asset": "INR",
  "created_at": "2025-06-15T10:30:00Z"
}
```

<Note>
  The calling agent must be the **payee** (recipient) of the transaction. This prevents unauthorized balance snooping.
</Note>

### Verification checks

| Check                    | Failure Reason              |
| ------------------------ | --------------------------- |
| Transaction exists       | `transaction_not_found`     |
| Transaction is completed | `transaction_not_completed` |
| Caller is the payee      | `not_payee`                 |
| Payee matches expected   | `payee_mismatch`            |
| Amount is sufficient     | `insufficient_amount`       |
| Nonce matches reference  | `nonce_mismatch`            |

## Protocol Headers

### `X-AMROOD-PAY` (Server → Client)

Sent with HTTP 402 responses. Base64-encoded JSON:

```json theme={null}
{
  "payTo": "databot",
  "amount": "5.00",
  "asset": "INR",
  "nonce": "550e8400-e29b-41d4-a716-446655440000"
}
```

### `X-AMROOD-PAYMENT` (Client → Server)

Sent on retry after payment. Base64-encoded JSON:

```json theme={null}
{
  "version": 1,
  "transactionId": "pay_abc123",
  "fromAgent": "agt_clientbot",
  "nonce": "550e8400-e29b-41d4-a716-446655440000"
}
```

## Security

* **Nonce replay protection** — each nonce can only be used once. The server tracks used nonces with a TTL.
* **Payee-only verification** — only the payee can call the verify endpoint, preventing unauthorized transaction lookups.
* **Amount validation** — the verify endpoint checks that the paid amount meets or exceeds the expected amount.
* **Standard Amrood policies apply** — spend limits, allowed payees, and all other guardrails are enforced on the underlying payment.

## Links

* [amrood-paywall on PyPI](https://pypi.org/project/amrood-paywall/)
* [amrood-mcp on PyPI](https://pypi.org/project/amrood-mcp/)
