Python SDK Stable
Official Python SDK. Full type hints, sync + async (asyncio) support, Django / Flask / FastAPI compatible.
- Package:
zayonoon PyPI - Source: github.com/zayono/zayono-python
- License: MIT
- Python: 3.9+
- HTTP: httpx (sync + async)
Installation
pip install zayonoOr with Poetry:
poetry add zayonoConfiguration
import os
from zayono import Zayono
client = Zayono(api_key=os.environ["ZAYONO_API_KEY"])Advanced options:
client = Zayono(
api_key=os.environ["ZAYONO_API_KEY"],
base_url="https://backend.zayono.com/api/v1", # default
timeout=30.0, # seconds, default 30
max_retries=3, # default 3
)Initialize a payment
payment = client.payments.create(
amount=5000,
currency="XOF",
description="Premium T-shirt",
return_url="https://your-site.com/success",
customer={
"email": "customer@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+22990123456",
},
operator="mtn_bj",
metadata={"order_id": "ORD-12345"},
)
print(payment.checkout_url)
# → https://app.zayono.com/checkout/abc123...Verify a payment
payment = client.payments.retrieve("019e5eaf-cb99-7351-a6d5-c219e28534db")
if payment.status == "success":
# Payment confirmed. Fulfil the order.
passInitialize a payout
payout = client.payouts.create(
amount=10000,
currency="XOF",
operator="mtn_bj",
description="Payout for order ORD-12345",
recipient={
"phone": "+22961000000",
"first_name": "Adele",
"last_name": "Akpovi",
},
)Refunds
Refunds will be added to the SDK once the /v1/payments/{id}/refunds endpoint is exposed on the API key surface. For now, use the dashboard.
Verify a webhook signature
Django
from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from zayono import Zayono
import json
import os
client = Zayono(api_key=os.environ["ZAYONO_API_KEY"])
@csrf_exempt
@require_POST
def webhook(request):
signature = request.META.get("HTTP_X_ZAYONO_SIGNATURE", "")
if not client.webhooks.verify(
request.body, signature, os.environ["ZAYONO_WEBHOOK_SECRET"]
):
return HttpResponseBadRequest("Invalid signature")
event = json.loads(request.body)
# ... process the event
return HttpResponse(status=200)FastAPI
from fastapi import FastAPI, Request, HTTPException
from zayono import Zayono
import os
app = FastAPI()
client = Zayono(api_key=os.environ["ZAYONO_API_KEY"])
@app.post("/webhook")
async def webhook(request: Request):
body = await request.body() # RAW bytes, not request.json()
signature = request.headers.get("x-zayono-signature", "")
if not client.webhooks.verify(
body, signature, os.environ["ZAYONO_WEBHOOK_SECRET"]
):
raise HTTPException(401, "Invalid signature")
event = await request.json()
# ... process the event
return {"received": True}Async mode
For async frameworks (FastAPI, Starlette, etc.) the SDK exposes a native asyncio client:
import asyncio
from zayono import AsyncZayono
async def main():
async with AsyncZayono(api_key="zyn_test_xxxxx") as client:
payment = await client.payments.create(
amount=5000,
currency="XOF",
description="Test",
return_url="https://example.com/success",
customer={
"email": "c@example.com",
"first_name": "Test",
"last_name": "User",
},
operator="mtn_bj",
)
print(payment.checkout_url)
asyncio.run(main())Pagination
Payment / payout listing not exposed on v1
The GET /v1/payments (and GET /v1/payouts) endpoint is not yet exposed on the API key surface. Only unit methods (retrieve, verify) are available. Pagination will be added to the SDK once those endpoints are exposed. In the meantime, check transaction history from the Zayono dashboard.
For customers, GET /v1/customers is exposed — sync iterator, paginates automatically:
for customer in client.customers.list(country="BJ"):
print(customer.id)Async version:
async for customer in client.customers.list(country="BJ"):
print(customer.id)Error handling
from zayono.exceptions import (
ValidationError, AuthenticationError, RateLimitError,
)
try:
payment = client.payments.create(amount=-1, currency="XOF", ...)
except ValidationError as e:
# 422 — e.errors is a dict {field: [messages]}
for field, msgs in e.errors.items():
print(f"{field}: {', '.join(msgs)}")
except AuthenticationError:
# 401
pass
except RateLimitError as e:
# 429 — e.retry_after in seconds
passType hints
The SDK ships full .pyi stubs. mypy + pyright + Pylance catch errors before runtime:
from zayono.types import Payment, PaymentStatus
def process(p: Payment) -> None:
if p.status == PaymentStatus.SUCCESS:
...Compatibility
| Python version | Status |
|---|---|
| 3.9 | Supported |
| 3.10 | Recommended |
| 3.11 | Recommended |
| 3.12 | Recommended |
| 3.13 | Supported |