SoftAggregator API documentation

Integrate 40,000+ casino games through one seamless-wallet API. This reference covers everything you need to list games, create players, launch games, award free rounds and handle wallet callbacks.

Introduction

The SoftAggregator API uses a seamless wallet model: your platform keeps player balances, and our API calls your callback URL for every balance check, bet and win. All API methods are sent as POST requests with a JSON body to a single endpoint.

Base URL
https://api.softaggregator.com/api/v1

Authentication

Every request includes your api_login and api_password (issued in your operator backend after approval). The method field selects the operation.

{
  "api_login": "YOUR_API_LOGIN",
  "api_password": "YOUR_API_PASSWORD",
  "method": "getGameList"
}

Multiple websites on one account

You can run several websites or projects on a single SoftAggregator account. Add each site in your operator backend (API integration → Your other sites) and it is issued its own api_login, api_password, salt_key and its own callback URL. Your credit balance, game catalogue, pricing and billing stay shared on the one account.

Shared across your sitesPer site
Credit balance, game catalogue, prices, invoicing, reportingapi_login / api_password / salt_key, callback URL, default player currency, players

Each site also carries its own default player currency, set in the same screen. It is only a default: the currency field you send on createPlayer / getGame still wins, so per-player multi-currency keeps working exactly as it does today. Order of precedence: currency on the call → the currency already recorded for that player → the site's default → your account default.

Always call us with the keys of the site the player belongs to. Players are scoped to the site whose keys created them, so two sites may safely use the same user_username (e.g. 1042 on both) without ever touching each other's wallet: each bet and win is sent back to the callback URL of that site only, with the username exactly as you sent it.

Nothing changes if you run a single website — your existing keys and callback URL keep working as they are.

Currencies

Every money method — createPlayer, getGame, getGameDemo and addFreeRounds — accepts an optional currency field (ISO 4217 code, e.g. EUR, USD, BRL, INR, PKR). It sets the currency the player sees in the game — bet limits and balance.

WhenBehaviour
currency omittedThe default currency of the site whose keys made the call is used — and your account default when that site has none.
currency providedMust be a currency enabled for your account — i.e. supported by the products you have enabled. A currency that is not supported makes the launch fail.
Per playerA player's currency is set the first time the player is created and does not change afterwards. Use a distinct user_username if you need the same person in another currency.

Wallet callbacks (balance / debit / credit) carry the same currency, and amount is always in that currency's minor units (e.g. 2.50 → 250). The currencies available to you are provisioned by SoftAggregator — contact support or @mentionso to enable a new currency on your account.

Pick the currency your players see in your operator portal (Integration → Player currency for the account, Integration → Your other sites for a specific site) — the choices are the currencies supported by the products you have enabled. Or read the same list from the API with getCurrencies below.

getCurrenciesGet your currencies

Returns the currencies enabled for your account, so you can pick the right currency value programmatically instead of hard-coding it.

POST /api/v1
{ "api_login":"...", "api_password":"...", "method":"getCurrencies" }

→ {
  "error": 0,
  "response": {
    "default": "PKR",            // send this on getGame / createPlayer (or omit to use it)
    "currencies": ["PKR","EUR"], // currencies your account may use
    "settlement": "EUR"          // currency your account is billed in
  }
}

getGameListGet game list

Returns all games available to you. Use each game's id_hash when launching a game.

POST /api/v1
{ "api_login": "...", "api_password": "...", "method": "getGameList" }

→ {
  "error": 0,
  "response": [
    {
      "id": 483,
      "name": "Game Name",
      "game_type": "slots",          // normalised category — use THIS to build your lobby
      "provider": "pragmaticplay",   // studio key, matches getProviderList
      "provider_name": "Pragmatic Play",
      "provider_logo": "https://cdn.imagesai.org/p/pragmaticplay.png",
      "type": "Video Slots",         // raw studio label — inconsistent, kept for compatibility
      "category": "pragmaticplay",   // raw studio code — kept for compatibility
      "id_hash": "provider/GameName",
      "freerounds_supported": true,
      "play_for_fun_supported": true,
      "image": "https://.../GameName.webp"
    }
  ]
}
Categories — use game_type, not type. type and category are passed through from the game studios and are not consistent: there are two dozen different labels for a handful of real categories, and many crash games arrive labelled as slots. game_type is our normalised value and is one of a fixed list: slots, live, crash, table, instant, bingo, keno, fishing, virtual, sportsbook, other. The list will not change without notice. type and category are unchanged, so existing integrations keep working.

getProviderListGet providers

Returns the game studios available to you, with a display name and a logo. Each provider value matches the provider field of every game in getGameList, so you can build a provider filter with a straight one-to-one match. Studios that publish under several codes (for example two Pragmatic Play feeds) are returned once.

POST /api/v1
{ "api_login": "...", "api_password": "...", "method": "getProviderList" }

→ {
  "error": 0,
  "response": [
    {
      "provider": "pragmaticplay",
      "name": "Pragmatic Play",
      "logo": "https://cdn.imagesai.org/p/pragmaticplay.png",
      "games": 3410
    }
  ]
}

Logos are PNG, 400×160, served from our own CDN — no external hosts, nothing that can be filtered by a national ISP. They are cached for one day, so a logo we improve reaches your players without any change on your side.

createPlayerCreate player

Creates (or ensures) a player on the system before launching a game.

{ "api_login":"...", "api_password":"...", "method":"createPlayer",
  "user_username":"player123", "user_password":"secret", "currency":"EUR" }

→ { "error": 0, "response": { ... } }

getGameLaunch game

Returns the URL to load the game in an iframe. Use the id_hash from getGameList as gameid.

