Bonus play API

From BetgamesTV
Jump to navigation Jump to search

Overview

The FreePlay API provides endpoints for managing free play tickets for both Classic games and Slot games. The API supports assignment, listing, revocation, and game information retrieval operations.

Authentication & Security

Headers

Required for all endpoints:

Header Type Description
X-OPERATOR string Partner code/identifier
X-TIMESTAMP string ISO 8601 timestamp
X-SIGNATURE string HMAC-SHA256 signature, base64 encoded
Content-Type string application/json for POST requests

Signature Generation

Signature payload format: {partnerId}|{secretKey}|{timestamp}|{param1}|{param2}|...
Algorithm: HMAC-SHA256
Encoding: Base64

Example signature generation:

$payload = implode('|', [$partnerId, $secretKey, $timestamp, $playerId, $gameId, $serial]);
$signature = base64_encode(hash_hmac('sha256', $payload, $secretKey, true));

Assign Free Play

Endpoint

POST /s/bonus/freeplay/assign

Description

Assigns free play tickets to a player.

Request Body

{
  "playerId": "player123",
  "gameId": "1",
  "serial": "UNIQUE-SERIAL-001",
  "currency": "EUR",
  "stake": "1.00",
  "count": 1,
  "expires": "2026-12-31T23:59:59+00:00",
  "minOddValue": 1.00,
  "maxOddValue": 100.00
}

Request Parameters

Field Type Required Description
playerId string Yes External player identifier
gameId string Yes Game ID
serial string Yes Unique serial number for this assignment
currency string Yes ISO 4217 currency code
stake decimal Yes Stake amount per ticket/bet
count integer Yes Number of tickets/bets to assign. Supported only by slot games. For Classic games, always 1.
expires string Optional Expiry date of the free play package. Can be provided as ISO 8601 UTC datetime string or Unix timestamp in seconds. If not set, the expiry date defaults to 180 days after the request is submitted.
minOddValue decimal Optional Minimum odd value required to place a free bet, applicable for Classic games. If not set, the default value is 1.
maxOddValue decimal Optional Maximum odd value required to place a free bet, applicable for Classic games. If not set, there are no limitations.

Signature Parameters

{partnerId}|{secretKey}|{timestamp}|{playerId}|{gameId}|{serial}|{currency}|{stake}|{count}

Success Response (200 OK)

{
  "serial": "UNIQUE-SERIAL-001",
  "internalId": "generated-internal-id",
  "count": 10,
  "used": 0,
  "expires": "2026-12-31T23:59:59+00:00"
}

Error Response (400 Bad Request)

{
  "serial": "UNIQUE-SERIAL-001",
  "errorCode": {
    "id": 901,
    "msg": "Request validation failed."
  }
}

List Free Plays

Endpoint

GET /s/bonus/freeplay/list?playerId={playerId}&gameId={gameId}&currency={currency}

Description

Retrieves all active, non-expired free plays for a specific player, game, and currency.

Query Parameters

Parameter Type Required Description
playerId string Yes External player identifier
gameId string Yes Game ID
currency string Yes ISO 4217 currency code

Signature Parameters

{partnerId}|{secretKey}|{timestamp}|{playerId}|{gameId}|{currency}

Success Response (200 OK)

{
  "tickets": [
    {
      "serial": "UNIQUE-SERIAL-001",
      "currency": "EUR",
      "stake": 1.0,
      "availableTickets": 5
    },
    {
      "serial": "UNIQUE-SERIAL-002",
      "currency": "EUR",
      "stake": 2.5,
      "availableTickets": 10
    }
  ]
}

Error Response (400 Bad Request)

{
  "errorCode": {
    "id": 901,
    "msg": "Request validation failed."
  }
}

Revoke Free Play

Endpoint

POST /s/bonus/freeplay/revoke

Description

Revokes, or suspends, an active free play by serial number.

Request Body

