Python SDK
The official Cashfin SDK for Python applications.
Installation
bash
pip install cashfin-business-sdkRequirements
- Python 3.8 or later
Quick Start
python
import os
from cashfin_sdk.main import CashfinSDK
os.environ["CASHFIN_CLIENT_SECRET"] = "cs_your_client_secret"
os.environ["CASHFIN_BASE_URL"] = "https://api.cashfin.africa"
sdk = CashfinSDK()Authentication
Authentication is handled via environment variables. Set them before initialising the SDK:
python
import os
from cashfin_sdk.main import CashfinSDK
os.environ["CASHFIN_CLIENT_SECRET"] = "cs_your_client_secret"
os.environ["CASHFIN_BASE_URL"] = "https://api.cashfin.africa" # optional, this is the default
sdk = CashfinSDK()TIP
Find your client secret under Settings → API Keys in the Cashfin Dashboard.
Environment Variables
| Variable | Description |
|---|---|
CASHFIN_CLIENT_SECRET | Your API client secret (from Cashfin Dashboard) |
CASHFIN_BASE_URL | API base URL (default: https://api.cashfin.africa) |
Products
List Products
python
products = sdk.business.products.list(status="published", type="product")
for product in products.data:
print(product.title)Get Product
python
product = sdk.business.products.get("507f1f77bcf86cd799439011")
print(product.title)
print(product.price)Create Product
python
product = sdk.business.products.create(
title='Premium Widget',
description='A high-quality widget',
price=1999.99,
stock=100,
type='product',
status='published',
featured=True,
variants=[
{
'attributetitle': 'Color',
'valuetitle': 'Blue',
'valueprice': 1999.99,
'valuestock': 50
}
]
)
print(f"Created: {product.id}")Update Product
python
product = sdk.business.products.update(
'507f1f77bcf86cd799439011',
price=2499.99,
stock=75
)Categories
List Categories
python
categories = sdk.business.categories.list()Create Category
python
category = sdk.business.categories.create(
title='Electronics',
description='Electronic devices and accessories',
status='active'
)Update Category
python
category = sdk.business.categories.update(
'507f191e810c19729de860ea',
status='archived'
)Orders
Create Checkout
python
order = sdk.business.orders.checkout(
customeremail='[email protected]',
items=[
{
'itemid': '507f1f77bcf86cd799439011',
'quantity': 2,
'rate': 1999.99
}
],
shippingaddress={
'name': 'John Doe',
'address': '123 Main St',
'city': 'Nairobi',
'country': 'Kenya',
'phone': '+254712345678'
}
)
print(f"Order: {order.orderno}")
print(f"Payment: {order.paymentlink.shorturl}")List Orders
python
orders = sdk.business.orders.list(status="processing")Get Order
python
order = sdk.business.orders.get("order_id")Payments
M-Pesa STK Push
python
payment = sdk.business.payment.request_stk_push(
phone_number='+254712345678',
ref_id='ORDER-001',
amount=1500
)
print(f"Checkout ID: {payment.checkoutrequestid}")Transactions
python
# List transactions
transactions = sdk.business.transactions.list(page=1, limit=20, status="completed")
# Get a transaction
transaction = sdk.business.transactions.get("transaction_id")Receipts
python
receipts = sdk.business.receipts.list()
receipt = sdk.business.receipts.get("receipt_id")Payment Links
python
# Create a payment link
link = sdk.business.payment_links.create(title="Website Payment", amount=1000)
# List payment links
links = sdk.business.payment_links.list()
# Get a payment link
link = sdk.business.payment_links.get("link_id")Invoices
python
# Create an invoice
invoice = sdk.business.invoices.create(
customerid='customer_id',
items=[{'itemid': 'prod_id', 'quantity': 1, 'rate': 1000}],
duedate='2025-12-31'
)
# List invoices
invoices = sdk.business.invoices.list()
# Get an invoice
invoice = sdk.business.invoices.get("invoice_id")
# Update an invoice
sdk.business.invoices.update("invoice_id", status="paid")Customers
Create Customer
python
customer = sdk.business.customers.create(
name='John Doe',
email='[email protected]',
phone='254712345678',
country='Kenya',
currency='KES',
type='individual'
)
print(f"Customer ID: {customer.id}")List & Search Customers
python
# List all customers
customers = sdk.business.customers.list()
# Search customers
results = sdk.business.customers.list(search="jane")Get Customer
python
customer = sdk.business.customers.get("customer_id")Update Customer
python
sdk.business.customers.update("customer_id", company="Acme Ltd")Subscriptions
Create Subscription
python
subscription = sdk.business.subscriptions.create(
customerid='507f1f77bcf86cd799439011',
items=[
{
'itemid': '507f191e810c19729de860ea',
'quantity': 1,
'rate': 2999.00
}
],
billingcycle='monthly',
autorenew=True
)
print(f"Subscription: {subscription.subscriptionno}")Get Subscription
python
subscription = sdk.business.subscriptions.get('507f1f77bcf86cd799439020')
print(f"Status: {subscription.status}")
print(f"Next Billing: {subscription.nextbillingdate}")Manage Subscriptions
python
# Cancel
sdk.business.subscriptions.cancel("sub_id")
# Pause
sdk.business.subscriptions.pause("sub_id")
# Resume
sdk.business.subscriptions.resume("sub_id")
# Generate invoice for the current billing cycle
sdk.business.subscriptions.generate_invoice("sub_id")CRM
Contacts
python
sdk.business.contacts.create(name="John Smith", email="[email protected]")
sdk.business.contacts.list()
sdk.business.contacts.get("contact_id")Leads
python
sdk.business.leads.create(name="Alice", source="website", budget=50000)
sdk.business.leads.list(status="new")Quotes
python
# Read-only
sdk.business.quotes.list(status="sent")
sdk.business.quotes.get("quote_id")Contracts
python
# Read-only
sdk.business.contracts.list(status="active")
sdk.business.contracts.get("contract_id")Bookings
python
# Read-only
sdk.business.bookings.list(status="scheduled")
sdk.business.bookings.get("booking_id")Appointments
python
# Read-only
sdk.business.appointments.list(status="active")
sdk.business.appointments.get("appointment_id")Purchases
Vendors
python
sdk.business.vendors.create(name="Office Supplies Co", type="business", phone="254700000000")
sdk.business.vendors.list()
sdk.business.vendors.get("vendor_id")
sdk.business.vendors.update("vendor_id", city="Nairobi")Expenses
python
sdk.business.expenses.create(title="Office rent", amount=30000, expensedate="2025-01-01")
sdk.business.expenses.list(status="approved")
sdk.business.expenses.get("expense_id")Bills
python
sdk.business.bills.create(
title="Electricity bill",
amount=5000,
billdate="2025-01-01",
duedate="2025-01-15"
)
sdk.business.bills.list()
sdk.business.bills.get("bill_id")Purchase Orders
python
sdk.business.purchase_orders.create(
title="Q1 stock order",
orderdate="2025-01-01",
deliverydate="2025-01-20"
)
sdk.business.purchase_orders.list()
sdk.business.purchase_orders.get("po_id")Marketing
Campaigns
python
# Read-only
sdk.business.campaigns.list(medium="email", status="sent")
sdk.business.campaigns.get("campaign_id")Marketing Lists
python
# Create a list
sdk.business.marketing_lists.create(name="Newsletter", type="email")
# List all
sdk.business.marketing_lists.list()
# Get a list
sdk.business.marketing_lists.get("list_id")
# Add a contact to a list
sdk.business.marketing_lists.add_contact(
list_id="list_id",
email="[email protected]",
firstname="Bob"
)Error Handling
python
from cashfin_sdk.error import (
CashfinError,
ValidationError,
AuthenticationError,
NotFoundError,
RateLimitError
)
try:
product = sdk.business.products.create(
title='Widget'
# Missing required fields
)
except ValidationError as e:
print(f'Validation errors: {e.errors}')
# {'price': 'Price is required'}
except AuthenticationError as e:
print('Check your API key')
except NotFoundError as e:
print('Resource not found')
except RateLimitError as e:
print(f'Rate limited. Retry after {e.retry_after} seconds')
except CashfinError as e:
print(f'API Error: {e.message}')
print(f'Status: {e.http_status}')Webhooks
Verify Signature
python
from flask import Flask, request
import os
from cashfin_sdk.main import CashfinSDK
from cashfin_sdk.webhook import Webhook
app = Flask(__name__)
@app.route('/webhooks/cashfin', methods=['POST'])
def webhook():
payload = request.data.decode('utf-8')
signature = request.headers.get('X-Cashfin-Signature')
secret = os.environ.get('CASHFIN_WEBHOOK_SECRET')
try:
event = Webhook.construct_event(
payload, signature, secret
)
except ValueError:
# Invalid payload
return 'Invalid payload', 400
except Exception:
# Invalid signature
return 'Invalid signature', 401
# Handle the event
if event.type == 'payment.completed':
handle_payment_completed(event.data)
elif event.type == 'order.created':
handle_order_created(event.data)
elif event.type == 'subscription.renewed':
handle_subscription_renewed(event.data)
return {'received': True}Pagination
Manual Pagination
python
page = 1
has_more = True
while has_more:
response = sdk.business.products.list(page=page, limit=100)
for product in response.data:
print(product.title)
has_more = page < response.meta.pages
page += 1Auto-Pagination
python
# Automatically handles pagination
for product in sdk.business.products.list().auto_paging_iter():
print(product.title)Django Integration
Settings
python
# settings.py
CASHFIN_CLIENT_SECRET = os.environ.get('CASHFIN_CLIENT_SECRET')
CASHFIN_WEBHOOK_SECRET = os.environ.get('CASHFIN_WEBHOOK_SECRET')
CASHFIN_BASE_URL = os.environ.get('CASHFIN_BASE_URL', 'https://api.cashfin.africa')Service Class
python
# services/cashfin_service.py
import os
from cashfin_sdk.main import CashfinSDK
from django.conf import settings
class CashfinService:
def __init__(self):
os.environ["CASHFIN_CLIENT_SECRET"] = settings.CASHFIN_CLIENT_SECRET
os.environ["CASHFIN_BASE_URL"] = settings.CASHFIN_BASE_URL
self.sdk = CashfinSDK()
def create_product(self, **kwargs):
return self.sdk.business.products.create(**kwargs)
def initiate_payment(self, amount, phone, reference):
return self.sdk.business.payment.request_stk_push(
amount=amount,
phone_number=phone,
ref_id=reference
)View Example
python
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .services.cashfin_service import CashfinService
class PaymentView(APIView):
def __init__(self):
self.cashfin = CashfinService()
def post(self, request):
amount = request.data.get('amount')
phone = request.data.get('phone')
order_id = request.data.get('order_id')
payment = self.cashfin.initiate_payment(
amount=amount,
phone=phone,
reference=order_id
)
return Response({
'success': True,
'checkout_id': payment.checkoutrequestid
})Webhook View
python
# views.py
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from cashfin_sdk.webhook import Webhook
from django.conf import settings
@csrf_exempt
def cashfin_webhook(request):
payload = request.body.decode('utf-8')
signature = request.headers.get('X-Cashfin-Signature')
try:
event = Webhook.construct_event(
payload, signature, settings.CASHFIN_WEBHOOK_SECRET
)
except Exception:
return JsonResponse({'error': 'Invalid webhook'}, status=400)
if event.type == 'payment.completed':
handle_payment_completed(event.data)
return JsonResponse({'received': True})Examples
Flask E-commerce
python
from flask import Flask, request, jsonify
import os
from cashfin_sdk.main import CashfinSDK
app = Flask(__name__)
os.environ["CASHFIN_CLIENT_SECRET"] = os.environ.get('CASHFIN_CLIENT_SECRET')
sdk = CashfinSDK()
@app.route('/api/checkout', methods=['POST'])
def checkout():
data = request.json
order = sdk.business.orders.checkout(
customeremail=data['email'],
items=[
{
'itemid': item['id'],
'quantity': item['quantity'],
'rate': item['price']
}
for item in data['items']
]
)
return jsonify({
'order_id': order.id,
'order_number': order.orderno,
'payment_url': order.paymentlink.shorturl
})
@app.route('/api/payment/mpesa', methods=['POST'])
def mpesa_payment():
data = request.json
payment = sdk.business.payment.request_stk_push(
amount=data['amount'],
phone_number=data['phone'],
ref_id=data['reference']
)
return jsonify({
'checkout_id': payment.checkoutrequestid,
'message': 'Check your phone for M-Pesa prompt'
})Development
bash
# Install UV
pip install uv
# Install dependencies
uv sync
# Run tests
uv run python -m pytestContributing
Want to contribute to the Python SDK?
- Check our GitLab repository or PyPI package
- Review open issues
- Submit pull requests