Provider Operator API (1.0.0)

Download OpenAPI specification:Download

SkyGaming Integration Team: partners@skygaming.io

B2B integration contract for operators and aggregators

The single REST + webhook contract for integrating with the Provider game catalog.

There are two surfaces:

  1. Provider-served REST endpoints under /v1/* (operator → provider).
  2. Operator-served wallet callbacks (provider → operator) — defined in #/components/schemas with method names: getBalance, bet, win, rollback.

All money is in integer minor units (e.g. cents). All currencies are ISO-4217. All timestamps are RFC 3339 UTC. All requests/responses are JSON.

Authentication

  • Provider-served REST: Authorization: Bearer <operator JWT> issued at onboarding.
  • Operator-served callbacks: every request carries:
    • X-Provider-Signature: <hex(HMAC_SHA256(rawBody, sharedSecret))> — constant-time verify only
    • X-Provider-Operator-ID — operator identifier
    • X-Provider-Request-ID — ULID; identifies the transport, used for replay defense
    • X-Provider-Request-Timestamp — RFC 3339 UTC OR Unix epoch seconds; wall-clock skew limit ± 60 s
    • X-Provider-Algorithmhmac-sha256 (currently the only value) Operators MUST reject requests with skew > 60 s, missing/invalid signature, or with a previously-seen X-Provider-Request-ID within the 5-minute replay window. If the same request id arrives with a different body, this is a probable attack — return HTTP 409 + errorCode: 400 and alert.

Idempotency

Wallet callbacks are idempotent on (operatorId, transactionId). A duplicate request MUST return errorCode: 0 with the post-first-call balance, never re-process. Different body for the same transactionId MUST return errorCode: 400.

Money & currency

All money fields are integer minor units. Decimal places per ISO-4217 (e.g. USD=2, JPY=0, KWD=3). Cross-currency mixing within a single round is forbidden.

Retry policy (provider → operator)

call retries total budget
bet 3 attempts at 250 / 750 / 2000 ms ~3 s
win every 30 s 48 h
rollback every 30 s 48 h
getBalance none — caller decides n/a

Bets MUST NOT be retried on errorCode = 200 (insufficient funds) or errorCode = 202 (self-excluded). Wins / rollbacks MUST always eventually settle; failed rounds are reported via the round-close monitor at /v1/rounds/{id}.

Error codes

code meaning
0 OK
100 INVALID_SIGNATURE
101 INVALID_REQUEST
102 PLAYER_NOT_FOUND
103 INVALID_CURRENCY
200 INSUFFICIENT_FUNDS
201 PLAYER_LIMIT_EXCEEDED
202 PLAYER_SELF_EXCLUDED / risk locked
300 GAME_DISABLED
301 GAME_MAINTENANCE
400 DUPLICATE_TRANSACTION_DIFFERENT_PAYLOAD
401 TRANSACTION_NOT_FOUND
500 INTERNAL_ERROR

catalog

List available games

Returns the games this operator is entitled to, optionally narrowed by jurisdiction/currency. Entitlements are managed per-operator: an operator with a non-empty game allow-list sees ONLY those games; an operator with no allow-list sees the entire catalog.

Authorizations:
operatorBearer
query Parameters
jurisdiction
string
Example: jurisdiction=CW
currency
string
Example: currency=USD

Responses

Response samples

Content type
application/json
{
  • "games": [
    ]
}

/v1/games/{gameId}

Authorizations:
operatorBearer
path Parameters
gameId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "skyrush",
  • "name": "SkyRush",
  • "engine": "crash",
  • "rtp": 0.97,
  • "volatility": "low",
  • "minBet": {
    },
  • "maxBet": {
    },
  • "maxWin": {
    },
  • "maxMultiplier": 10000,
  • "jurisdictions": [
    ],
  • "currencies": [
    ],
  • "languages": [
    ],
  • "thumbnailUrl": "http://example.com"
}

sessions

Create a one-time launch session

Authorizations:
operatorBearer
Request Body schema: application/json
required
userId
required
string

External player ID at the operator

gameId
required
string
currency
required
string = 3 characters
language
required
string
mode
string
Default: "real"
Enum: "real" "demo"
kycLevel
integer [ 0 .. 3 ]
Default: 1
ipAddress
string
deviceFingerprint
string
returnUrl
string <uri>
depositUrl
string <uri>

Responses

Request samples

Content type
application/json
{
  • "userId": "string",
  • "gameId": "string",
  • "currency": "str",
  • "language": "en",
  • "mode": "real",
  • "kycLevel": 1,
  • "ipAddress": "string",
  • "deviceFingerprint": "string",
  • "returnUrl": "http://example.com",
  • "depositUrl": "http://example.com"
}

Response samples

Content type
application/json
{
  • "sessionId": "string",
  • "launchUrl": "http://example.com",
  • "token": "string",
  • "expiresAt": "2019-08-24T14:15:22Z"
}

rounds

/v1/rounds/{roundId}

Authorizations:
operatorBearer
path Parameters
roundId
required
string

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "gameId": "string",
  • "userId": "string",
  • "startedAt": "2019-08-24T14:15:22Z",
  • "endedAt": "2019-08-24T14:15:22Z",
  • "status": "open",
  • "bet": {
    },
  • "win": {
    },
  • "outcome": { },
  • "provablyFair": {
    }
}

List rounds (paginated, by player or game).

Authorizations:
operatorBearer
query Parameters
userId
string
gameId
string
status
string
Enum: "open" "settled" "expired" "cancelled"
from
string <date-time>
to
string <date-time>
limit
integer <= 1000
Default: 100

Responses

Response samples

Content type
application/json
{
  • "rounds": [
    ]
}

List transactions (bet / win / rollback) for the operator.

Authorizations:
operatorBearer
query Parameters
userId
string
gameId
string
roundId
string
method
string
Enum: "bet" "win" "rollback"
status
string
Enum: "pending" "committed" "rolled_back" "failed"
from
string <date-time>
to
string <date-time>
limit
integer <= 1000
Default: 100

Responses

Response samples

Content type
application/json
{
  • "transactions": [
    ]
}

reports

/v1/reports/ggr

Authorizations:
operatorBearer
query Parameters
from
required
string <date-time>
to
required
string <date-time>
gameId
string
currency
string

Responses

Response samples

Content type
application/json
{
  • "from": "2019-08-24T14:15:22Z",
  • "to": "2019-08-24T14:15:22Z",
  • "rows": [
    ]
}

Pre-aggregated per-day GGR/NGR per (operator, game, currency).

Authorizations:
operatorBearer
query Parameters
from
required
string <date>
to
required
string <date>
gameId
string
currency
string

Responses

Response samples

Content type
application/json
{
  • "rows": [
    ]
}

players

/v1/players/{userId}/limits

Authorizations:
operatorBearer
path Parameters
userId
required
string
Request Body schema: application/json
required
object (Money)
object (Money)
object (Money)
sessionTimeMinutes
integer >= 1
realityCheckMinutes
integer >= 1

Responses

Request samples

Content type
application/json
{
  • "dailyLossLimit": {
    },
  • "weeklyLossLimit": {
    },
  • "monthlyLossLimit": {
    },
  • "sessionTimeMinutes": 1,
  • "realityCheckMinutes": 1
}

/v1/players/{userId}/exclude

Authorizations:
operatorBearer
path Parameters
userId
required
string
Request Body schema: application/json
required
duration
required
string
Enum: "24h" "7d" "30d" "6m" "permanent"
reason
string

Responses

Request samples

Content type
application/json
{
  • "duration": "24h",
  • "reason": "string"
}

wallet-callbacks

webhooks

Outbound product webhooks (provider → operator). Subscribe per-event in the back-office; each subscription gets its own HMAC secret. At-least-once delivery with exponential backoff; dedupe on the envelope id.

A game round reached its final settled state. Webhook

Fired once per round when it transitions open → settled. Headers match the wallet-callback signing scheme (X-Provider-Signature, X-Provider-Operator-ID, X-Provider-Request-Timestamp, X-Provider-Algorithm: hmac-sha256) plus X-Provider-Event: round.settled and X-Provider-Delivery-ID. The signature covers the raw JSON body.

Authorizations:
operatorBearer
Request Body schema: application/json
id
required
string

Stable per-delivery id (whd_<n>). Receivers MUST dedupe on this.

event
required
string

Event name (matches the subscription).

operatorId
required
string
occurredAt
required
string <date-time>

When the underlying event was recorded (not the delivery attempt time).

required
object

Event-specific payload (see the per-event schemas).

Responses

Request samples

Content type
application/json
{
  • "id": "whd_10472",
  • "event": "round.settled",
  • "operatorId": "op_demo",
  • "occurredAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}

A wallet transaction (bet/win/rollback) was committed to the ledger. Webhook

Authorizations:
operatorBearer
Request Body schema: application/json
id
required
string

Stable per-delivery id (whd_<n>). Receivers MUST dedupe on this.

event
required
string

Event name (matches the subscription).

operatorId
required
string
occurredAt
required
string <date-time>

When the underlying event was recorded (not the delivery attempt time).

required
object

Event-specific payload (see the per-event schemas).

Responses

Request samples

Content type
application/json
{
  • "id": "whd_10472",
  • "event": "round.settled",
  • "operatorId": "op_demo",
  • "occurredAt": "2019-08-24T14:15:22Z",
  • "data": {
    }
}