Skip to main content

Overview

The Bila Python SDK provides convenient access to the Bila REST API from any Python 3.9+ application. It includes type definitions for all request params and response fields, and offers both synchronous and asynchronous clients.

Fully Typed

Type definitions for every request param and response field.

Sync & Async

Synchronous and asynchronous clients powered by httpx.

Comprehensive

Access to all Bila API features: Accounts, Transfers, Collections, and more.

Stainless Generated

Consistently structured and always up-to-date with the latest API changes.

Installation

pip install usebila

Quick Start

import os
from usebila import Bila
 
client = Bila(
    api_key=os.environ.get("BILA_API_KEY"),  # This is the default and can be omitted
    environment="sandbox",  # defaults to "production"
)
 
accounts = client.accounts.list()
print(accounts.message)
While you can provide an api_key keyword argument, it’s recommended to use python-dotenv to add BILA_API_KEY="My API Key" to your .env file so your API key isn’t stored in source control.

API Classes

The SDK is organized into resources, each handling a specific domain:
ResourceDescription
AccountsRetrieve accounts, list accounts, and check balances
TransferRecipientsManage payout recipients for bank and mobile money transfers
TransfersSend payouts via bank transfer and mobile money
CollectionsCollect payments via mobile money
TransactionsRetrieve and list transaction history
WebhooksConfigure webhooks and manage delivery history
BanksList supported banks and financial institutions
ResolveVerify bank account and mobile money details

Accounts

Manage your Bila wallets and check balances. Types: AccountRetrieveResponse, AccountListResponse, AccountGetBalanceResponse

Methods

client.accounts.retrieve(id) Retrieve details for a specific account.
ACCOUNT_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
account = client.accounts.retrieve(ACCOUNT_ID)
print("retrieve:", account)
Returns: AccountRetrieveResponse client.accounts.list(**params) List all accounts associated with your profile.
accounts = client.accounts.list(page=1, per_page=50)
print("list:", accounts)
Returns: AccountListResponse client.accounts.get_balance(id) Check the real-time balance of an account.
balance = client.accounts.get_balance(ACCOUNT_ID)
print("get_balance:", balance)
Returns: AccountGetBalanceResponse

TransferRecipients

Manage payout recipients for bank and mobile money transfers. Types: TransferRecipientRetrieveResponse, TransferRecipientListResponse, TransferRecipientCreateBankAccountResponse, TransferRecipientCreateMobileMoneyResponse

Methods

client.transfer_recipients.retrieve(id) Retrieve details for a specific transfer recipient.
TRANSFER_RECIPIENT_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
recipient = client.transfer_recipients.retrieve(TRANSFER_RECIPIENT_ID)
print("retrieve:", recipient)
Returns: TransferRecipientRetrieveResponse client.transfer_recipients.list(**params) List all transfer recipients.
recipients = client.transfer_recipients.list(page=1, per_page=50)
print("list:", recipients)
Returns: TransferRecipientListResponse client.transfer_recipients.create_bank_account(**params) Create a new bank account transfer recipient.
bank_recipient = client.transfer_recipients.create_bank_account(
    account_number="1234567890",
    bank_id="bank-001",
    country="zm",
    name="John Doe",
)
print("create_bank_account:", bank_recipient)
Returns: TransferRecipientCreateBankAccountResponse client.transfer_recipients.create_mobile_money(**params) Create a new mobile money transfer recipient.
mobile_recipient = client.transfer_recipients.create_mobile_money(
    phone="0977433571",
    operator="airtel",
    country="zm",
    name="Jane Doe",
)
print("create_mobile_money:", mobile_recipient)
Returns: TransferRecipientCreateMobileMoneyResponse

Transfers

Send funds to bank accounts or mobile money wallets. Types: TransferRetrieveResponse, TransferListResponse, TransferGetStatusByReferenceResponse, TransferInitiateBankTransferResponse, TransferInitiateMobileMoneyTransferResponse

Methods

client.transfers.retrieve(id) Retrieve details for a specific transfer.
TRANSFER_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
transfer = client.transfers.retrieve(TRANSFER_ID)
print("retrieve:", transfer)
Returns: TransferRetrieveResponse client.transfers.list(**params) List all transfers.
transfers = client.transfers.list(
    account_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
    start_date="2024-01-01T00:00:00Z",
    end_date="2024-12-31T23:59:59Z",
    page=1,
    per_page=50,
    status="pending",
    type="bank-account",
)
print("list:", transfers)
Returns: TransferListResponse client.transfers.get_status_by_reference(reference) Get the status of a transfer by its reference.
BANK_REFERENCE = "transfer-001"
 
