Metadata-Version: 2.4
Name: paegents
Version: 2.8.0
Summary: Official Python SDK for Paegents - Payment infrastructure for AI agents with Service Catalog and Usage Escrow
Author-email: Paegents Inc <support@paegents.com>
License-Expression: MIT
Project-URL: Homepage, https://paegents.com
Project-URL: Documentation, https://docs.paegents.com
Project-URL: Repository, https://github.com/paegents/python-sdk
Project-URL: Bug Tracker, https://github.com/paegents/python-sdk/issues
Keywords: payments,ai,agents,fintech,automation,stripe,braintree,stablecoin
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Operating System :: OS Independent
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Requires-Dist: eth-account>=0.8.0
Requires-Dist: x402>=0.1.0
Provides-Extra: dev
Requires-Dist: pytest>=6.0; extra == "dev"
Requires-Dist: pytest-cov>=2.0; extra == "dev"
Requires-Dist: black>=21.0.0; extra == "dev"
Requires-Dist: flake8>=3.8.0; extra == "dev"
Requires-Dist: mypy>=0.800; extra == "dev"
Requires-Dist: isort>=5.0.0; extra == "dev"
Dynamic: license-file

# Paegents Python SDK

Official Python SDK for integrating Paegents agent payments.

## Installation

```bash
pip install paegents
```

## Initialize

```python
import os
from paegents import PaegentsSDK

sdk = PaegentsSDK(
    api_url=os.getenv('PAEGENTS_API_URL', 'https://api.paegents.com'),
    agent_id=os.environ['PAEGENTS_AGENT_ID'],
    api_key=os.environ['PAEGENTS_API_KEY'],
    owner_jwt=os.getenv('OWNER_JWT'),  # optional: owner-only endpoints
)
```

Agent runtime auth is `api_key + agent_id`. `owner_jwt` is only for owner-scoped routes such as policy management, dashboard setup, or owner-managed webhooks.

## AP2 Quick Start

```python
from paegents import build_card_payment_method

intent = sdk.create_ap2_intent_mandate(
    policy={"max_amount": {"value": 5000}, "currency": "usd"},
    metadata={"purpose": "compute credits"},
)

cart = sdk.create_ap2_cart_mandate(
    intent_mandate_id=intent.id,
    cart={"total": 2500, "currency": "usd"},
)

payment = sdk.ap2_pay(
    intent_mandate_id=intent.id,
    cart_mandate_id=cart.id,
    payment_method=build_card_payment_method(provider='stripe'),
)

if isinstance(payment, dict) and payment.get('approval_required'):
    print('Approval required:', payment['request_id'])
else:
    print('Payment status:', payment.status)
```

## Bilateral Escrow Usage Agreements

For bilateral escrow, the buyer signs in two phases:

1. create the proposal with `buyer_permit_signature`
2. after the server returns a real `onchain_agreement_id`, call `get_deposit_params()` and submit `buyer_deposit_auth_signature` via `refresh_permit()`

The live Base Sepolia fast-cycle contract used in current examples is:

- `0xcA98356B65951b621C32B840F0266847C6043B45`

