What you can do
- Create payment requests (invoices) in MGA with an amount, description, and your own reference.
- Accept payments by MVola, Airtel Money, Orange Money, or card — the money lands in your Dralako wallet.
- Check your balance and monitor every payment request from your own systems.
- Use QR codes and links generated for each request — no app needed on the customer's side.
How it works
- 1Get an API key. In the wallet, open Settings → API keys and generate a key. You get a
client_idand aclient_secret— keep the secret safe. - 2Exchange it for a token. Call
POST /v1/auth/tokenwith your credentials to receive a short-lived access token. - 3Create payment requests. Call
POST /v1/transactionswith the amount and payment rail. Each request returns anidand a payment link/QR.
Endpoints
| Method & path | Description |
|---|---|
POST /v1/auth/token | Exchange client_id + client_secret for an access token |
GET /v1/balance | Available wallet balance (MGA) |
POST /v1/transactions | Create a payment request (amount, rail, description, reference) → returns a shareable pay_url |
GET /v1/transactions | List payment requests (keyset paginated) |
GET /v1/transactions/{id} | Payment request status |
POST /v1/transactions/{id}/start-payment | Start a card payment for a request → returns a payment URL |
Authenticate with Authorization: Bearer <token>. Payment rails: cc (card), mvola, airtel, orange.
Create, list and revoke keys with POST / GET / DELETE /api/merchant/apikeys.
Rate limits: 5/min token · 10/min create payment · 60/min reads.
Base URLs
| Environment | Base URL | Notes |
|---|---|---|
| Production | https://app.dralako.io | Live money movement |
| Sandbox | https://sandbox.dralako.io | Development & testing — no real money |
The wallet and the API are served from the same host: sandbox.dralako.io or app.dralako.io. API paths start with /v1.
Quick start
# 1. Get a token (returns {access_token: "..."})
curl -X POST https://sandbox.dralako.io/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"client_id":"ak_1234","client_secret":"sk_abcd"}'
# 2. Create a payment request of 25,000 MGA
curl -X POST https://sandbox.dralako.io/v1/transactions \
-H "Authorization: Bearer <access_token_from_step_1>" \
-H "Content-Type: application/json" \
-d '{"amount":25000,"rail":"mvola","description":"Order #123"}'
# 3. Track it
curl https://sandbox.dralako.io/v1/transactions/<invoice_id> \
-H "Authorization: Bearer <access_token_from_step_1>"
Webhooks
Pass callback_url when creating a transaction and we'll POST a signed JSON event when the payment succeeds or fails. The callback URL must be https and publicly reachable.
How delivery works
- Create the transaction with a
callback_url. - The customer pays — the money settles on your wallet.
- We POST the signed event to your
callback_url. - Your server verifies the signature, dedupes on
event_id, processes the order, and replies 200.
Events
| event | When |
|---|---|
transaction.succeeded | Payment settled — invoice paid |
transaction.failed | Terminal failure (mobile-money callback FAILED) |
transaction.payment_failed | Card attempt declined — NOT terminal; the customer can retry (reason carries the decline message) |
Payload
POST /your/hook
Content-Type: application/json
X-Dralako-Signature: t=1787000000,v1=<hex>
{
"event_id": "<uuid>",
"event": "transaction.succeeded" | "transaction.failed" | "transaction.payment_failed",
"invoice_id": "inv_...",
"tx_id": "tx_...",
"amount_mga": 5000,
"rail": "mvola",
"currency": "mga",
"status": "COMPLETED" | "FAILED" | "PENDING",
"provider_ref": "",
"reference_id": "order-123",
"description": "Order #1",
"reason": "",
"created_at": "2026-08-17T12:00:00Z"
}
Verifying the signature
Header X-Dralako-Signature: t=<unix_ts>,v1=<hex> with v1 = HMAC-SHA256(webhook_secret, "t=<unix_ts>." + raw_body). The webhook_secret (whsec_...) is shown when you create an API key. Reject events with an old t (replay protection) and always dedupe on event_id — delivery is at-least-once.
import hashlib, hmac, time
WEBHOOK_SECRET = "your_webhook_secret" # shown when you create an API key
def verify_and_process(raw_body, signature, payload):
parts = dict(p.split("=", 1) for p in signature.split(",") if "=" in p)
ts, v1 = parts.get("t", ""), parts.get("v1", "")
if not ts or not v1 or abs(time.time() - int(ts)) > 300:
return 400 # missing or stale (possible replay)
expected = hmac.new(
WEBHOOK_SECRET.encode(),
f"{ts}.".encode() + raw_body, # sign the RAW body bytes
hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, v1):
return 401 # not from Dralako — drop it
if payload["event_id"] in PROCESSED_IDS:
return 200 # at-least-once: dedupe, then ack
PROCESSED_IDS.add(payload["event_id"])
# ... your business logic (match on reference_id) ...
return 200 # ack fast; do heavy work in the background
Retries & responding
Reply 2xx to acknowledge — any other status, a timeout, or an unreachable URL triggers retries at 1m, 5m, 30m, 2h, 6h (max 5 attempts). Acknowledge fast and do heavy work in the background. If an event is ever lost, reconcile with GET /v1/transactions/{id}.
Test locally with dralako listen
Receive real, signed webhook events on localhost — no public URL, no ngrok. Install the CLI, log in with your API key, and point it at your local endpoint. Events arrive byte-identical to production HTTPS delivery (same body, same signature), so your verification code works unchanged.
- Install the CLI (sandbox only):
curl -fsSL https://sandbox.dralako.io/install.sh | sh - Log in with your API key (prompts for the secret, never stored in shell history):
dralako login - Forward events to your local endpoint:
dralako listen --forward-to http://localhost:8080/webhooks/dralako - Create a payment (
rail=cc+ a test card in the sandbox) — the signed event arrives at your localhost endpoint. Nocallback_urlis needed while the listener is connected.
curl -fsSL https://sandbox.dralako.io/install.sh | sh
dralako login
dralako listen --forward-to http://localhost:8080/webhooks/dralako
Embedded checkout
You can show the payment page inside your own site with an <iframe>. Register the origin(s) you will embed from first — until you do, the page refuses to be framed by anyone.
curl -X PUT https://sandbox.dralako.io/api/users/<user_id>/embed-origins \
-H "Authorization: Bearer <session_token>" \
-H "Content-Type: application/json" \
-d '{"origins":["https://shop.example"]}'
Then embed the pay_url returned when you create the transaction:
<iframe src="https://sandbox.dralako.io/pay/<token>"
width="420" height="640" style="border:0"
title="Dralako payment"></iframe>