southbill (Python)
Official Python SDK for the Southbill API. No third-party dependencies — standard library only. Requires Python 3.8+.
pip install southbill
Quick start
from southbill import Southbill
southbill = Southbill() # or Southbill("sk_live_...")
session = southbill.checkout.sessions.create(
amount=4900,
currency="EUR",
customer_email="ada@acme.com",
success_url="https://acme.com/thanks",
)
print(session["checkout_url"])
The Merchant API accepts live keys only (sk_live_... for server calls, pk_live_...
for publishable/browser use). Legacy sk_test_... keys are rejected with
401 authentication_error — sandbox testing happens on the Developer Platform, not
through merchant keys.
Errors carry a machine-readable error.type plus an optional error.code:
type |
When |
|---|---|
authentication_error |
Missing, malformed, revoked or expired key |
permission_error |
Key lacks the required scope, or merchant is suspended |
invalid_request |
Bad input; code: "resource_missing" for unknown IDs (404) |
idempotency_error |
code: "idempotency_key_reused" (same key, different body) or code: "idempotency_in_flight" (same key still processing — retry shortly) |
rate_limit_error |
code: "rate_limit_exceeded" — retry after Retry-After |
already_refunded, charge_disputed |
Refund not possible for that charge |
product_limit_reached, account_not_ready, invalid_state |
Plan or account state blocks the call |
stripe_error, api_error |
Upstream or internal failure (502 / 500) |
Note: the App API (OAuth apps) uses not_found as an error type, while the Merchant API
returns invalid_request with code: "resource_missing" instead.
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, delete, list_prices, create_price, set_default_price |
payments |
retrieve, list |
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, list, delete, rotate_secret, list_deliveries |
balance |
retrieve, balance.transactions.retrieve, balance.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.
Installment payments (invoices)
installments = southbill.invoices.list_installments("inv_123")
payments = southbill.invoices.list_payments("inv_123")
Webhook endpoints (API-managed)
endpoint = southbill.webhook_endpoints.create(
url="https://acme.com/webhooks/southbill",
enabled_events=["invoice.paid", "payment.succeeded"],
)
southbill.webhook_endpoints.rotate_secret(endpoint["id"]) # old secret stays valid 24 h
deliveries = southbill.webhook_endpoints.list_deliveries(endpoint["id"])
Balance & transactions
balance = southbill.balance.retrieve()
for tx in southbill.balance.transactions.auto_paging_iter(type="charge"):
print(tx["bt_id"], tx["net"], tx["currency"])
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
Network errors, 429 and 5xx are retried twice with exponential backoff.
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.
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":
... # 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 tolerance 300s.
License
MIT
Metadata
Release files for southbill 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| southbill-0.1.1.tar.gz | 6.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| southbill-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 14.6 kB
Release files / southbill-0.1.1.tar.gz
| Download URL | southbill-0.1.1.tar.gz |
|---|---|
| Size | 6.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d362e0b778ff33e218699c9e8af6532757300bd8aec7af357186a603a99ecb05
|
|
BLAKE2b-256 checksum How to use checksums |
42b071e25c929314c08497a731abf7cc8cc0123ad807da545bb1dc579b9711d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|
Release files / southbill-0.1.1-py3-none-any.whl
| Download URL | southbill-0.1.1-py3-none-any.whl |
|---|---|
| Size | 8.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc56ae86232c9a184377a508ddc2fda91c521140dd165ed59aafc5f33d7516fd
|
|
BLAKE2b-256 checksum How to use checksums |
a83673c4e62df0065f1f92a498d32f5e9de65cd54fa26dd1394bf1056e2b0e5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.12
|