```python
import time
from paegents import (
    UsageAgreementRequest,
    build_bilateral_agreement_signatures,
)

permit_deadline = int(time.time()) + 600

proposal_signatures = build_bilateral_agreement_signatures(
    buyer_private_key=os.environ['BUYER_PRIVATE_KEY'],
    deposit_params={
        "agreement_id": "proposal_001",
        "chain_id": 84532,
        "usdc_address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
        "escrow_contract_address": "0xcA98356B65951b621C32B840F0266847C6043B45",
        "service_amount_atomic": 10_000_000,
        "infra_fee_amount_atomic": 250_000,
        "gas_wallet_address": "0x13e8F75fA46D0ecC3C22b10774b8Ce2180199218",
    },
    quantity=1000,
    price_per_unit_cents=10,
    permit_deadline=permit_deadline,
    usdc_permit_nonce=0,
    infra_fee_permit_nonce=1,
)

agreement = sdk.create_usage_agreement(
    UsageAgreementRequest(
        seller_agent_id='seller-agent-123',
        service_id='svc_abc123',
        quantity=1000,
        unit='api_calls',
        price_per_unit_cents=10,

        # Required agreement authorization fields
        buyer_wallet_address='0xBuyerWallet...',
        buyer_permit_signature=proposal_signatures['buyer_permit_signature'],
        buyer_permit_deadline=proposal_signatures['buyer_permit_deadline'],
        buyer_infra_fee_permit_signature=proposal_signatures['buyer_infra_fee_permit_signature'],
        buyer_infra_fee_permit_deadline=proposal_signatures['buyer_infra_fee_permit_deadline'],

        client_proposal_id='proposal_001',
    )
)

deposit_params = sdk.get_deposit_params(agreement.agreement_id)

funding_signatures = build_bilateral_agreement_signatures(
    buyer_private_key=os.environ['BUYER_PRIVATE_KEY'],
    deposit_params=deposit_params.__dict__,
    quantity=1000,
    price_per_unit_cents=10,
    deposit_auth_deadline=int(time.time()) + 600,
)

sdk.refresh_permit(
    agreement.agreement_id,
    buyer_deposit_auth_signature=funding_signatures['buyer_deposit_auth_signature'],
    buyer_deposit_auth_deadline=funding_signatures['buyer_deposit_auth_deadline'],
)

current = sdk.get_escrow_status(agreement.agreement_id)
print(current.settlement_status, current.escrow_status)
```

### Optional: Metered Client

```python
client = sdk.create_metered_client(agreement.agreement_id)

result = client.post('/generate', json={
    'prompt': 'hello world',
    'max_tokens': 150,
})

usage = client.get_usage_status()
print(usage.units_used, usage.units_remaining)
```

## Policies and Approvals

Owner JWT is required for these endpoints.

```python
import os

owner_jwt = os.environ['OWNER_JWT']

sdk.update_agent_policies(
    {
        'approvals': {'threshold_cents': 2000},
        'rails': {'allowed': ['card', 'stablecoin']},
        'spending': {'daily_limit_cents': 10000},
    },
    agent_id='agent-123',
    jwt_token=owner_jwt,
)

pending = sdk.list_approvals(status='pending', agent_id='agent-123', jwt_token=owner_jwt)
if pending.get('approvals'):
    sdk.approve_approval(pending['approvals'][0]['id'], agent_id='agent-123', jwt_token=owner_jwt)
```

## Webhooks

```python
import os

owner_jwt = os.environ['OWNER_JWT']

webhook = sdk.create_webhook(
    url='https://example.com/webhooks',
    event_types=['payment.*', 'agreement.*'],
    agent_id='agent-123',
    jwt_token=owner_jwt,
)

print(webhook.get('id'))
```

### Verify Webhook Signatures

```python
from paegents import verify_webhook_signature

verify_webhook_signature(signature_header, raw_body, os.environ['PAEGENTS_WEBHOOK_SECRET'])
```

## Error Handling

```python
from paegents import ApiError, PolicyDeniedError

try:
    sdk.ap2_pay(
        intent_mandate_id='intent_123',
        cart_mandate_id='cart_123',
        payment_method=build_card_payment_method(),
    )
except PolicyDeniedError as exc:
    print('Policy denied:', exc)
except ApiError as exc:
    print('API error:', exc)
except Exception as exc:
    print('Unexpected error:', exc)
```

## Notes

- Prefer SDK methods over manual HTTP calls.
- Keep API keys and JWTs in environment variables.
- Use idempotency keys on critical write operations.
- Bilateral escrow settlement auto-pays on finalization. Buyer and seller do not need a second payout signature after the agreement is already funded and metered.
- The platform fee is upfront-only in the current live model. Settlement should not perform a second per-call fee pull.

## Support

- Docs: https://docs.paegents.com
- API docs: https://docs.paegents.com/api
- Support: support@paegents.com

## License

MIT
