Python SDK

Official Python client with retries, idempotency and webhook verification

The official Python SDK wraps the same REST API documented here. It has no third-party dependencies (standard library only) and adds retries, idempotency keys, auto-pagination and webhook signature verification.

Install

pip install southbill

Package: pypi.org/project/southbill

Requires Python 3.8 or newer.

Create a checkout session

from southbill import Southbill

southbill = Southbill()  # reads SOUTHBILL_API_KEY

session = southbill.checkout.sessions.create(
    amount=4900,
    currency="EUR",
    customer_email="ada@acme.com",
    success_url="https://acme.com/thanks",
)

print(session["checkout_url"])

All merchant API keys are live keys (sk_live_...). Southbill has no test mode. is False for them.

Resources

Namespace Methods
checkout.sessions create, retrieve, list, expire
customers create, retrieve, update, list, delete
invoices create, retrieve, update, list, send, void, mark_paid, list_installments, list_payments
products create, retrieve, update, list
payments retrieve, list
prices via products: list_prices, create_price, set_default_price
refunds create, retrieve, list
subscriptions create, retrieve, update, list, cancel
subscription_links create, retrieve, update, list, archive
events retrieve, list, replay
webhook_endpoints create, retrieve, update, delete, list, rotate_secret, list_deliveries
balance retrieve, transactions.retrieve, transactions.list

Payouts, bank details, KYC and API-key management stay merchant-controlled in the dashboard and are intentionally not part of the API surface.

Idempotency

Every POST sends an Idempotency-Key header (random UUID). Pass your own for safe retries across processes:

southbill.invoices.create(idempotency_key=f"inv-{order_id}", customer="cus_123")

Pagination

for invoice in southbill.invoices.auto_paging_iter(status="open"):
    print(invoice["id"])

Errors and retries

Network errors, 429 and 5xx are retried twice with exponential backoff (configurable via max_retries). Everything else raises SouthbillError:

from southbill import SouthbillError

try:
    southbill.refunds.create(payment="pi_123", amount=500)
except SouthbillError as error:
    print(error.status, error.type, error.param, error.request_id)

Webhooks

Verify the raw request body — never a re-serialized object.

import os
from flask import Flask, request
from southbill import construct_event, SouthbillSignatureError

app = Flask(__name__)

@app.post("/webhooks/southbill")
def webhook():
    try:
        event = construct_event(
            payload=request.get_data(),
            signature=request.headers.get("Southbill-Signature", ""),
            secret=os.environ["SOUTHBILL_WEBHOOK_SECRET"],
        )
    except SouthbillSignatureError:
        return "", 400

    if event["type"] == "invoice.paid":
        pass  # handle it

    return "", 200

Signature scheme: Southbill-Signature: t=<unix seconds>,v1=<hex> where the hex digest is HMAC-SHA256(secret, "<timestamp>.<raw body>"). Default clock tolerance is 300 seconds.

Configuration

Southbill(
    api_key=os.environ["SOUTHBILL_API_KEY"],
    base_url="https://api.southbill.com",
    timeout=30.0,
    max_retries=2,
)