{
  "playerId": "player123",
  "gameId": "1",
  "serial": "UNIQUE-SERIAL-001"
}

Request Parameters

Field Type Required Description
playerId string Yes External player identifier
gameId string Yes Game ID
serial string Yes Serial number to revoke

Signature Parameters

{partnerId}|{secretKey}|{timestamp}|{playerId}|{gameId}|{serial}

Success Response (200 OK)

{
  "serialRevoked": "UNIQUE-SERIAL-001"
}

Error Response (400 Bad Request)

{
  "serial": "UNIQUE-SERIAL-001",
  "errorCode": {
    "id": 915,
    "msg": "Free play not found."
  }
}

Get Available Games

Endpoint

GET /s/bonus/freeplay/games

Description

Retrieves all games available for free play assignment for the partner, including betting limits and available stakes.

Query Parameters

None required. The partner is identified via headers.

Signature Parameters

{partnerId}|{secretKey}|{timestamp}

Success Response (200 OK)

{
  "games": [
    {
      "id": 1,
      "name": "Classic game",
      "limits": {
        "minBet": 0.10,
        "maxBet": 100.00,
        "maxWinPerBet": 5000.00
      },
      "stakes": []
    },
    {
      "id": 50,
      "name": "Slot game",
      "limits": {
        "minBet": 1.00,
        "maxBet": 500.00,
        "maxWinPerBet": 10000.00
      },
      "stakes": [1.0, 2.0, 5.0, 10.0, 25.0, 50.0]
    }
  ]
}

Response Fields

Field Type Description
games array List of available games
games[].id integer Game ID
games[].name string Game name
games[].limits object Betting limits for the partner
games[].limits.minBet number Minimum bet amount
games[].limits.maxBet number Maximum bet amount
games[].limits.maxWinPerBet number Maximum win per bet
games[].stakes array Predefined stakes, slot games only

Error Response (400 Bad Request)

{
  "errorCode": {
    "id": 902,
    "msg": "Signature mismatch."
  }
}

Complete Error Codes Reference

Code Message Applicable Endpoints
900 No valid post data provided assign, revoke
901 Request validation failed all
902 Signature mismatch all
903 Wrong headers all
910 Partner not found all
911 Game not found assign, list, revoke
912 Currency invalid assign, list
914 External game not found assign (Slot)
915 Free play not found revoke (Slot)
916 Free play not found revoke (Classic)
930 Invalid expiration date format assign
932 No handler found assign, list, revoke
941 Communication error assign (Slot)

Request/Response Examples

Example 1: Assign Free Play (Classic Game)

Request:

POST /s/bonus/freeplay/assign
X-OPERATOR: PARTNER123
X-TIMESTAMP: 2026-03-12T10:30:00Z
X-SIGNATURE: aGFzaGVkX3NpZ25hdHVyZV9leGFtcGxl
Content-Type: application/json

{
  "playerId": "player_ext_456",
  "gameId": "1",
  "serial": "FB-2026-001",
  "currency": "EUR",
  "stake": "5.00",
  "count": 1,
  "expires": "2026-12-31T23:59:59+00:00",
  "minOddValue": 1.00,
  "maxOddValue": 100.00
}

Success Response:

{
  "serial": "FB-2026-001",
  "internalId": "FB-2026-001",
  "count": 1,
  "used": 0,
  "expires": "2026-12-31T23:59:59+00:00"
}

Example 2: Assign Free Play (Slot Game)

Request:

POST /s/bonus/freeplay/assign
X-OPERATOR: PARTNER123
X-TIMESTAMP: 2026-03-12T10:30:00Z
X-SIGNATURE: YW5vdGhlcl9oYXNoZWRfc2lnbmF0dXJl
Content-Type: application/json

{
  "playerId": "player_ext_789",
  "gameId": "50",
  "serial": "FP-SLOT-2026-001",
  "currency": "USD",
  "stake": "10.00",
  "count": 25,
  "expires": "2026-12-31T23:59:59+00:00"
}

