Skip to content

Quickstart

You need a test secret key (sk_test_…). Locally, yarn bootstrap prints one for the demo merchant; an operator can issue more from the operator console. Keys are shown once — store them server-side.

Terminal window
curl -s -X POST http://localhost:4000/v1/payments \
-H "Authorization: Bearer $XAALIS_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042" \
-d '{"amount":15000,"description":"Commande #1042","client_reference":"order_1042","success_url":"https://shop.example/merci"}'
{
"id": "pay_…", "object": "payment", "livemode": false,
"amount": 15000, "currency": "XOF", "fee": 225, "net": 14775,
"status": "requires_payment_method",
"checkout_url": "http://localhost:3000/pay/pay_…?cs=pay_…_secret_…",
"expires_at": "…"
}

fee is your Xaalis fee (1.5 % by default, rounded up to the franc); net is what reaches your balance.

The hosted checkout lets them choose Wave or Orange Money. In test mode both lead to a test wallet page with Approuver / Refuser — no real money moves.

From a script you can play the customer instead:

Terminal window
curl -s -X POST "http://localhost:4000/v1/payments/$PAYMENT_ID/simulate" \
-H "Authorization: Bearer $XAALIS_KEY" -H "Content-Type: application/json" \
-d '{"outcome":"succeeded"}'

3. Confirm — with a webhook, not the redirect

Section titled “3. Confirm — with a webhook, not the redirect”

A customer landing on your success_url proves nothing (they can type that URL). Fulfil the order when you receive the signed payment.succeeded webhook, or when GET /v1/payments/{id} says succeeded.

Terminal window
curl -s http://localhost:4000/v1/balance -H "Authorization: Bearer $XAALIS_KEY"
# {"object":"balance","livemode":false,"currency":"XOF","available":14775,"pending_payouts":0}

Next: Payments for the full lifecycle, or the Node SDK to skip the curl.