Integration Docs

Introduction

One IOP integration for Originals, casino games and sportsbook content available on your account. You keep the player balance; games settle through your HTTPS wallet webhook.

Amounts are integer minor units with two decimal places of the currency in each wallet request: 100 = 1.00. Never assume every request is USD.

Base URL

Use the gateway base URL issued with your account. Stage and production have separate credentials. Examples use https://YOUR_GATEWAY_HOST; replace it before calling.

Read the sections in the sidebar or download the integration reference. Last reviewed: 12 November 2026.

How it works

  • Your server requests a game launch from IOP. Embed the returned game URL in your site.
  • IOP calls your wallet for balances, bets, wins and rollbacks. Your durable wallet ledger is authoritative for player funds.
  • Use catalogue identifiers exactly as returned. IDs are opaque strings: do not infer a route, studio or game from their format.
  • One round can have several money movements. Idempotency belongs to TransactionId, not to event_id.
  • Game availability, native currency, free spins and billing depend on your account configuration and the individual game.

Credentials

SettingUse
apiKeyYour server-side API key. Send it in the launch JSON body; catalogue and billing reads use the x-api-key header. Never expose it in browser code or a URL.
webhookUrlYour public HTTPS wallet endpoint, registered in Integration → Config. It must be reachable before testing.
Wallet contract v2Implement rollback and have rollback support enabled before launching aggregated games.
Webhook signing secretA separate per-account secret, provisioned with IOP when signing is enabled. It is not your apiKey. See Security.

Keep stage and production credentials separate. Request account activation and allowed content through your IOP manager.

Launch a game

POST/gw/launch

Call from your backend. For real-money play, authenticate the player on your platform first.

FieldDescription
apiKeyRequired account API key.
gameIdRequired game ID from the account catalogue, unchanged.
loginYour stable player identifier, required for real-money play.
currencyRequested session currency, default USD. Support varies by game and account. Use the currency in each subsequent wallet request.
countryPlayer location as an ISO 3166-1 alpha-2 code, for example IN or DE. Also controls country-specific sportsbook presentation where configured.
ipThe player’s public IP address; supply their real public IPv4 address where required. Do not substitute your backend IP.
mobileBoolean indicating mobile delivery.
tokenOptional opaque session token echoed in wallet requests for correlation. It is not a substitute for callback authentication.
curl -X POST https://YOUR_GATEWAY_HOST/gw/launch   -H 'Content-Type: application/json'   -d '{"apiKey":"YOUR_API_KEY","gameId":"GAME_ID_FROM_CATALOG","login":"player-123","currency":"EUR","country":"DE","ip":"PLAYER_PUBLIC_IPV4","mobile":false,"token":"session-abc"}'

On success, use launch_options.game_url. Originals can also return game limits and provably-fair seed information; these are not guaranteed for every game.

Deliver the game

Embed the returned URL. Preserve its query parameters; do not construct or rewrite the URL yourself.

<iframe src="RETURNED_GAME_URL" style="width:100%;height:100%;border:0" allow="autoplay; fullscreen" allowfullscreen></iframe>

Test desktop and mobile, back navigation, reload and session expiry. Originals branding is configured in the backoffice. Do not put API keys into an iframe URL.

Game catalog

Use your account key in the x-api-key header for catalogue reads. Keep requests server-to-server.

GET/gw/catalog/providers
GET/gw/catalog/games

Games can be filtered with providerId, search, page and country. Use provider IDs returned by the providers feed; follow the feed’s pagination.

curl 'https://YOUR_GATEWAY_HOST/gw/catalog/games?country=DE&page=1'   -H 'x-api-key: YOUR_API_KEY'

Identifiers and artwork

Keep IDs as strings and pass them unchanged into launches. Use the image URLs and provider logos returned by the feed, including their version parameters. Do not build image URLs from a studio name or strip query parameters. Refresh your cached catalogue after entitlement or artwork changes.