status = client.transfers.get_status_by_reference(BANK_REFERENCE)
print("get_status_by_reference:", status)
Returns: TransferGetStatusByReferenceResponse client.transfers.initiate_bank_transfer(**params) Initiate a bank transfer.
bank_transfer = client.transfers.initiate_bank_transfer(
    account_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
    amount=1000,
    reference="transfer-001",
    account_number="1234567890",
    bank_id="bank-001",
    country="zm",
    narration="Payment for services",
    recipient_name="Jane Doe",
    transfer_recipient_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
    wallet_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
)
print("initiate_bank_transfer:", bank_transfer)
Returns: TransferInitiateBankTransferResponse client.transfers.initiate_mobile_money_transfer(**params) Initiate a mobile money transfer.
mobile_transfer = client.transfers.initiate_mobile_money_transfer(
    amount=250,
    country="zm",
    operator="airtel",
    phone="0977433571",
    reference="mobile-transfer-001",
    narration="Mobile money payout",
    recipient_name="Jane Doe",
    wallet_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
)
print("initiate_mobile_money_transfer:", mobile_transfer)
Returns: TransferInitiateMobileMoneyTransferResponse

Collections

Accept mobile money payments from customers. Types: CollectionRetrieveResponse, CollectionListResponse, CollectionGetStatusByReferenceResponse, CollectionInitiateMobileMoneyCollectionResponse

Methods

client.collections.retrieve(id) Retrieve details for a specific collection.
COLLECTION_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
collection = client.collections.retrieve(COLLECTION_ID)
print("retrieve:", collection)
Returns: CollectionRetrieveResponse client.collections.list(**params) List all collections.
collections = client.collections.list(
    account_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
    start_date="2024-01-01T00:00:00Z",
    end_date="2024-12-31T23:59:59Z",
    page=1,
    per_page=50,
    status="pending",
)
print("list:", collections)
Returns: CollectionListResponse client.collections.get_status_by_reference(reference) Get the status of a collection by its reference.
REFERENCE = "collection-001"
 
status = client.collections.get_status_by_reference(REFERENCE)
print("get_status_by_reference:", status)
Returns: CollectionGetStatusByReferenceResponse client.collections.initiate_mobile_money_collection(**params) Initiate a mobile money collection.
initiated = client.collections.initiate_mobile_money_collection(
    amount=100.5,
    country="zm",
    operator="airtel",
    phone="0977433571",
    reference="collection-001",
    wallet_id="68f11209-451f-4a15-bfcd-d916eb8b09f4",
    bearer="customer",
    customer_name="John Doe",
    narration="Payment for subscription",
)
print("initiate_mobile_money_collection:", initiated)
Returns: CollectionInitiateMobileMoneyCollectionResponse

Transactions

View and manage transaction history. Types: TransactionRetrieveResponse, TransactionListResponse

Methods

client.transactions.retrieve(id) Retrieve details for a specific transaction.
TRANSACTION_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
transaction = client.transactions.retrieve(TRANSACTION_ID)
print("retrieve:", transaction)
Returns: TransactionRetrieveResponse client.transactions.list(**params) List all transactions.
transactions = client.transactions.list(page=1, per_page=50)
print("list:", transactions)
Returns: TransactionListResponse

Webhooks

Configure endpoints to receive real-time event notifications. Types: WebhookCreateResponse, WebhookUpdateResponse, WebhookListResponse, WebhookGetDeliveriesResponse, WebhookListEventsResponse, WebhookRotateSecretResponse

Methods

client.webhooks.create(**params) Register a new webhook endpoint.
webhook = client.webhooks.create(
    events=["payment.completed", "withdrawal.completed", "transfer.completed"],
    url="https://example.com/webhooks",
)
print("create:", webhook)
Returns: WebhookCreateResponse client.webhooks.update(id, **params) Update an existing webhook.
WEBHOOK_ID = "68f11209-451f-4a15-bfcd-d916eb8b09f4"
 
