Juno Solutions

Integration

One catalogue call, one launch call, five callbacks

There is no SDK to install and no library to keep up to date. You call two of our endpoints, we call five of yours, and everything is JSON over HTTPS. A competent backend team has this working in an afternoon.

The sequence

What your backend does, in order

Fetch the catalogue

Public and unauthenticated, so you can browse it before any account exists. Games we have switched off are absent from the list rather than flagged disabled — anything returned is safe to put in your lobby.

GET https://junosolutions.store/api/v1/games

{
  "data": [
    { "game_id": 6, "game_code": "BBCrash", "game_title": "Crash",
      "platforms": ["desktop", "mobile", "retail"] }
  ],
  "error": null
}

Open a session for a player

You pass the player's identifier and the session token you already issued them. We replay that token verbatim on every wallet call and never inspect it, so your existing auth keeps working exactly as it does elsewhere on your site.

POST https://junosolutions.store/launch_url
Authorization: <your player's session token>
X-Signature:    hex(HMAC-SHA256(raw body, your api_key))

{
  "player_id":        "7241",
  "game_id":          "6",
  "mode":             "real",
  "client_config_id": "14",
  "language":         "en",
  "currency":         "KES",
  "clientPlatform":   "desktop"
}

— 200
{ "data": { "game_url": "https://...", "balance": 1500.00,
            "currency": "KES" }, "error": null }

Send mode: "demo" and we skip your wallet entirely on a fixed play-money balance — worth doing as your first end-to-end test, before any money is wired up.

Send the player to game_url

Redirect the browser or embed it in an iframe; both are supported. From there the game drives play and your wallet starts hearing from us.

Answer five callbacks

Registered once against your account as a single base URL. We derive the five endpoints from it, so there is nothing to configure per game.

POST {your base}/auth/{your id}      log the player in, return balance
POST {your base}/debit/{your id}     take a stake
POST {your base}/credit/{your id}    pay a win
POST {your base}/cancel/{your id}    reverse an unsettled stake
POST {your base}/balance/{your id}   optional balance probe

Every one of them is keyed on ticket_id, and that matters more than anything else on this page: we retry timeouts and 5xx responses by design. A wallet that charges per request rather than per ticket takes money from players twice. If you have already processed a ticket, return the same answer you returned the first time.

A decline is not an error. Insufficient funds, a cancel on an already-settled bet, a cancel of something never staked — all of those are a 200 with {"accepted": false} and a note. Returning 500 for a business decline tells us to retry it.

Test your own wallet, whenever you like

We ship a conformance suite you run yourself against your own integration. It needs no credential from us beyond the API key you already have, and that signature is what scopes it — it can only ever test your own account.

BODY='{"client_config_id":14,"profile_tag":"test-player",
       "mode":"conformance","stake_amount":1}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$API_KEY" -hex \
      | sed 's/.*= //')

curl -X POST https://junosolutions.store/wallet-test \
  -H 'Content-Type: application/json' \
  -H "X-Signature: $SIG" -d "$BODY"

Start in readonly mode, which touches nothing and is safe against production at any time. Then run conformance, which covers the five cases that cost real money and never show up in a happy-path test.

  • The same debit sent twice — must charge once
  • The same credit sent twice — must pay once
  • Cancel after a credit — must be refused, the bet already settled
  • Cancel of a ticket never debited — must be refused, nothing was staked
  • A negative stake — must be refused, or a player can pay themselves

We will not agree a go-live date on "we have tested it". We run this against your wallet ourselves and go through the result with you, because the replay and negative-amount cases are precisely the ones a working integration passes and production does not.

Every call we make to you is logged

Request body, your response, status code, latency, and each retry as its own entry. So "what did you send me at 14:32, and how many times?" has an answer rather than an argument. Please still log your side: we can show what we sent, only you can show what your code did with it.

Settings, not releases

Stake minimum and maximum, preset stake buttons, maximum payout, per-round exposure ceiling, return to player, currency, and your brand name, logo and accent colour are all account settings. They take effect on the next round.

Retail runs on the same contract

A shop launch is the same endpoint with a different mode. Shops, cashiers and float sit on our side, and your own backend can create and manage them over the API with a separate key from the one your wallet uses — so a compromised game key cannot open shops.

Your staff can see their own numbers

An operator dashboard with your turnover, gross gaming revenue, margin and per-game breakdown, scoped so you see your accounts and nobody else's. Optional, and it needs no work on your side.

Before you go live

We put your server's IP on the launch allowlist, issue your API key once, and run the conformance suite with you. Full API reference goes out with your account details.