Skip to main content

Official Python SDK for the billing.io crypto checkout API

Project description

billingio

Official Python SDK for the billing.io crypto checkout API.

Installation

pip install billingio

Requires Python 3.9+.

Quick start

from billingio import BillingIO

client = BillingIO(api_key="sk_test_...")

# Create a checkout
checkout = client.checkouts.create(
    amount_usd=49.99,
    chain="tron",
    token="USDT",
    metadata={"order_id": "ord_12345"},
)

print(checkout.checkout_id)      # co_1a2b3c4d5e
print(checkout.deposit_address)  # blockchain address to send funds to
print(checkout.status)           # "pending"

Resources

The client exposes the following resource namespaces that mirror the REST API:

client.checkouts             # create, list, get, get_status
client.webhooks              # create, list, get, delete
client.events                # list, get
client.customers             # create, list, get, update
client.payment_methods       # create, list, update, delete, set_default
client.payment_links         # create, list
client.subscription_plans    # create, list, update
client.subscriptions         # create, list, update
client.subscription_renewals # list, retry
client.entitlements          # create, list, update, delete, check
client.payout_intents        # create, list, update, execute
client.settlements           # list
client.revenue_events        # list, accounting
client.adjustments           # create, list
client.health                # get

Checkouts

# Create with idempotency key for safe retries
checkout = client.checkouts.create(
    amount_usd=100.00,
    chain="arbitrum",
    token="USDC",
    expires_in_seconds=3600,
    idempotency_key="550e8400-e29b-41d4-a716-446655440000",
)

# List checkouts filtered by status
page = client.checkouts.list(status="confirmed", limit=10)
for co in page.data:
    print(co.checkout_id, co.amount_usd)

# Get a single checkout
checkout = client.checkouts.get("co_1a2b3c4d5e")

# Poll for status (lightweight endpoint)
status = client.checkouts.get_status("co_1a2b3c4d5e")
print(status.confirmations, "/", status.required_confirmations)

Webhook endpoints

# Register an endpoint
endpoint = client.webhooks.create(
    url="https://example.com/webhooks/billing",
    events=["checkout.completed", "checkout.expired"],
    description="Production webhook",
)
# IMPORTANT: store endpoint.secret -- it is only returned once
print(endpoint.secret)  # whsec_...

# List endpoints
page = client.webhooks.list()

# Delete an endpoint
client.webhooks.delete("we_abc123")

Events

# List events for a specific checkout
page = client.events.list(checkout_id="co_1a2b3c4d5e")

# Filter by event type
page = client.events.list(type="checkout.completed")

# Get a single event
event = client.events.get("evt_xyz789")
print(event.type, event.data.status)

Customers

# Create a customer
customer = client.customers.create(
    email="alice@example.com",
    name="Alice",
    metadata={"tier": "enterprise"},
)

# List customers
page = client.customers.list(status="active", limit=10)

# Get a single customer
customer = client.customers.get("cus_abc123")

# Update a customer
customer = client.customers.update("cus_abc123", name="Alice Smith")

Payment Methods

# Add a payment method
pm = client.payment_methods.create(
    customer_id="cus_abc123",
    type="wallet",
    label="My TRON wallet",
)

# List payment methods for a customer
page = client.payment_methods.list(customer_id="cus_abc123")

# Set as default
client.payment_methods.set_default("pm_xyz789")

# Delete a payment method
client.payment_methods.delete("pm_xyz789")

Payment Links

# Create a payment link
link = client.payment_links.create(
    amount_usd=25.00,
    chain="tron",
    token="USDT",
)
print(link.url)  # shareable payment URL

# List payment links
page = client.payment_links.list()

Subscription Plans

# Create a plan
plan = client.subscription_plans.create(
    name="Pro Monthly",
    amount_usd=29.99,
    chain="arbitrum",
    token="USDC",
    interval="month",
)

# List plans
page = client.subscription_plans.list()

# Archive a plan
client.subscription_plans.update("plan_abc123", status="archived")

Subscriptions

# Subscribe a customer to a plan
sub = client.subscriptions.create(
    customer_id="cus_abc123",
    plan_id="plan_abc123",
)

# List active subscriptions
page = client.subscriptions.list(status="active")

# Cancel a subscription
client.subscriptions.update("sub_xyz789", status="cancelled")

Subscription Renewals

# List renewals
page = client.subscription_renewals.list(subscription_id="sub_xyz789")

# Retry a failed renewal
renewal = client.subscription_renewals.retry("ren_abc123")

Entitlements

# Grant a feature entitlement
ent = client.entitlements.create(
    subscription_id="sub_xyz789",
    feature_key="analytics",
    value="premium",
)

# Check if a customer has access
check = client.entitlements.check(
    customer_id="cus_abc123",
    feature_key="analytics",
)
print(check.has_access)  # True

# List and delete
page = client.entitlements.list(subscription_id="sub_xyz789")
client.entitlements.delete("ent_abc123")

Payout Intents

# Create a payout
payout = client.payout_intents.create(
    amount_usd=500.00,
    chain="tron",
    token="USDT",
    destination_address="T...",
)

