Python port of paybot-sdk — USDC/EURC payments for AI agents via the x402 protocol.
Project description
paybot-sdk (Python port)
Python port of paybot-sdk. Mirror of the TypeScript SDK in ../../src/.
Status: runtime (0.1.0). Type surface, network config, HTTP transport, all client REST methods, EIP-3009 signing (
PayBotClient.pay()real-mode path), and webhook signature verification are implemented and tested. The signed payload and the webhook signature are byte-for-byte compatible with the TS SDK.
Install
pip install paybot-sdk
Or with the signing extras (required for pay() in real mode):
pip install paybot-sdk[signing]
Quick start (mock mode)
import asyncio
from paybot_sdk import PayBotClient, PayBotConfig, PaymentRequest
async def main():
client = PayBotClient(PayBotConfig(
api_key="pb_test_...",
bot_id="my-bot",
))
await client.register()
balance = await client.balance()
print(balance)
asyncio.run(main())
What's implemented
| File | Mirror of TS | Status |
|---|---|---|
paybot_sdk/types.py |
src/types.ts |
✅ Full type surface as @dataclass |
paybot_sdk/networks.py |
src/networks.ts |
✅ Full (chain IDs, USDC addresses, EIP-712 domains, EIP-3009 types) |
paybot_sdk/errors.py |
src/errors.ts |
✅ Full (PayBotApiError, get_error_message) |
paybot_sdk/crypto.py |
src/crypto.ts |
✅ Full (generate_eip3009_nonce via secrets.token_hex) |
paybot_sdk/client.py |
src/client.ts |
✅ Full — all REST methods + real-mode EIP-3009 signing in _sign_payload() |
paybot_sdk/webhook.py |
src/webhook.ts |
✅ Full (verify_webhook_signature, HMAC-SHA256, replay guard) |
paybot_sdk/__init__.py |
src/index.ts |
✅ Full exports |
paybot_sdk/middleware.py |
src/middleware.ts |
❌ Not yet ported |
paybot_sdk/x402_handler.py |
src/x402-handler.ts |
❌ Not yet ported |
Working today:
register(), balance(), history(), set_limits(), health(),
commission_summary(), commission_ledger(), create_api_key(),
list_api_keys(), revoke_api_key(), real-mode pay() (EIP-3009 signing),
and verify_webhook_signature(). Mock mode (no wallet_private_key) and real
mode both mirror the TS SDK wire contract.
Not yet ported:
middleware.pyx402_handler.py
Webhook verification
from paybot_sdk import verify_webhook_signature
ok = verify_webhook_signature(
payload=request_body, # str or bytes — the raw body
signature=headers["Paybot-Signature"], # "t=<unix_ts>,v1=<hex>"
secret="whsec_...",
tolerance=300, # replay window in seconds
)
The signing string is f"{t}.{payload}" and the header format is
t=<unix_ts>,v1=<hmac_sha256_hex>, identical to the TS
verifyWebhookSignature, so a server-signed webhook verifies in either runtime.
Notes
- Snake-case naming. TS uses
botId,walletPrivateKey. Python convention isbot_id,wallet_private_key. Wire format on the HTTP boundary is still camelCase (matches the TS server contract). Worth confirming this is the right boundary placement. PayBotConfigas dataclass vs. kwargs. CurrentlyPayBotConfigis a dataclass that gets passed in. Could also exposePayBotClient(api_key=..., bot_id=...)directly. Open to either; let me know which matches the SDK's intended ergonomics.- Async-first vs. sync wrapper. Right now everything is
async def. The TS SDK is also async-first (promise-based). If the consumer use cases include sync agents (LangChain old-style), a thinpaybot_sdk.syncwrapper is easy to add. Worth deciding now so the public API doesn't drift. _to_base_units. String-based conversion to avoid float drift. Matches the TS path; worth verifying no precision corner cases I missed.
Test plan
cd packages/python
pip install -e ".[signing,test]"
pytest
The test suite (in tests/) covers:
- Type surface (every dataclass constructable from valid inputs)
PayBotClient.__init__validation (api_key required, bot_id required, facilitator_url URL, wallet_private_key 0x-prefix)_to_base_unitscorner cases (zero, no decimal, exact decimal, more decimals than scale)generate_eip3009_nonceshape (0x-prefixed, 66 chars)NETWORKSparity withsrc/networks.ts(chain IDs, USDC addresses)- EIP-3009 signing (
test_signing.py): TS wire shape, signer-address recovery round-trip, unsupported-network + missing-key errors, deterministic-given-nonce structure - Real-mode
pay()verify→settle flow (respx-mocked HTTP) - Webhook verification (
test_webhook.py): valid/tampered/expired/future/malformed-header cases + thef"{t}.{payload}"cross-language signing contract
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paybot_sdk-0.2.0.tar.gz.
File metadata
- Download URL: paybot_sdk-0.2.0.tar.gz
- Upload date:
- Size: 73.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d37101b6679c1c360e0879e7409e709ccd8bcc2f1ddea4d9d76f8fb53a0d47f
|
|
| MD5 |
43309f42e52528d81d18e4d90813d58a
|
|
| BLAKE2b-256 |
45a639564030dc0fc71c359519beae0c05c7f3d61b32819b97cfeaae59519181
|
File details
Details for the file paybot_sdk-0.2.0-py3-none-any.whl.
File metadata
- Download URL: paybot_sdk-0.2.0-py3-none-any.whl
- Upload date:
- Size: 52.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef051b7b774dd5ecb767302b6d66dc96d865e571c3e43d9ff2955c37e4412fa9
|
|
| MD5 |
983c0f961aff360265243fb95e81cc33
|
|
| BLAKE2b-256 |
985af3f9eff2528c04ebd1504be56731a52cbd772157f894d4fc8bb104d9e764
|