Skip to content

Python SDK

The official Cashfin SDK for Python applications.

Installation

bash
pip install cashfin-business-sdk

Requirements

  • 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

VariableDescription
CASHFIN_CLIENT_SECRETYour API client secret (from Cashfin Dashboard)
CASHFIN_BASE_URLAPI 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")
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 += 1

Auto-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 pytest

Contributing

Want to contribute to the Python SDK?

  1. Check our GitLab repository or PyPI package
  2. Review open issues
  3. Submit pull requests

Getting Help

Cashfin Business API Documentation