The catalogue reflects account access when fetched. A subsequent launch can still fail because of current account status, currency, location, session validation or a temporary outage. Handle launch responses explicitly.

Free spins

Free spins require account activation and an eligible game/currency. The regular catalogue alone does not prove eligibility. Use POST /gw/freespins/games to read eligible games and POST /gw/freespins/bets with gameId and currency to read supported bet levels. Authenticate with x-api-key.

Issuance, status and cancellation use /gw/freespins/grant, /gw/freespins/status and /gw/freespins/cancel, all POST. Coordinate the bonus-wallet contract and run the free-spin acceptance tests with IOP before issuing campaigns. Never turn an uncertain grant response into a new claim ID.

Wallet webhook overview

Host one HTTPS endpoint accepting JSON POST requests. Successful responses use HTTP 200 and {"status":"success","balance":250000,"currency":"EUR"}. Balance is a safe integer in the request’s currency.

ActionPurpose
getBalanceRead the player’s current spendable balance in the requested currency.
processGameResultAtomically debit betAmount and credit winAmount, recording TransactionId.
rollbackReverse the referenced movement exactly once; required for aggregated games.

Durable processing

The outline below is pseudocode, not a ready-to-run wallet. Use a database transaction, concurrency control and a unique idempotency constraint scoped to your IOP account and TransactionId.

authenticate callback and validate action, player, currency and integer amounts
begin database transaction
  reserve the account + TransactionId with a unique constraint
  if already committed: verify the same movement, return current balance without applying again
  lock the player's wallet for this currency
  for a new bet: validate funds before debit
  for a win: credit the stated amount even when another win exists in the round
  for a rollback: resolve and reverse the referenced movement only once
  persist the wallet movement, result and idempotency record atomically
commit before returning success

Do not use an in-memory Set for financial idempotency. A process restart, concurrent request or lost HTTP response must not cause a second debit or credit.

getBalance

Return the current spendable balance in the request currency. Balance reads can happen during play as well as launch.

{"action":"getBalance","userId":"player-123","currency":"EUR","token":"session-abc","timestamp":1794484800000}
{"status":"success","balance":250000,"currency":"EUR"}

The optional currency in your response is an echo, not an instruction to convert. Never return a EUR balance for a USD request.

processGameResult

Each request is one settlement movement. A bet and win may arrive separately or together, and multiple wins may share a round.

{"action":"processGameResult","userId":"player-123","currency":"EUR","betAmount":0,"winAmount":4500,"gameId":"GAME_ID_FROM_CALLBACK","event_id":"round-123","TransactionId":"credit-456","token":"session-abc"}
{"status":"success","balance":254500,"currency":"EUR"}

Apply winAmount − betAmount atomically. An insufficient-funds rejection must use {"status":"error","error":"Insufficient funds"}, without applying the rejected movement.

Credit legitimate win-only and promotional payments even when no bet exists on that event. A zero-bet, zero-win call moves no money and settles open bets as lost, but does not close the event_id: later wins can still arrive. Do not reject a new payout just because an earlier payout was accepted.

Deduplicate by TransactionId. A changed ID is not sufficient evidence of a new economic payout when reconciling a disputed retry; ask IOP to map the original movement before manual recovery.

rollback

Reverse a previous movement in its original currency. Rollback requests have their own TransactionId and may include originalTransactionId identifying the movement being reversed.

{"action":"rollback","userId":"player-123","currency":"EUR","rollbackOf":"bet","betAmount":100,"event_id":"round-123","TransactionId":"rollback-789","originalTransactionId":"debit-123"}
  • rollbackOf: "bet": refund the referenced betAmount.
  • rollbackOf: "win": reverse the referenced winAmount.
  • Record the reversal and idempotency result atomically. An identical retry must not reverse twice.
  • If the original movement never applied, do not create a refund out of nothing. Record the resolved no-op so a delayed original cannot subsequently debit it.
  • Do not silently clamp a reversal or report success for an amount you did not reverse. Resolve unsupported or ambiguous cases with IOP.

