Skip to content

Python SDK

xaalis (in integrations/sdk-python) wraps the API for Python 3.9+ servers. Standard library only — no requests, no httpx — and fully type-hinted. Not on PyPI yet: pip install ./integrations/sdk-python.

import os
from xaalis import Xaalis, XaalisAPIError, construct_event, format_xof
xaalis = Xaalis(os.environ["XAALIS_SECRET_KEY"], base_url="http://localhost:4000")
payment = xaalis.payments.create(
amount=15000,
description="Commande #1042",
client_reference="order_1042",
success_url="https://shop.example/merci",
idempotency_key="payment:order_1042",
)
print(format_xof(payment["amount"]), payment["checkout_url"])

Objects are plain dicts typed as TypedDicts (Payment, Payout, Balance, Account, WebhookDelivery, WebhookEvent). Every amount is an int in XOF.

API Methods
payments create, retrieve, list, list_all (generator over every page)
payouts create, retrieve, list, list_all
balance retrieve
account retrieve, update(webhook_url=...)
webhook_deliveries list(limit=...)
test_helpers simulate_payment(id, "succeeded" | "failed") — test keys only
construct_event(raw, header, secret) verify and parse a webhook
  • Idempotency: every create sends an Idempotency-Key (random unless you pass idempotency_key=) and reuses it on each retry. See Idempotency.
  • Retries: network errors, 429 and 5xx, with exponential backoff and Retry-After — only when replaying is safe (reads, PATCH, or creates carrying their key). Default 2 retries, 30 s timeout per attempt. Redirects are never followed.
  • Errors: XaalisAPIError (status, code, message, details), XaalisConnectionError, XaalisSignatureError — all subclasses of XaalisError. Codes are listed in Errors.
  • Safety: refuses a live key over http://; rejects non-int amounts before sending; never puts the key in an error message or repr.
try:
xaalis.payouts.create(amount=5000, provider="wave", recipient={"phone": "+221770000001"})
except XaalisAPIError as err:
if err.code == "insufficient_funds":
... # show "balance too low"
else:
raise

Pass the raw request bytes — Flask request.get_data(), Django request.body — never re-serialized JSON:

from xaalis import XaalisSignatureError, construct_event
try:
event = construct_event(request.body, request.headers.get("Xaalis-Signature"), os.environ["XAALIS_WEBHOOK_SECRET"])
except XaalisSignatureError:
return HttpResponse(status=400)
# answer 2xx fast, deduplicate on event["id"], check event["livemode"], then fulfil

In test mode, xaalis.test_helpers.simulate_payment(payment["id"], "succeeded") drives the payment to its final state and fires the same webhook live mode would.

Examples: integrations/sdk-python/examples/ (checkout, webhook server with http.server, payout). Tests: cd integrations/sdk-python && python3 -m unittest discover -s tests -v. See also the Node SDK.