Success Response:

{
  "serial": "FP-SLOT-2026-001",
  "internalId": "SLOT-INTERNAL-12345",
  "count": 25,
  "used": 0,
  "expires": "2026-12-31T23:59:59+00:00"
}

Example 3: List Free Plays

Request:

GET /s/bonus/freeplay/list?playerId=player_ext_456&gameId=1&currency=EUR
X-OPERATOR: PARTNER123
X-TIMESTAMP: 2026-03-12T11:00:00Z
X-SIGNATURE: bGlzdF9zaWduYXR1cmVfZXhhbXBsZQ==

Success Response:

{
  "tickets": [
    {
      "serial": "FB-2026-001",
      "currency": "EUR",
      "stake": 5.0,
      "availableTickets": 1
    },
    {
      "serial": "FB-2026-002",
      "currency": "EUR",
      "stake": 10.0,
      "availableTickets": 1
    }
  ]
}

Example 4: Revoke Free Play

Request:

POST /s/bonus/freeplay/revoke
X-OPERATOR: PARTNER123
X-TIMESTAMP: 2026-03-12T12:00:00Z
X-SIGNATURE: cmV2b2tlX3NpZ25hdHVyZV9leGFtcGxl
Content-Type: application/json

{
  "playerId": "player_ext_456",
  "gameId": "1",
  "serial": "FB-2026-001"
}

Success Response:

{
  "serialRevoked": "FB-2026-001"
}

Example 5: Get Available Games

Request:

GET /s/bonus/freeplay/games
X-OPERATOR: PARTNER123
X-TIMESTAMP: 2026-03-12T13:00:00Z
X-SIGNATURE: Z2FtZXNfc2lnbmF0dXJlX2V4YW1wbGU=

Success Response:

{
  "games": [
    {
      "id": 1,
      "name": "Bet on Poker",
      "limits": {
        "minBet": 0.5,
        "maxBet": 200.0,
        "maxWinPerBet": 10000.0
      },
      "stakes": []
    },
    {
      "id": 50,
      "name": "Baccarat",
      "limits": {
        "minBet": 1.0,
        "maxBet": 500.0,
        "maxWinPerBet": 25000.0
      },
      "stakes": [1.0, 2.0, 5.0, 10.0, 25.0, 50.0, 100.0]
    }
  ]
}

Versioning

Public integration guide for partner developers. Your assigned version is configured by BetGames. Contact your integration manager to enable the API or request a version upgrade.

What “version” means

The Bonus Play API has three public contract versions: 1.0, 2.0, and 2.1.

  • URLs do not change between versions.
  • You do not send a version header or query parameter.
  • BetGames assigns the active version to your operator account.
  • The server applies the validation rules for that version automatically.
  • If the API is not enabled for your account, requests return error 918Bonus Play API is not enabled for this partner.

Quick comparison

Feature 1.0 2.0 2.1
Status Legacy Current recommended Strict / newest
Game types supported Slot games only Classic + slot games Classic + slot games
Extra request fields Allowed, ignored Allowed, ignored Rejected
Field type checking Lenient Lenient Strict
minOddValue / maxOddValue on assign Not supported Optional Optional
gameCategory in GET /s/bonus/freeplay/games response Not included Included Included

Recommendation for new integrations: implement against 2.1. Use 2.0 only if you need backward-compatible lenient validation during migration.

How the version affects your integration

All versions share the same base URL, endpoints, authentication headers (X-OPERATOR, X-TIMESTAMP, X-SIGNATURE), signature algorithm, and response formats, except where noted below.

Differences are in:

  • which games you can use;
  • which fields are accepted;
  • how strictly requests are validated.

Version details

Version 1.0 — slots only (legacy)

