Skip to content

Node / TypeScript SDK

@xaalis/sdk is the server-side TypeScript client (Node 20+, no runtime dependencies, MIT licence).

Terminal window
npm install https://docs.xaalis.org/downloads/xaalis-sdk-0.1.0.tgz # `npm install @xaalis/sdk` once it is on npm

Every release, its checksums and the other packages: Downloads.

import { XaalisClient, XaalisApiError, constructEvent, formatXof } from "@xaalis/sdk";
// baseUrl defaults to https://api.xaalis.org (always HTTPS: live keys are refused over plain HTTP).
// A sandbox account's keys belong to https://sandbox-api.xaalis.org — set it explicitly for those.
const xaalis = new XaalisClient({ secretKey: process.env.XAALIS_SECRET_KEY!, baseUrl: process.env.XAALIS_API_URL });
const payment = await xaalis.payments.create(
{ amount: 15000, description: "Commande #1042", client_reference: "order_1042", success_url: "https://shop.example/merci" },
{ idempotencyKey: "payment:order_1042" }, // required, and the same on every retry
);
console.log(formatXof(payment.amount), payment.checkout_url);
API Methods
payments create, retrieve, list, listAll (async iterator over every page)
payouts create, retrieve, list, listAll
payments.refunds create(paymentId, { idempotencyKey }), list(paymentId) — see Refunds
subscriptions create, retrieve, list, listAll, cancel, testAdvance (test keys) — see Subscriptions
invoices retrieve, list, listAll (filters subscription, status)
balance retrieve
agentWallets create, fund, reclaim, disable, keys, payouts — see Agent wallets
testHelpers simulatePayment(id, "succeeded" | "failed") — test keys only
constructEvent(raw, header, secret) verify and parse a webhook
const refund = await xaalis.payments.refunds.create(payment.id, { idempotencyKey: `refund:${payment.id}` });
const sub = await xaalis.subscriptions.create(
{ customer: { phone: "+221771234567", name: "Awa Ndiaye" }, amount: 5_000, interval: "month" },
{ idempotencyKey: "subscription:customer-123:monthly" },
);
// Send sub.latest_invoice?.hosted_invoice_url to the customer (it stays valid across payment attempts).
  • Idempotency is explicit: every create takes an idempotencyKey you choose (your order or withdrawal id) — it stays the same across retries and process restarts.
  • Retries only when safe: reads on network errors, 429 and 5xx, and any request answered 429, honouring Retry-After (maxRetries, default 2). If a write’s outcome is unknown (error.outcomeUnknown), retry it yourself with the same key.
  • Errors: XaalisApiError (status, code, message), XaalisNetworkError / XaalisProtocolError (outcomeUnknown), XaalisSignatureError.
  • Safety: refuses to run in a browser and refuses a live key over http://.
try {
await xaalis.payouts.create({ amount: 5000, provider: "wave", recipient: { phone: "+221770000001" } }, { idempotencyKey: "withdraw:2026-09-27" });
} catch (err) {
if (err instanceof XaalisApiError && err.code === "insufficient_funds") {
/* show "balance too low" */
} else throw err;
}

A complete integration using it: Example shop. Full reference: packages/sdk/README.md.