FieldDescription
user_usernamePlayer username
user_passwordPlayer password
gameidGame id_hash
langLanguage code, e.g. en
currencyOptional — player currency (see Currencies). Defaults to your account currency.
deviceOptional — desktop (default) or mobile. Some game platforms refuse a launch that does not declare the device.
countryPlayer country, ISO 3166 alpha-2 (e.g. ET, BR). Optional by default, required on accounts serving a restricted market — see the note below. user_country is accepted as an alias.
homeurlReturn URL after the player exits
play_for_funOptional — demo mode
{ "api_login":"...", "api_password":"...", "method":"getGame",
  "user_username":"player123", "user_password":"secret",
  "gameid":"provider/GameName", "lang":"en", "currency":"EUR",
  "country":"BR", "homeurl":"https://yourcasino.com" }

→ { "error": 0, "response": "https://game-launch-url..." }
For demo play use method: "getGameDemo" with the same parameters. country is never required in demo mode.

Restricted markets. Studios are not licensed everywhere, and a few of them exclude specific countries. We enforce that per player, from the country you send on the launch — we never guess it from an IP address. A game the player's country is not allowed to open is refused with Game not available in your country; everything else launches normally. If your account serves a market where studio restrictions apply, we switch country from optional to required and a launch without it is refused with country is required on getGame. Send it on every real-money launch and you are covered whatever we enable later.

addFreeRoundsFree rounds

Award free spins on a supported game (freerounds_supported: true in the game list).

{ "api_login":"...", "api_password":"...", "method":"addFreeRounds",
  "user_username":"player123", "user_password":"secret",
  "gameid":"provider/GameName", "freespins":10, "bet_level":0,
  "valid_days":7, "currency":"EUR" }

Use getFreeRounds to list and deleteFreeRounds to remove them.

getPlayerHistoryPlayer history

Returns the round history of one of your players, newest first. One entry per game round (all legs of a round are merged). Amounts are integers in cents, in the currency the round was played in.

{ "api_login":"...", "api_password":"...", "method":"getPlayerHistory",
  "user_username":"player123",
  "limit":50, "offset":0,
  "date_from":"2026-08-01 00:00:00", "date_to":"2026-08-01 23:59:59",
  "gameid":"x6046f4988155b46", "round_id":"..." }

Only user_username is required. limit defaults to 50 (max 500); gameid is the id_hash from getGameList; date_from/date_to are UTC.

{ "error":0, "response":{
    "user_username":"player123", "total":128, "limit":50, "offset":0,
    "rounds":[
      { "round_id":"88c6807b55e7434c3e00aa50dc82240e",
        "gameid":"x6046f4988155b46", "game_name":"Gates of Olympus 1000",
        "currency":"USD", "bet":40, "win":58, "net":18,
        "legs":2, "rolled_back":false,
        "started_at":"2026-08-01 16:10:15", "ended_at":"2026-08-01 16:10:24" } ] } }
FieldMeaning
totalRounds matching the filter (for paging), not the number returned
bet / winTotal wagered / paid for the round, in cents
netwin - bet: negative = player lost the round
legsWallet movements merged into this round
rolled_backtrue if the round was cancelled/refunded
Scope. This is a record of money movements, not of game outcomes. The result of a round — reel symbols, cards dealt, multipliers, baccarat roadmaps — is produced inside the game itself and never reaches the wallet layer, so it cannot be returned here. A bet your wallet refused is not listed either, since nothing moved. You may only read your own players.

Wallet callbacks

We call your callback URL (set in your operator backend — one per website, see Multiple websites) for every player balance change. Callbacks are sent as GET requests. Your endpoint must always return HTTP 200; communicate errors only via the JSON body. Balances are always integers in cents (e.g. €2.50 → 250).

action: balance

Sent at the start of a session to read the player's balance.

GET {your_callback}?username=player123¤cy=EUR&action=balance
     &call_id=...×tamp=...&key=...

← { "error": 0, "balance": 250 }

action: debit / credit

debit subtracts a bet; credit adds a win. call_id is the unique transaction id — use it to de-duplicate. If funds are insufficient on a debit, return error: 1 with the current balance.

GET {your_callback}?username=player123¤cy=EUR&action=debit
     &amount=100&type=bet&round_id=...&game_id=provider/GameName
     &call_id=...×tamp=...&rb=0&key=...

← { "error": 0, "balance": 150 }

Two rules your handler must follow.

  1. Never reject a callback because of type. Branch on action only. type is informational and its set of values grows as we add providers — treat an unknown value as a normal bet or win.
  2. A credit can arrive with no matching debit. Free spins, bonus rounds and jackpot payouts are wins with amount only — there is no bet to match them against. De-duplicate on call_id alone; requiring a prior debit means your players never get paid for free-spin wins.
FieldDescription
amountAmount in cents
actiondebit | credit | balance
typeInformational, never reject on it. bet on a debit, win on a credit; bonus_fs marks a free spin (nothing to deduct on debit). Other values may appear.
call_idUnique transaction id (de-dup)
round_idGame round id
game_idGame id_hash
rb1 = rollback (process like a normal debit/credit)

Signature validation

Every callback carries timestamp and key. Validate that the timestamp is within 30 seconds and that the key matches:

key = md5(timestamp + your_salt_key)

Your salt_key is shown in your operator backend. If validation fails, return { "error": 2, "balance": 0 }.

Error codes

CodeMeaning
0Success
1Insufficient balance (return current balance)
2Processing error / invalid signature / player not found

Need help integrating? Contact us on Telegram @mentionso or email [email protected].

API changes, new game providers and planned maintenance are announced on our Telegram channel — @casinogamessoftware. Worth following if you maintain this integration.