namibrapay (Python)
Official NamibraPay client for Python. Collections, payouts, verification, invoices and status — with zero dependencies.
- Standard library only (
urllib,hmac,json) - Sync client, Python 3.9+
- PEP 561 typed (
py.typedincluded) - Retries that never double-charge
Install
pip install namibrapay
Quick start
import os
from namibrapay import NamibraPay
client = NamibraPay(
api_key=os.environ["NAMBRAPAY_API_KEY"],
api_secret=os.environ["NAMBRAPAY_API_SECRET"],
)
tx = client.transactions.collect(
amount=2500, # GHS 25.00, in minor units
channel="mtn_momo",
payer_identifier="0244000000",
reference="ORDER-1042",
)
print(tx["reference"], tx["status"])
Omit the credentials to read NAMBRAPAY_API_KEY and NAMBRAPAY_API_SECRET
from the environment:
client = NamibraPay()
Python arguments are snake_case; the SDK maps them to the API's camelCase
fields for you (payer_identifier → payerIdentifier).
Configuration
| Option | Default | Notes |
|---|---|---|
api_key / api_secret |
env vars | Sent as X-API-Key / X-API-Secret |
base_url |
https://api.namibrapay.com/api/v1 |
Must include the version segment |
timeout |
30.0 |
Per attempt, in seconds |
max_retries |
2 |
Applies only to retry-safe calls |
headers |
None |
Extra headers on every request |
transport |
urllib |
Advanced/testing hook |
Resources
client.transactions.collect(amount=..., channel=..., payer_identifier=..., reference=..., idempotency_key=None)
client.transactions.initialize(amount=..., reference=...)
client.transactions.payout(amount=..., channel=..., recipient_account=..., recipient_bank=..., recipient_name=..., reference=...)
client.transactions.get(reference)
client.transactions.receipt(reference)
client.transactions.reverse(transaction_id, reason=..., amount=None)
client.checkout.retrieve(reference)
client.checkout.pay(reference, channel=..., payer_identifier=...)
client.payment_links.retrieve(slug)
client.payment_links.charge(slug, channel=..., payer_identifier=..., amount=None)
client.invoices.retrieve(code)
client.invoices.pay(code)
client.virtual_accounts.create(customer_name=..., customer_phone=..., ghana_card_number=...)
client.virtual_accounts.list()
client.virtual_accounts.sync_balance(account_id)
client.verification.banks()
client.verification.networks()
client.verification.resolve_account(bank_reference=..., account_number=..., amount=None)
client.verification.resolve_wallet(network=..., wallet_number=...)
client.verification.verify_id(id_type="ghanacard", id_number=...)
client.verification.confirm_payee(payee_type=..., expected_name=..., account_number=..., bank_reference=None, network=None)
client.status.snapshot()
client.status.incidents(page=None, limit=None) # {"data": [...], "pagination": {...}}
client.status.feed() # RSS 2.0 as a string
client.health()
Every method returns the data object from the envelope directly — a dict,
not a custom model, so new API fields arrive without an SDK release.
Money amounts
Amounts are integers in minor units (pesewas) and must be whole cedis:
GHS 10.00 → 1000. Collections have a minimum of 100, payouts 1000. The
SDK raises NamibraPayError before any request is made when the value is
invalid.
Errors
from namibrapay import NamibraPayAPIError, NamibraPayConnectionError, NamibraPayError
try:
client.transactions.payout(...)
except NamibraPayAPIError as error:
if error.code == "BIZ_009":
... # insufficient balance, etc.
print(error.status_code, error.errors)
except NamibraPayConnectionError as error:
print("network failed", error.cause)
NamibraPayAPIError exposes status_code, code, errors, body,
retry_after_seconds and is_retryable.
Retries and idempotency
The SDK retries 408, 429, 500, 502, 503 and 504 with backoff and
honours Retry-After.
| Call | Retried? | Why |
|---|---|---|
GET (get, receipt, status, …) |
Yes | Reads are safe to repeat |
collect, initialize, payout |
Yes | The API deduplicates on reference |
Any call with idempotency_key |
Yes | The key makes the retry safe |
reverse, checkout.pay, payment_links.charge, invoices.pay, virtual_accounts.create |
No | A retry would create a second money movement |
Webhooks
from flask import Flask, request, abort
from namibrapay.webhooks import construct_webhook_event, WebhookSignatureError
app = Flask(__name__)
@app.post("/webhooks/namibrapay")
def receive():
try:
event = construct_webhook_event(
request.get_data(), # raw bytes, not request.json
request.headers.get("X-Webhook-Signature", ""),
app.config["NAMBRAPAY_WEBHOOK_SECRET"],
)
except WebhookSignatureError:
abort(401)
# Acknowledge fast; do the work out of band.
return "", 200
verify_webhook_signature and compute_webhook_signature are available if you
prefer to handle the details yourself. Comparison is constant-time.
Async
This release is synchronous. Inside async frameworks (FastAPI, Starlette, aiohttp) run calls in a worker thread so the event loop stays free:
from starlette.concurrency import run_in_threadpool
tx = await run_in_threadpool(client.transactions.get, "ORDER-1042")
Versioning
The package follows semver. Additions are minor, breaking changes are major.
namibrapay.__version__ matches pyproject.toml.
License
Metadata
Release files for namibrapay 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| namibrapay-0.1.0.tar.gz | 21.6 kB | Without provenance | Details for namibrapay-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| namibrapay-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for namibrapay-0.1.0-py3-none-any.whl |
Total release size: 41.8 kB
Release files / namibrapay-0.1.0.tar.gz
| Download URL | namibrapay-0.1.0.tar.gz |
|---|---|
| Size | 21.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e9a5071efa6ebff163ba0f70ae0e357a06d1fc2e2f931747a4787f59628bf02
|
|
BLAKE2b-256 checksum How to use checksums |
a3d2260dcefff57eca20b60d02dbe39ae1fc65e6a2b196b31696ca6a28b8b5c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|
Release files / namibrapay-0.1.0-py3-none-any.whl
| Download URL | namibrapay-0.1.0-py3-none-any.whl |
|---|---|
| Size | 20.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
455b6d39131e4f406afc6694db0229093f127d639163af2118b1f603af8f7c74
|
|
BLAKE2b-256 checksum How to use checksums |
113178ca2dd1722106f09bb609d8499eb37c623c2f334dde70c9cdc80e8dc516
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|
Security for namibrapay 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.