Skip to content

Python SDK

xaalis wraps the API for Python 3.9+ servers. Standard library only — no requests, no httpx — fully type-hinted, MIT licence.

Terminal window
pip install https://docs.xaalis.org/downloads/xaalis-0.1.0-py3-none-any.whl # `pip install xaalis` once it is on PyPI

Every release and its checksums: Downloads.

import os
from xaalis import Xaalis, XaalisAPIError, construct_event, format_xof
xaalis = Xaalis(os.environ["XAALIS_SECRET_KEY"], base_url="https://sandbox-api.xaalis.org")
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"])

base_url follows the key when you leave it out: https://sandbox-api.xaalis.org for a sk_test_… key, https://api.xaalis.org for sk_live_…. Refused with ValueError: a live key over http:// or to sandbox-api.xaalis.org, a test key to api.xaalis.org or http://sandbox-api.xaalis.org, and any URL with credentials, a query or a fragment. Other hosts (a proxy, http://localhost:4000) are accepted. SDK 0.1.0 defaulted to https://api.xaalis.sn for every key, which does not answer, and refuses none of these hosts: on 0.1.0 always pass the base_url that matches your key.

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:// and, from 0.1.1, a key sent to the other environment’s API; 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.