Add Maktub games to your site
You keep the player’s wallet. Maktub runs the games.
Connect your wallet, create a player session from your backend, and open the game in an iframe. The same integration works across the game catalog. No game SDK is required.
Before you start
Ask Maktub for your client ID, webhook secret and environment addresses. Register two public HTTPS URLs with us: your main wallet endpoint and your retry endpoint. Both use the same wallet and transaction records.
| Address in the examples | Purpose |
|---|---|
https://server.maktub.bet | Your backend calls the Maktub API. |
https://play.maktub.bet | Your frontend opens the game. |
Use the addresses confirmed for your environment. Keep the secret on your
backend. Every session is opened in the player’s currency: send
currency: { "code": "ZAR" } when creating it. Every wallet amount is in that currency. Non-USD bets (including free-bet placements) and credits may also
carry usdRate, a reporting value; apply the received amount without conversion.
1. Connect your wallet
Implement the wallet webhook contract on both URLs. It receives balance queries, debits, credits and round-close notifications.
That page is the complete wallet specification: request fields, signature verification, exact HTTP responses and duplicate handling. Your database remains the source of truth for the player’s balance.
2. Create a session
When a logged-in player opens a game, call POST /session from your backend.
Use the player ID from your authenticated session, not an arbitrary ID sent
by the browser.
Example inside your existing authenticated backend handler:
const response = await fetch("https://server.maktub.bet/session", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-operator-secret": process.env.MAKTUB_WEBHOOK_SECRET,
},
body: JSON.stringify({
clientId: process.env.MAKTUB_CLIENT_ID,
userId: String(req.user.id),
currency: { code: req.user.walletCurrency }, // e.g. "ZAR"
}),
});
if (response.status !== 200) {
throw new Error("Could not create the game session");
}
const session = await response.json();
const launchUrl = new URL(session.gameUrl);
launchUrl.pathname = "/dice";
res.json({ launchUrl: launchUrl.toString() });Maktub checks the player through your webhook before returning a session. Your wallet must recognize the player; a balance of zero is valid.
gameUrl already includes the Maktub token. Set its path to the chosen game and
keep its query parameters. Share the resulting URL only with that player and
keep it out of logs.
Need your own reference on the webhooks? See session references.
3. Show the game
Add an iframe to your page and set its src to the launchUrl returned by your
backend:
<iframe
id="maktub-game"
title="Maktub game"
style="width:100%;height:730px;border:0;display:block"
allow="fullscreen; clipboard-write"
></iframe>// launchUrl is the string received from your backend.
const frame = document.getElementById("maktub-game");
frame.src = launchUrl;The iframe handles gameplay, including WebSocket connections. If your site uses
CSP, allow the Play origin in frame-src.
This fixed-size embed is enough to start. For automatic height changes on small screens, add the resize listener.
4. Test before going live
Open the Webhook Tester with a disposable player holding 0.10–1.00 in your wallet’s currency. Enter your endpoint, secret, client ID, test player ID and the wallet’s currency code. Use your own session reference only if you supplied one when creating the session. Enter the retry endpoint registered during onboarding as well.
The tester runs 27 checks: 23 wallet checks and four retry checks, each with an explanation of failures. It moves money and attempts to restore the starting balance after every check. Keep this wallet idle elsewhere during the run. If recovery is required, reconcile its ledger before reusing it.
A zero-balance wallet runs four read-only diagnostics and skips 23 money checks. Passing those diagnostics does not validate debits or credits. The tester probes authentication independently and reports whether each endpoint requires HMAC, accepts the shared secret, or requires both.
Finally, open each game you plan to offer, play a test round and match its webhooks to your wallet ledger. A tester pass does not verify live delivery or game availability.
Add only what you need
| If you need… | Read… |
|---|---|
| Field types, errors or session renewal | Sessions |
| A different game | Game catalog |
| Colors, language or logos | Appearance |
| Resize, loading or login messages | Browser events |
| Promotional wagers | Free bets |