A network timeout is not a rollback request. Do not invent a refund because an HTTP response was lost.

Integration flow

Your server -> IOP: POST /gw/launch
IOP -> your wallet: getBalance
IOP -> your server: launch_options.game_url
Player opens the game
IOP -> your wallet: processGameResult (bet)
IOP -> your wallet: processGameResult (one or more wins, possibly later)
IOP -> your wallet: rollback (when a movement must be reversed)

Sportsbook events may settle hours or days after the bet. Retain round and transaction records independently of the browser session. A lost response can lead to redelivery: acknowledge an already committed TransactionId without applying it again.

Money & settlement rules

RuleRequirement
UnitsInteger minor units, two decimal places for every supported currency: 100 = 1.00, including currencies normally displayed without decimals. Reject malformed amounts rather than rounding.
Native currencyOriginals settle in the session currency. Aggregated games use native currency only when enabled on the account and supported for that game. Other sessions may settle in USD. Always use the currency in each wallet request.
Minimum stakeOriginals minimum is 0.10 of the session currency. Other games have their own limits.
event_idGroups round activity; it is not a unique payout key or an instruction to reject later wins.
TransactionIdThe settlement idempotency key. Persist it together with the balance change.
TimeoutAn uncertain outcome: the wallet may have committed even though its reply was lost. Reconcile and deduplicate; reverse only on an explicit rollback.
RetentionKeep durable transaction and reversal records after the player session ends. Support late wins and sportsbook settlement.

Billing & limits

Billing can use client fees or a legacy GGR allowance. Check which basis your account uses; a fee balance and a GGR limit are not interchangeable.

For fee billing, available allowance is the posted USD balance plus credit, less pending fees. Rates follow your agreement and studio overrides. Pending fees consume allowance before monthly settlement. When blocking is enabled, exhaustion blocks new launches and bets; existing bets can still settle.

GET/gw/billing/status

Send x-api-key, no body and no query string. Read server-to-server and respect refreshAfterSeconds.

FieldMeaning
basisFEES or GGR; use the matching label.
usagePercentDisplay value only. null means no confirmed figure, not zero usage.
reached / blockedUse these exact flags rather than a rounded percentage to determine whether the billing restriction is active.
stateAVAILABLE, EXHAUSTED, UNAVAILABLE, PENDING, DISABLED or UNLIMITED.
usedCents / allowanceCents / availableCentsUSD cents, possibly negative; null when not applicable.
lastCheckedAtUTC timestamp of the confirmed figures.

Payments and credit changes are handled by your manager. Confirm refreshed status before assuming access has resumed. The endpoint remains readable while the account is suspended.

Errors

A launch failure uses an HTTP status and a JSON error response. Preserve the response code and request correlation ID when contacting support; redact API keys and tokens.

HTTPTypical cause
400Invalid or missing fields, unsupported currency or malformed country.
401Missing or invalid API key.
403Account, billing, game entitlement or location restriction.
409A prerequisite or request state conflict, including missing rollback support.
5xx / timeoutTemporary or uncertain failure. Inspect the response and reconcile any money operation before attempting recovery.

Wallet success means the movement committed durably. Return the current balance on an identical committed retry. Non-200 responses, an error envelope or timeouts do not by themselves prove whether money moved. Never return success merely to stop retries.

Performance & timeouts

Wallet latency directly affects gameplay. Aim for responses under 200 ms and keep the wallet and its database close together.

The normal gateway wallet timeout is up to five seconds, but individual integrations can have a shorter remaining budget. Do not treat five seconds as guaranteed processing time.

Keep unrelated reporting, risk scans and third-party calls off the settlement path. Use bounded connection pools and database transactions. Concurrent duplicate callbacks and redelivery after a lost response must remain safe.

Monitor latency, timeouts, rejected money movements and unresolved transactions separately from normal insufficient-funds responses. Alert on changes by account and action rather than relying only on a rolling failure percentage.

Security