updated_webhook = client.webhooks.update(
    WEBHOOK_ID,
    events=["payment.completed", "collection.completed", "transfer.failed"],
    url="https://example.com/webhooks/v2",
    is_active=True,
)
print("update:", updated_webhook)
Returns: WebhookUpdateResponse client.webhooks.list() List all registered webhooks.
webhooks = client.webhooks.list()
print("list:", webhooks)
Returns: WebhookListResponse client.webhooks.deactivate(id) Deactivate a webhook.
deactivated = client.webhooks.deactivate(WEBHOOK_ID)
print("deactivate:", deactivated)
Returns: BilaResponse client.webhooks.get_deliveries(id, **params) Get delivery history for a specific webhook.
deliveries = client.webhooks.get_deliveries(
    WEBHOOK_ID,
    start_date="2026-04-01T00:00:00.000Z",
    end_date="2026-04-30T23:59:59.999Z",
    event_type="payment.completed",
    page=1,
    per_page=20,
    status="DELIVERED",
)
print("get_deliveries:", deliveries)
Returns: WebhookGetDeliveriesResponse client.webhooks.list_events() List all supported webhook events.
events = client.webhooks.list_events()
print("list_events:", events)
Returns: WebhookListEventsResponse client.webhooks.rotate_secret(id) Rotate the signing secret for a webhook.
rotated = client.webhooks.rotate_secret(WEBHOOK_ID)
print("rotate_secret:", rotated)
Returns: WebhookRotateSecretResponse

Banks

Utilities for listing supported financial institutions. Types: BankListResponse

Methods

client.banks.list(**params) List supported banks for a specific country.
banks = client.banks.list(country="zm")
print("list:", banks)
Returns: BankListResponse

Resolve

Utilities for verifying account details. Types: ResolveBankAccountResponse, ResolveMobileMoneyResponse

Methods

client.resolve.bank_account(**params) Verify the owner of a bank account.
resolution = client.resolve.bank_account(
    account_number="1234567890",
    bank_id="bank-001",
)
print("bank_account:", resolution)
Returns: ResolveBankAccountResponse client.resolve.mobile_money(**params) Verify mobile money details.
resolution = client.resolve.mobile_money(
    phone="0977433571",
    operator="airtel",
    country="zm",
)
print("mobile_money:", resolution)
Returns: ResolveMobileMoneyResponse

Async Usage

Import AsyncBila instead of Bila and use await with each API call. Functionality between the synchronous and asynchronous clients is otherwise identical.
import os
import asyncio
from usebila import AsyncBila
 
client = AsyncBila(
    api_key=os.environ.get("BILA_API_KEY"),
    environment="sandbox",
)
 
 
async def main() -> None:
    accounts = await client.accounts.list()
    print(accounts.message)
 
 
asyncio.run(main())

Error Handling

When the library is unable to connect to the API, a subclass of usebila.APIConnectionError is raised. When the API returns a non-success status code (4xx or 5xx), a subclass of usebila.APIStatusError is raised, containing status_code and response properties. All errors inherit from usebila.APIError.
import usebila
from usebila import Bila
 
client = Bila()
 
try:
    client.accounts.list()
except usebila.APIConnectionError as e:
    print("The server could not be reached")
    print(e.__cause__)
except usebila.RateLimitError as e:
    print("A 429 status code was received; we should back off a bit.")
except usebila.APIStatusError as e:
    print("Another non-200-range status code was received")
    print(e.status_code)
    print(e.response)
Status CodeError Type
400BadRequestError
401AuthenticationError
403PermissionDeniedError
404NotFoundError
422UnprocessableEntityError
429RateLimitError
>=500InternalServerError
N/AAPIConnectionError

Type Definitions

Every API method has typed request params and responses. Types are available from usebila.types:
from usebila import Bila
from usebila.types import AccountListResponse, CollectionListParams
 
client = Bila(
    api_key="Your API key",
    environment="sandbox",
)
 
# Response type — what the API returns
accounts: AccountListResponse = client.accounts.list()
 
# Request type — what you send to the API
params: CollectionListParams = {
    "account_id": "your-wallet-id",
    "page": 1,
    "per_page": 50,
}
collections = client.collections.list(**params)
Type names follow a simple pattern:
KindPatternExample
Response{Resource}{Action}ResponseTransferRetrieveResponse
Request params{Resource}{Action}ParamsWebhookCreateParams

Best Practices

1

Use Environment Variables

Store API credentials in environment variables, never in source code. Consider using python-dotenv to load BILA_API_KEY from a .env file.
2

Implement Webhook Signature Verification

Always verify webhook signatures to ensure events are legitimately from Bila and haven’t been tampered with.
3

Handle Errors Gracefully

Catch usebila.APIConnectionError, usebila.RateLimitError, and usebila.APIStatusError separately to handle each failure mode appropriately.

Next Steps

SDK Quickstart

Complete integration guide with examples

Transfers

Learn about initiating transfers

Webhooks

Set up webhook notifications

API Reference

Complete REST API documentation