# Execute the payout
payout = client.payout_intents.execute("po_abc123")

# List payouts
page = client.payout_intents.list(status="executed")

Settlements

# List settlements
page = client.settlements.list(payout_id="po_abc123")
for s in page.data:
    print(s.settlement_id, s.net_usd)

Revenue Events

# List revenue events
page = client.revenue_events.list()

# Get accounting summary for a period
summary = client.revenue_events.accounting(
    period_start="2025-01-01",
    period_end="2025-01-31",
)
print(summary.net_revenue_usd)

Adjustments

# Create a refund adjustment
adj = client.adjustments.create(
    type="refund",
    amount_usd=49.99,
    source_id="co_1a2b3c4d5e",
    source_type="checkout",
    reason="Customer requested refund",
)

# List adjustments
page = client.adjustments.list(type="refund")

Health

health = client.health.get()
print(health.status)   # "healthy"
print(health.version)  # "2.0.0"

Webhook verification

Verify incoming webhook signatures before processing the event. The SDK ports the exact same HMAC-SHA256 logic used by the billing.io backend.

Flask example

from flask import Flask, request, abort
from billingio import verify_webhook_signature, WebhookVerificationError

app = Flask(__name__)
WEBHOOK_SECRET = "whsec_..."

@app.route("/webhooks/billing", methods=["POST"])
def handle_webhook():
    raw_body = request.get_data(as_text=True)
    signature = request.headers.get("x-billing-signature", "")

    try:
        event = verify_webhook_signature(raw_body, signature, WEBHOOK_SECRET)
    except WebhookVerificationError:
        abort(400)

    if event["type"] == "checkout.completed":
        checkout_id = event["checkout_id"]
        # Fulfil the order ...

    return "", 200

Django example

import json
from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt
from billingio import verify_webhook_signature, WebhookVerificationError

WEBHOOK_SECRET = "whsec_..."

@csrf_exempt
def billing_webhook(request):
    raw_body = request.body.decode("utf-8")
    signature = request.headers.get("X-Billing-Signature", "")

    try:
        event = verify_webhook_signature(raw_body, signature, WEBHOOK_SECRET)
    except WebhookVerificationError:
        return HttpResponseBadRequest("Invalid signature")

    if event["type"] == "checkout.completed":
        # Fulfil the order ...
        pass

    return HttpResponse(status=200)

Error handling

All API errors are raised as BillingIOError with structured fields:

from billingio import BillingIO, BillingIOError

client = BillingIO(api_key="sk_test_...")

try:
    checkout = client.checkouts.get("co_nonexistent")
except BillingIOError as e:
    print(e.type)         # "not_found"
    print(e.code)         # "checkout_not_found"
    print(e.status_code)  # 404
    print(e.message)      # "No checkout found with ID co_nonexistent."
    print(e.param)        # "checkout_id"

Error types returned by the API:

type HTTP status Description
invalid_request 400 Missing or invalid request parameters
authentication_error 401 Invalid or missing API key
not_found 404 Resource does not exist
idempotency_conflict 409 Idempotency key reused with different params
rate_limited 429 Too many requests
internal_error 500 Unexpected server error

Pagination

List endpoints use cursor-based pagination. You can page manually or use the auto_paginate helper to iterate through all items:

Manual pagination

cursor = None
while True:
    page = client.checkouts.list(cursor=cursor, limit=50)
    for checkout in page.data:
        process(checkout)
    if not page.has_more:
        break
    cursor = page.next_cursor

auto_paginate helper

from billingio import auto_paginate

for checkout in auto_paginate(client.checkouts.list, status="confirmed"):
    print(checkout.checkout_id)

auto_paginate accepts the same keyword arguments as the underlying list() method and yields individual items across all pages.

Configuration

Parameter Default Description
api_key (required) Your secret API key
base_url https://api.billing.io/v1 API base URL override
# Point to a local development server
client = BillingIO(
    api_key="sk_test_...",
    base_url="http://localhost:8080/v1",
)

License

Proprietary -- see billing.io/terms.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

billingio-2.0.0.tar.gz (19.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

billingio-2.0.0-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file billingio-2.0.0.tar.gz.

File metadata

  • Download URL: billingio-2.0.0.tar.gz
  • Upload date:
  • Size: 19.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for billingio-2.0.0.tar.gz
Algorithm Hash digest
SHA256 f28e175772732d696b592eab92cf1d1f25d03f847d1f919fe8b3b43875b0a8a3
MD5 32e8f951d5188da4326226a5b922e8fd
BLAKE2b-256 efe75bfc16a43ed6dc53caee06863252a46955eb91e6514bd787956430fa5650

See more details on using hashes here.

File details

Details for the file billingio-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: billingio-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for billingio-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 800b4fad3c08f59e94930badf22ed4301eae6dd3ff6b2b783606ab6d3f863ae8
MD5 e170e3e965660f89748d0d4d40e187ea
BLAKE2b-256 1f509d00420e6346858137b45a41b921e7ec4f6009ce0a003f95e1493eac7d20

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page