Use HTTPS and keep API keys and webhook signing secrets on the server. Arrange egress-IP allowlisting with IOP where required; an unguessable webhook URL is not authentication.

Optional HMAC webhook signing

When signing is configured for your account, IOP sends X-IOP-Timestamp (Unix seconds) and X-IOP-Signature. The signature is:

v1=hex(HMAC-SHA256(webhook_secret, timestamp + "." + raw_request_body))

Verify the exact raw bytes before JSON parsing, use a constant-time digest comparison and enforce an agreed timestamp tolerance. Keep your server clock synchronized. The per-account webhook secret is separate from apiKey. Coordinate activation before requiring signed callbacks, then reject missing or invalid signatures rather than downgrading to unsigned handling.

Signature validation authenticates the sender; it does not replace durable TransactionId deduplication. Logs and support exports must redact credentials and player session tokens.

Verification tests

ScenarioExpected result
Winning and losing roundsWallet and IOP ledger totals agree exactly.
Concurrent identical TransactionIdOne movement, both requests safely resolved.
Commit, then drop the HTTP responseRedelivery returns success without another balance change.
Two different wins in one event_idBoth legitimate payouts credited once.
Zero result followed by a late winThe late win is accepted once.
Win with no paid betEligible promotional or free-round payment is credited.
Insufficient fundsRejected movement changes no balance.
Rollback and duplicate rollbackOriginal movement reversed exactly once.
Rollback before delayed originalNo unearned refund and no later debit of a cancelled movement.
EUR/native and USD fallbackAmounts and returned balance match each request currency.
Invalid signature / stale timestampRejected before any balance change when signing is enabled.
Free spinsEligibility, issuance, duplicate claim, expiry, payout and cancellation reconciled with the bonus wallet.
Long-running sportsbook eventLate settlement works after the browser session ends.

Go-live checklist

  • Production credentials, gateway URL and HTTPS wallet registered.
  • Content access, currencies and billing agreed for this account.
  • Wallet signing and IP rules tested against the configured mode.
  • Durable TransactionId uniqueness and atomic balance updates tested under concurrency and restarts.
  • Multiple wins, late wins, zero results, rollbacks and uncertain responses reconciled.
  • Rollback support enabled; optional free spins tested before issuing real campaigns.
  • Catalogue images, desktop/mobile launch and player IP/country handling verified.
  • Monitoring and a reconciliation procedure in place; no credentials in browser code or logs.
  • Test rounds matched against the IOP transaction report before public traffic.

Glossary

TermMeaning
Seamless walletThe operator keeps player funds and processes game movements through its wallet webhook.
GGRGross gaming revenue: bets less wins. This is distinct from the client fees calculated under your agreement.
event_idThe round correlation identifier; several movements may belong to it.
TransactionIdThe idempotency identifier for a settlement request.
Native currencySettlement in the supported requested currency rather than a USD fallback.
Wallet contract v2Wallet balance and settlement handling plus rollback support.

FAQ

Do all games settle in USD?

No. Read currency from every wallet request. Native settlement depends on the account and game; do not infer it from what the player sees.

Does a timeout mean the bet was refunded?

No. A wallet may commit before the response is lost. Use durable transaction records and reconcile; only an explicit rollback requests reversal.

Can more than one win arrive for a round?

Yes. Deduplicate by TransactionId, not event_id, and retain the round for late payouts.

Can I operate several brands?

Each brand has its own account credentials, wallet configuration, content access and billing settings. Arrange onboarding with your IOP manager.

Can I reuse a game image URL?

Use catalogue artwork URLs as returned, including version parameters. Refresh the feed when artwork changes.

Why can a listed game fail to launch?

Check current entitlements, billing, currency, player location and the actual error response. A cached catalogue is not a guarantee of current launch availability.

Changelog

DateDocumentation update
2026-11-12Clarified native currency, durable idempotency, late and multiple wins, timeout reconciliation, optional HMAC signing, fee billing, catalogue artwork and free-spin activation. Updated the downloadable integration reference.

Download integration reference · Credentials