Metadata-Version: 2.4
Name: ap2-x402-bridge
Version: 0.1.0
Summary: Bridge between Google AP2 Agent Payment Protocol and Coinbase x402. The only open-source AP2↔x402 converter.
License: Apache-2.0
Project-URL: Homepage, https://bonanza-labs.com
Project-URL: Repository, https://github.com/c6zks4gssn-droid/ap2-x402-bridge
Project-URL: Issues, https://github.com/c6zks4gssn-droid/ap2-x402-bridge/issues
Keywords: ap2,x402,agent-payments,payments,ai-agents,google-agent-payment,coinbase,stablecoin,bridge
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"

# ap2-x402-bridge

**The only open-source bridge between Google AP2 (Agent Payment Protocol) and Coinbase x402.**

```bash
pip install ap2-x402-bridge
```

Two dominant agent payment protocols emerged in 2026 — and nothing bridged them. Until now.

---

## Why this exists

| Protocol | Backer | Mechanism | Agents |
|---|---|---|---|
| **AP2** | Google | Signed mandate objects | Google Vertex AI agents |
| **x402** | Linux Foundation / Coinbase | HTTP 402 + on-chain payment | Claude, OpenAI agents, Hermes |

An AP2 agent can't pay an x402 endpoint. An x402 agent can't submit to an AP2 endpoint. This bridge fixes both directions.

---

## Quickstart

### AP2 agent → x402 endpoint

Your agent has an AP2 mandate. The target service speaks x402. Bridge it:

```python
from ap2_x402_bridge import AP2Mandate, BridgeServer

# Create and sign a mandate
mandate = AP2Mandate.create(
    agent_id="my-agent",
    payee_url="https://data.example.com/report",
    max_amount_usd=5.00,
    signing_key="my-signing-key",
    chain="base",
)

# Bridge it to an x402 endpoint
bridge = BridgeServer(signing_key="my-signing-key")
result = bridge.ap2_to_x402(
    mandate=mandate,
    x402_url="https://data.example.com/report",
)

if result.success:
    print(f"Paid ${result.amount_usd:.2f}")
    print(result.response_body)
```

### x402 agent → AP2 endpoint

You have an x402 challenge (from a 402 response). The payee expects AP2. Convert it:

```python
from ap2_x402_bridge import BridgeServer, X402Challenge

# Challenge from an HTTP 402 response
challenge = X402Challenge.from_json(response_body)

bridge = BridgeServer(signing_key="my-signing-key")
result = bridge.x402_to_ap2(
    challenge=challenge,
    ap2_endpoint="https://ap2.example.com/pay",
    agent_id="my-agent",
)
```

### Auto-detect

```python
bridge = BridgeServer(signing_key="my-key", simulate_payments=True)

# With mandate: uses AP2→x402 flow
result = bridge.pay("https://api.example.com", mandate=mandate)

# Without mandate: probes URL, detects protocol, bridges automatically
result = bridge.pay("https://api.example.com", agent_id="my-agent")
```

---

## AP2 Mandate

```python
from ap2_x402_bridge import AP2Mandate

# Create and sign
mandate = AP2Mandate.create(
    agent_id="agent-007",
    payee_url="https://data.io/v1/report",
    max_amount_usd=10.00,
    signing_key="agent-signing-key",
    chain="base",           # "base", "ethereum", "polygon", ...
    currency="USD",
    ttl_seconds=300,        # expires in 5 minutes
    purpose="Download quarterly report",
)

# Verify
assert mandate.verify("agent-signing-key") is True
assert mandate.is_expired() is False

# Serialize / deserialize
d = mandate.to_dict()
mandate2 = AP2Mandate.from_dict(d)
```

---

## x402 Challenge

```python
from ap2_x402_bridge import X402Challenge

# Parse from HTTP 402 response body
challenge = X402Challenge.from_json(response.text)

# Or construct manually
challenge = X402Challenge.simple(
    resource="https://api.example.com/data",
    amount_usd=2.50,
    network="base",
    description="API call",
)

# Inspect
print(f"Cost: ${challenge.amount_usd('base'):.2f}")
print(f"Network: {challenge.preferred.network}")

# To wire format
header = challenge.to_dict()
```

---

## BridgeServer options

```python
bridge = BridgeServer(
    signing_key="bridge-signing-key",    # used for bridge receipts and AP2 signing
    ap2_signing_key="ap2-specific-key",  # separate key for AP2 mandates (optional)
    timeout_seconds=30.0,                # HTTP timeout
    simulate_payments=False,             # True = no real HTTP calls (for tests)
    on_payment=lambda result: log(result),  # callback after each payment
)
```

---

## Supported networks

| AP2 name | x402 name | Chain |
|---|---|---|
| `base` | `base` | Base (Coinbase L2) |
| `ethereum` / `eth` | `ethereum` | Ethereum mainnet |
| `polygon` / `matic` | `polygon` | Polygon |
| `arbitrum` / `arb` | `arbitrum` | Arbitrum One |
| `optimism` / `op` | `optimism` | Optimism |
| `solana` / `sol` | `solana` | Solana |

---

## Zero dependencies

`ap2-x402-bridge` uses only Python stdlib (hashlib, hmac, base64, json, uuid, urllib). No external packages required.

---

## Testing

```bash
cd ap2-x402-bridge
python3 tests/test_ap2.py
python3 tests/test_x402.py
python3 tests/test_converter.py
python3 tests/test_bridge.py
```

Or with pytest:
```bash
pip install pytest && pytest tests/ -v
```

---

## License

Apache 2.0. Built by [Bonanza Labs](https://bonanza-labs.com).

For a managed payment firewall with approval UI, policy editor, and audit log:
→ **[bonanza-labs.com/firewall](https://bonanza-labs.com/firewall)**
