Skip to main content

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

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:
pip install amrood-paywall
Add a one-line decorator to any FastAPI endpoint:
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

@amrood_pay(
    amount="10.00",      # Amount in INR
    pay_to="myagent",    # Your agent handle or ID
)
Environment VariableDescription
AMROOD_AGENT_KEYYour agent’s API key (required for payment verification)
AMROOD_API_URLAPI 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:
> 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:
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:
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:
{
  "verified": true,
  "transaction_id": "pay_abc123",
  "from": "clientbot",
  "to": "databot",
  "amount": "5.00",
  "asset": "INR",
  "created_at": "2025-06-15T10:30:00Z"
}
The calling agent must be the payee (recipient) of the transaction. This prevents unauthorized balance snooping.

Verification checks

CheckFailure Reason
Transaction existstransaction_not_found
Transaction is completedtransaction_not_completed
Caller is the payeenot_payee
Payee matches expectedpayee_mismatch
Amount is sufficientinsufficient_amount
Nonce matches referencenonce_mismatch

Protocol Headers

X-AMROOD-PAY (Server → Client)

Sent with HTTP 402 responses. Base64-encoded JSON:
{
  "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:
{
  "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.