Unofficial but friendly Python client for the Crypto Bot API. It provides typed models, sane defaults, and synchronous/async clients for invoices, transfers, balances, exchange rates, and webhook handling.
Features
- Synchronous
httpx-based API client (CryptoBotClient) - Async
httpx-based API client (AsyncCryptoBotClient) - Dataclass models for API responses (
Invoice,Transfer,Balance,ExchangeRate,Currency) - Enum guard rails for assets, statuses, and paid button names
- Mainnet/testnet support with configurable timeouts and retries
- FastAPI-powered webhook listener with signature verification and optional replay protection
- Custom exception model (
CryptoBotError) with API code/name fields
What's New in 0.5.0
- Added
AsyncCryptoBotClientwith method parity and async invoice iterators - Added invoice pagination helpers:
iter_invoice_pages(...)anditer_invoices(...) - Added configurable retries/backoff (
max_retries,retry_backoff,retryable_status_codes) - Added webhook replay protection (
replay_store,replay_ttl_seconds,replay_key_resolver)
Installation
CryptoBot Python supports Python >=3.9.12.
pip install cryptobot-python
Install webhook server dependencies only when needed:
pip install "cryptobot-python[webhook]"Install documentation tooling extras only when needed:
pip install "cryptobot-python[docs]"Quick Start
import os from cryptobot import CryptoBotClient from cryptobot.models import Asset client = CryptoBotClient( api_token=os.environ["CRYPTOBOT_API_TOKEN"], is_mainnet=True, timeout=5.0, max_retries=2, retry_backoff=0.5, ) app = client.get_me() print(app.name) invoice = client.create_invoice( asset=Asset.USDT, amount=5.25, description="Coffee order #42", ) print(invoice.invoice_id, invoice.bot_invoice_url)
To use testnet instead of mainnet:
client = CryptoBotClient(api_token=os.environ["CRYPTOBOT_TESTNET_TOKEN"], is_mainnet=False)
Retry behavior is optional and disabled by default (max_retries=0). The default retryable status codes are
429, 500, 502, 503, 504.
client = CryptoBotClient( api_token=os.environ["CRYPTOBOT_API_TOKEN"], max_retries=3, retry_backoff=0.5, retryable_status_codes={429, 500, 502, 503, 504}, )
Async usage:
import asyncio import os from cryptobot import AsyncCryptoBotClient from cryptobot.models import Asset async def main(): async with AsyncCryptoBotClient(api_token=os.environ["CRYPTOBOT_API_TOKEN"], max_retries=2) as client: app = await client.get_me() print(app.name) invoice = await client.create_invoice(asset=Asset.USDT, amount=5.25, description="Async order #42") print(invoice.invoice_id, invoice.bot_invoice_url) asyncio.run(main())
Core API
CryptoBotClient methods:
get_me()create_invoice(...)get_invoices(...)transfer(...)get_balances()get_exchange_rates()get_currencies()iter_invoice_pages(...)iter_invoices(...)
AsyncCryptoBotClient provides the same methods with await, plus async iterators for
iter_invoice_pages(...) and iter_invoices(...).
get_invoices(...) accepts invoice_ids as a comma-separated string ("1,2,3") or list[int] ([1, 2, 3]).
Iterator helpers accept page_size and start_offset to support controlled pagination scans.
Example transfer with idempotency via spend_id:
from cryptobot.errors import CryptoBotError from cryptobot.models import Asset try: transfer = client.transfer( user_id=123456789, asset=Asset.TON, amount=0.5, spend_id="reward_2026_02_10_user_123456789", comment="Cashback reward", ) print(transfer.transfer_id, transfer.status) except CryptoBotError as exc: print(exc.code, exc.name)
Webhooks
Use the built-in listener to validate incoming signatures and process updates:
import os from cryptobot.webhook import InMemoryReplayKeyStore, Listener def handle_webhook(headers, data): if data.get("update_type") == "invoice_paid": payload = data.get("payload", {}) print("Paid invoice:", payload.get("invoice_id")) listener = Listener( host="0.0.0.0", callback=handle_webhook, api_token=os.environ["CRYPTOBOT_API_TOKEN"], replay_store=InMemoryReplayKeyStore(), replay_ttl_seconds=3600, port=2203, url="/webhook", log_level="info", ) listener.listen()
Listener accepts both sync and async callback functions.
For custom dedupe behavior, pass replay_key_resolver(data, raw_body, headers) with a stable key strategy.
For custom webhook stacks, use cryptobot.webhook.check_signature(...) to verify
crypto-pay-api-signature against the raw request body.
Development
uv sync
make lint
make test
make docsDocumentation
- Docs: https://cryptobot-python.readthedocs.io/
- API reference: https://cryptobot-python.readthedocs.io/en/latest/modules.html
- Webhook security guide: https://cryptobot-python.readthedocs.io/en/latest/webhook_security.html
Contributing
Issues and pull requests are welcome. Before opening a PR:
See CONTRIBUTING.md and AGENTS.md for project workflow and coding standards.
Credits
This project started with Cookiecutter and the audreyr/cookiecutter-pypackage template.