Use this version if you only assign free play to slot games.

  • Assign / list / revoke: gameId must be a slot game ID.
  • Assign: minOddValue and maxOddValue are not part of the contract.
  • Validation: lenient — unknown JSON fields are allowed; numeric fields may be sent as strings, for example "5".
  • GET /s/bonus/freeplay/games: returns game list without gameCategory.

Version 2.0 — classic + slot games

Use this version if you need free play on classic BetGames games and slot games.

What is new compared with 1.0:

  • Assign / list / revoke: gameId may be a classic or slot game ID.
  • Assign: optional minOddValue and maxOddValue. Both must be sent together, and minOddValue must be less than or equal to maxOddValue.
  • GET /s/bonus/freeplay/games: each game includes gameCategory: classic_games or slot_games.
  • Validation: still lenient — extra fields are allowed; types are not strictly enforced.

Version 2.1 — classic + slot games, strict validation

Same game coverage as 2.0, with stricter request validation. This is the best version for new integrations.

What is new compared with 2.0:

  • Unknown fields are rejected. Do not send extra properties in JSON bodies or unknown query parameters on list.
  • Strict field types are enforced.
  • GET /s/bonus/freeplay/games: same as 2.0, including gameCategory.

Version 2.1 field typing

Field Expected type Notes
playerId string
gameId string Must be an allowed game ID
serial string Assign / revoke
currency string Case-insensitive; see Authentication & currency
stake positive decimal Assign
count positive integer Assign
minOddValue, maxOddValue positive decimal Optional; both or neither

Per-endpoint summary

Endpoint Method Request payload 1.0 2.0 2.1
Assign POST /s/bonus/freeplay/assign JSON body Slots only Classic + slots; optional odds range Classic + slots; strict types
Revoke POST /s/bonus/freeplay/revoke JSON body Slots only Classic + slots Classic + slots; strict types
List GET /s/bonus/freeplay/list Query string only Slots only Classic + slots Classic + slots; strict types
Games GET /s/bonus/freeplay/games Headers + signature only No gameCategory Includes gameCategory Includes gameCategory

List endpoint note: parameters are passed as URL query parameters (playerId, gameId, currency), not in a request body.

Authentication & currency (all versions)

Endpoint Values included in signature
List playerId, gameId, currency
Assign playerId, gameId, serial, currency, stake, count
Revoke playerId, gameId, serial
Games Signature over headers only — no request fields

Currency:

  • You may send currency in any case, for example usd, USD, or Usd.
  • Build the signature with the exact value you send in the request, using the same casing in the URL/body and signature payload.
  • Responses and stored values use uppercase ISO codes, for example USD or EUR.

Upgrading between versions

From → To Action required on your side
1.02.0 Support classic game IDs; handle gameCategory in the games response; optionally use minOddValue / maxOddValue on assign.
2.02.1 Remove extra/unknown fields; ensure correct JSON types; ensure list uses only documented query parameters.
1.02.1 Combine both steps above.

You do not need to change URLs or authentication when BetGames upgrades your version. Test on staging after BetGames confirms the switch.

Which version am I on?

BetGames configures this per operator. To confirm:

  1. Ask your BetGames contact, or
  2. Infer from behavior on staging:
    • 918 → API not enabled
    • Assign to a classic game ID succeeds → 2.0 or 2.1
    • Assign to a classic game ID fails with game validation error → likely 1.0
    • Unknown field in assign body fails → 2.1
    • Unknown field in assign body is ignored → 2.0 or 1.0

FAQ

Do I put the version in the URL?

No. Endpoints are identical for all versions.

Will BetGames change my version without notice?

Version changes are coordinated with your integration team. You will be told when to adjust your client.

Is 1.0 deprecated?

It remains supported for existing slot-only integrations. New partners should use 2.1.

Why does list behave differently from assign?

List is a GET request: parameters go in the query string, not the body. Assign and revoke use a JSON body.

What error do I get if my version does not support a game?

Validation fails, typically with 901, if gameId is not allowed for your version, for example a classic game on 1.0.