Python SDK
Python SDK
The NovaBilling Python SDK provides a fully typed, Pythonic interface to the entire NovaBilling API. It supports both synchronous and asynchronous usage and is compatible with Python 3.8+.
Installation
pip install novabilling
poetry add novabilling
Client Initialization
Synchronous Client
Use NovaBilling for synchronous operations across all resources (customers, plans, subscriptions, invoices, payments, analytics, payment providers, webhooks, auth, and tenant settings).
from novabilling import NovaBilling
client = NovaBilling(
token="sk_live_a1b2c3d4e5f6g7h8i9j0...",
# Optional: override the default base URL
base_url="https://api.novabilling.com"
)
Async Client
Use AsyncNovaBilling for asynchronous operations. See the Async Support section for details.
from novabilling import AsyncNovaBilling
client = AsyncNovaBilling(
token="sk_live_a1b2c3d4e5f6g7h8i9j0..."
)
Authentication
All API calls require a token parameter passed at client initialization. This token is sent as a Bearer token with every request. There is no automatic environment variable reading -- you must always provide the token explicitly.
import os
from novabilling import NovaBilling
client = NovaBilling(
token=os.environ["NOVABILLING_TOKEN"]
)
Customers
Customers represent the people or businesses you bill. Every subscription, invoice, and payment is linked to a customer. Each customer has a unique email within your tenant and can have metadata for storing your application-specific data.
Create a Customer
customer = client.customers.create(
external_id="usr_12345",
email="john@example.com",
currency="NGN",
name="John Doe",
metadata={
"plan": "enterprise",
"source": "website"
}
)
print(f"Created customer: {customer.data.id}")
Get a Customer
customer = client.customers.get("cus_x1y2z3a4b5c6")
print(f"Name: {customer.data.name}")
print(f"Email: {customer.data.email}")
Update a Customer
updated = client.customers.update(
"cus_x1y2z3a4b5c6",
name="John A. Doe",
metadata={
"plan": "enterprise",
"notes": "VIP customer"
}
)
List Customers
customers = client.customers.list(
page=1,
limit=20,
search="john",
sort_by="created_at",
sort_order="desc"
)
print(f"Total customers: {customers.meta.total}")
for customer in customers.data:
print(f"{customer.name} ({customer.email})")
Delete a Customer
client.customers.delete("cus_x1y2z3a4b5c6")
print("Customer deleted")
Get Customer Subscriptions
subscriptions = client.customers.get_subscriptions("cus_x1y2z3a4b5c6")
for sub in subscriptions.data:
print(f"{sub.id}: {sub.status} - Plan: {sub.plan_id}")
Get Customer Invoices
invoices = client.customers.get_invoices("cus_x1y2z3a4b5c6")
for invoice in invoices.data:
print(f"{invoice.id}: {invoice.status} - {invoice.currency} {invoice.amount}")
Plans
Plans define what you sell -- the product tiers, billing frequency, and included features. Each plan has a unique code and can have prices in multiple currencies. Plans can be deactivated to prevent new subscriptions without affecting existing ones.
Create a Plan
plan = client.plans.create(
name="Pro Plan",
code="pro_monthly",
billing_interval="monthly",
description="Professional plan with advanced features",
features=[
"Unlimited projects",
"Priority support",
"Advanced analytics",
"API access",
"Custom integrations"
]
)
print(f"Created plan: {plan.data.id}")
List Plans
plans = client.plans.list(
active=True
)
for plan in plans.data:
print(f"{plan.name} ({plan.code}): {plan.billing_interval}")
Update a Plan
updated = client.plans.update(
"pln_d7e8f9g0h1i2",
name="Pro Plan v2",
features=[
"Unlimited projects",
"Priority support",
"Advanced analytics",
"API access",
"Custom integrations",
"Dedicated account manager"
]
)
Deactivate a Plan
deactivated = client.plans.update(
"pln_d7e8f9g0h1i2",
active=False
)
Subscriptions
Subscriptions connect customers to plans and manage the recurring billing lifecycle. A subscription tracks the current billing period, status (active, paused, canceled), and handles automatic renewals. You can pause, resume, cancel, or change the plan of any active subscription.
Create a Subscription
subscription = client.subscriptions.create(
customer_id="cus_x1y2z3a4b5c6",
plan_id="pln_d7e8f9g0h1i2",
currency="NGN",
metadata={
"source": "website",
"campaign": "launch_promo"
}
)
print(f"Subscription status: {subscription.data.status}")
print(f"Current period ends: {subscription.data.current_period_end}")
Cancel a Subscription
canceled = client.subscriptions.cancel(
"sub_j3k4l5m6n7o8",
cancel_at_period_end=True # Continue access until period ends
)
print(f"Subscription will cancel at: {canceled.data.current_period_end}")
Pause a Subscription
paused = client.subscriptions.pause("sub_j3k4l5m6n7o8")
print("Subscription paused")
Resume a Subscription
resumed = client.subscriptions.resume("sub_j3k4l5m6n7o8")
print("Subscription resumed")
Change Plan
updated = client.subscriptions.change_plan(
"sub_j3k4l5m6n7o8",
plan_id="pln_newplan123"
)
print(f"Plan changed. New period end: {updated.data.current_period_end}")
List Subscriptions
subscriptions = client.subscriptions.list(
customer_id="cus_x1y2z3a4b5c6",
status="active",
page=1,
limit=20
)
for sub in subscriptions.data:
print(f"{sub.id}: {sub.status} - Plan: {sub.plan_id}")
Invoices
Invoices are billing documents that track amounts owed by customers. They can be created automatically from subscriptions or manually for one-off charges. Invoices go through a lifecycle: draft, finalized, paid, or voided. You can also generate PDF versions for download.
Create an Invoice
from novabilling.types import InvoiceItemDto
invoice = client.invoices.create(
customer_id="cus_x1y2z3a4b5c6",
items=[
InvoiceItemDto(
description="Pro Plan - Monthly",
amount=15000,
quantity=1
),
InvoiceItemDto(
description="Additional API calls (500)",
amount=2500,
quantity=1
)
],
due_date="2025-02-28T00:00:00Z",
notes="Thank you for your business!"
)
print(f"Invoice ID: {invoice.data.id}")
print(f"Total: {invoice.data.currency} {invoice.data.total}")
List Invoices
invoices = client.invoices.list(
customer_id="cus_x1y2z3a4b5c6",
status="finalized",
page=1,
limit=10
)
for invoice in invoices.data:
print(f"{invoice.id}: {invoice.status} - {invoice.currency} {invoice.total}")
Finalize an Invoice
finalized = client.invoices.finalize("inv_p1q2r3s4t5u6")
print(f"Invoice finalized. PDF URL: {finalized.data.pdf_url}")
Void an Invoice
voided = client.invoices.void("inv_p1q2r3s4t5u6")
print(f"Invoice voided: {voided.data.status}")
Mark an Invoice as Paid
paid = client.invoices.mark_paid("inv_p1q2r3s4t5u6")
print(f"Invoice marked paid: {paid.data.status}")
Get Invoice PDF
pdf = client.invoices.get_pdf("inv_p1q2r3s4t5u6")
print(f"PDF URL: {pdf.data.url}")
Payments
Payments are read-only records created automatically when invoices are paid through a payment provider. You can list, retrieve, and refund payments.
List Payments
payments = client.payments.list(
customer_id="cus_x1y2z3a4b5c6",
status="successful",
page=1,
limit=20
)
total = 0
for payment in payments.data:
total += payment.amount
print(f"{payment.id}: {payment.currency} {payment.amount} - {payment.status}")
print(f"Total paid: {total}")
Get a Payment
payment = client.payments.get("pay_v1w2x3y4z5a6")
print(f"Payment ID: {payment.data.id}")
print(f"Status: {payment.data.status}")
print(f"Amount: {payment.data.currency} {payment.data.amount}")
Refund a Payment
refund = client.payments.refund(
"pay_v1w2x3y4z5a6",
amount=15000, # Partial refund
reason="Customer requested plan downgrade"
)
print(f"Refund ID: {refund.data.id}")
print(f"Refund status: {refund.data.status}")
Payment Providers
Payment providers are the external services that process payments on your behalf. NovaBilling supports Stripe, Flutterwave, Paystack, and M-Pesa. Configure one or more providers and set priorities to control the fallback order when a provider is unavailable.
List Payment Providers
providers = client.payment_providers.list()
for provider in providers.data:
print(f"{provider.name}: {provider.type} - {'Active' if provider.active else 'Inactive'}")
Configure a Payment Provider
provider = client.payment_providers.create(
type="stripe",
name="Stripe Production",
credentials={
"secret_key": "sk_live_...",
"publishable_key": "pk_live_..."
}
)
print(f"Provider configured: {provider.data.id}")
Webhooks
Webhooks let you receive real-time HTTP notifications when events happen in your NovaBilling account, such as successful payments, subscription cancellations, or failed charges. Register an endpoint URL and choose which events to subscribe to.
List Webhooks
webhooks = client.webhooks.list()
for webhook in webhooks.data:
print(f"{webhook.url}: {webhook.status}")
Create a Webhook
webhook = client.webhooks.create(
url="https://yourapp.com/webhooks/novabilling",
events=["invoice.finalized", "payment.successful", "subscription.canceled"]
)
print(f"Webhook ID: {webhook.data.id}")
print(f"Secret: {webhook.data.secret}")
Error Handling
The SDK raises typed exceptions for different error scenarios.
from novabilling import NovaBilling
from novabilling import (
BadRequestError,
NotFoundError,
UnauthorizedError,
ConflictError
)
client = NovaBilling(token="sk_live_...")
try:
customer = client.customers.get("cus_nonexistent")
except NotFoundError as e:
print(f"Customer not found: {e.message}")
except BadRequestError as e:
print(f"Bad request: {e.message}")
except UnauthorizedError as e:
print(f"Authentication failed: {e.message}")
except ConflictError as e:
print(f"Conflict: {e.message}")
except Exception as e:
print(f"Unexpected error: {e}")
Error Types
| Exception Class | HTTP Status | Description |
|---|---|---|
BadRequestError | 400 | Request body or parameters are invalid |
UnauthorizedError | 401 | Missing or invalid authentication credentials |
NotFoundError | 404 | The requested resource does not exist |
ConflictError | 409 | Resource state conflict (e.g., duplicate email) |
Async Support
The SDK provides a fully asynchronous client for use with asyncio.
import asyncio
from novabilling import AsyncNovaBilling
async def main():
client = AsyncNovaBilling(
token="sk_live_a1b2c3d4e5f6g7h8i9j0..."
)
# All methods are async
customer = await client.customers.create(
external_id="usr_12345",
email="john@example.com",
currency="NGN",
name="John Doe"
)
print(f"Created customer: {customer.data.id}")
# Concurrent requests
customer_task = client.customers.get("cus_x1y2z3a4b5c6")
plans_task = client.plans.list(active=True)
customer, plans = await asyncio.gather(customer_task, plans_task)
print(f"Customer: {customer.data.name}")
print(f"Active plans: {plans.meta.total}")
asyncio.run(main())
Pagination
Manual Pagination
page = 1
has_more = True
while has_more:
response = client.customers.list(page=page, limit=100)
for customer in response.data:
print(customer.name)
has_more = page * 100 < response.meta.total
page += 1
Type Hints
The SDK includes comprehensive type hints for all models and methods. This enables IDE autocompletion, static type checking with mypy, and documentation tooltips.
from novabilling.types import (
Customer,
Plan,
Subscription,
Invoice,
InvoiceItemDto,
Payment,
PaginatedResponse,
Currency,
BillingInterval,
SubscriptionStatus,
InvoiceStatus,
PaymentStatus
)
from typing import List
def process_customers(customers: List[Customer]) -> None:
for customer in customers:
print(f"Processing {customer.name} ({customer.id})")
# Type-safe literals
currency: Currency = "NGN"
interval: BillingInterval = "monthly"
Configuration Options
client = NovaBilling(
# Required
token="sk_live_...",
# Optional
base_url="https://api.novabilling.com", # Custom base URL
timeout=60.0, # Request timeout in seconds (default: 60)
follow_redirects=True, # Follow HTTP redirects (default: True)
)
Next Steps
- Explore the TypeScript SDK if you also work with Node.js.
- Read the Guides for in-depth usage patterns.
- Check the API Reference for all available endpoints.