SportAPI Documentation
EN
C Product documentationCoupon API
v1
Service & pricing ↗ Get access ↗
Coupon API / Quick start

Quick Start

This guide walks you through checking API availability, authenticating, placing a single coupon, and retrieving its current state.

A callback is not required for the first test. You can retrieve the coupon result with a regular API request.

What you need

Before starting the integration, obtain the following from your manager:

  • API base URL;
  • username;
  • password.

To place a coupon, you also need a pointer to the selected outcome from the sports line. The examples use this test pointer:

line#737779544#1#1#0#1.85

Replace it with a current pointer from your Sport Line API integration.

Store the provided address without a trailing / in a variable:

BASE_URL="https://coupon-api.example.com"

This is only an example. Replace https://coupon-api.example.com with the address provided by your manager.

Step 1. Check API availability

The health-check method does not require authentication:

curl --request GET \
  --url "$BASE_URL/api/partner/health" \
  --header "Accept: application/json"

Successful response:

{
  "code": 1,
  "body": "ok",
  "error_code": null,
  "error_message": null,
  "date": 1784970000000,
  "time_ms": 1,
  "path": "/api/partner/health"
}

If the request fails, check the base URL, network access, and firewall settings.

Step 2. Obtain a JWT

Submit the username and password:

curl --request POST \
  --url "$BASE_URL/api/partner/login" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --data '{
    "username": "{username}",
    "password": "{password}"
  }'

Successful response:

{
  "code": 1,
  "body": {
    "token": "eyJhbGciOiJIUzI1NiJ9...",
    "username": "partner-demo"
  },
  "error_code": null,
  "error_message": null,
  "date": 1784970000000,
  "time_ms": 35,
  "path": "/api/partner/login"
}

Store the value of body.token. Include it in the following header with every subsequent request:

Authorization: Bearer <client_token>

An administrator JWT cannot be used with Client API methods.

See Authentication for details.

Step 3. Place a single

A single is a coupon containing one bet.

Replace:

  • <client_token> with the token obtained in the previous step;
  • the value in list_bets with a current pointer to the selected outcome;
  • amount and currency with the stake amount and currency;
  • lang with the required two-letter language code.

Request:

curl --request POST \
  --url "$BASE_URL/api/partner/coupons/place" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer <client_token>" \
  --header "Content-Type: application/json" \
  --data '{
    "list_bets": [
      "line#737779544#1#1#0#1.85"
    ],
    "amount": 10,
    "currency": "UAH",
    "lang": "en",
    "mode": "reject",
    "multi": false
  }'

In this request:

  • mode: "reject" rejects the coupon if the odds have changed;
  • mode: "accept" allows changed odds to be accepted; the available mode_type values and their behavior are described in Odds changes;
  • multi: false combines all entries in list_bets into one coupon;
  • multi: true creates a separate single for every entry in list_bets; the amount is applied to each coupon, so the total stake must be reflected in the bet slip;
  • one entry in list_bets creates a single.

This example uses the safe defaults: mode: "reject" and multi: false.

Example of a successful response:

{
  "code": 1,
  "body": {
    "coupons": [
      {
        "coupon_code": "000000000272",
        "amount": 10,
        "win": 18.5,
        "potential_win": 18.5,
        "real_win": null,
        "coef": 1.85,
        "original_coef": 1.85,
        "calculate_coef": null,
        "has_return": false,
        "date": 1784970000000,
        "status": 0,
        "asian": false,
        "calculate_date": null,
        "coupon_type": 1,
        "events_count": 1,
        "events_data": [
          {
            "id": 912,
            "game_id": 737779544,
            "main_game_id": 737779544,
            "is_sub_game": false,
            "parent_game_id": null,
            "raw_pointer": "line#737779544#1#1#0#1.85",
            "line_type": "line",
            "is_live": false,
            "bet_group_id": 1,
            "bet_group_name": "Match Result",
            "bet_id": 1,
            "bet_name": "First Team to Win",
            "sport_id": 1,
            "sport_name": "Football",
            "tournament_id": 10001,
            "tournament": "Test Tournament",
            "event_date": 1784977200000,
            "status": 0,
            "opp1": "Team 1",
            "opp2": "Team 2",
            "team1_id": 101,
            "team2_id": 102,
            "opp_icon1": 101,
            "opp_icon2": 102,
            "coef": 1.85,
            "calc_coef": null,
            "bet_score": "line#737779544#1#1#0#1.85",
            "calculate_date": null,
            "calculate_score": null,
            "settlement_reason_code": null,
            "settlement_reason": null,
            "rate": "0"
          }
        ]
      }
    ]
  },
  "error_code": null,
  "error_message": null,
  "date": 1784970000015,
  "time_ms": 45,
  "path": "/api/partner/coupons/place"
}

The operation is successful when code = 1.

By the time this response is returned, the API has already debited amount from the SportAPI client account balance. With multi = true, amount is debited for every coupon created. If the balance is insufficient for the total amount, the API returns 507, Insufficient balance, creates no coupons, and leaves the client balance unchanged.

The end user’s balance is held in the partner’s system and is handled separately.

Important. Until code = 1 is received, the contents of the bet slip are only the user’s preliminary selection and are not an accepted coupon. Do not store them as an accepted coupon in the partner’s system: during validation, the outcome may no longer exist in the sports line, may be blocked, or may have different odds. After confirmation, store the coupon data returned by the API in body.coupons.

The API returns created coupons in body.coupons. Even when only one coupon is created, coupons remains an array.

Each coupon contains:

  • general coupon data: code, amount, potential payout, odds, type, and status;
  • events_count — the number of bets;
  • events_data — an array with detailed information about every bet, including event and outcome identifiers, names, participants, odds, the pointer, and settlement fields.

The partner decides which coupon and bet data must be stored in the partner’s system. Storing the entire response is optional, but you should store every field required to display the coupon, reconcile data, and process subsequent settlement.

The coupon_code must always be stored. It is the primary linking key between the coupon in the SportAPI Coupon Settlement System and the corresponding record in the partner’s system. Store it as a string to preserve leading zeros.

If the partner tracks the result of each bet separately, store events_data[].id and any other required fields. The recommended key for a specific bet is the combination of coupon_code and events_data[].id.

See also:

Step 4. Check the current state

Submit the stored coupon_code:

curl --request GET \
  --url "$BASE_URL/api/partner/coupons/get?coupon_code=000000000272" \
  --header "Accept: application/json" \
  --header "Authorization: Bearer <client_token>"

While the coupon has not yet been settled, the response contains:

{
  "code": 1,
  "body": {
    "coupon_code": "000000000272",
    "real_win": null,
    "calculate_coef": null,
    "status": 0,
    "calculate_date": null
  },
  "error_code": null,
  "error_message": null,
  "date": 1784970000000,
  "time_ms": 5,
  "path": "/api/partner/coupons/get"
}

status = 0 means that settlement has not yet been completed.

After the coupon is settled, the response contains the final status, actual payout, and settlement data. Shortened example of a winning single:

{
  "code": 1,
  "body": {
    "coupon_code": "000000000272",
    "amount": 10,
    "potential_win": 18.5,
    "real_win": 18.5,
    "original_coef": 1.85,
    "calculate_coef": 1.85,
    "status": 2,
    "calculate_date": 1784973600000,
    "coupon_type": 1,
    "events_count": 1,
    "events_data": [
      {
        "status": 1,
        "coef": 1.85,
        "calc_coef": 1.85,
        "calculate_date": 1784973600000,
        "calculate_score": "2:1"
      }
    ]
  },
  "error_code": null,
  "error_message": null,
  "date": 1784973600100,
  "time_ms": 6,
  "path": "/api/partner/coupons/get"
}

In this example:

  • coupon status 2 means win;
  • bet status 1 means win;
  • real_win contains the actual payout;
  • calculate_coef contains the final settlement multiplier.

See also:

Always check code

HTTP 200 does not always mean that the operation succeeded. Business errors are also usually returned with HTTP 200, but contain:

{
  "code": 0,
  "error_code": 501,
  "error_message": "Coefficient is change"
}

Minimum response-handling logic:

HTTP 2xx and code = 1 → operation succeeded
HTTP 2xx and code = 0 → handle error_code and error_message
HTTP 401 → obtain a new JWT
HTTP 403 → check client access and token type
HTTP 5xx → temporary server error

See also:

Receiving results automatically

After placing the first coupon successfully, choose the appropriate method:

  1. Periodically request coupons through the Client API.
  2. Ask the manager to enable callbacks and receive signed updates automatically.
  3. Use callbacks as the primary method and API requests for fallback reconciliation.

Callbacks are optional. To enable them, the manager activates the feature and creates a secret phrase for HMAC signature verification.

See also:

Completion checklist

The basic integration is working when your system:

  • obtains a JWT;
  • places a coupon with code = 1;
  • stores coupon_code as a string;
  • retrieves the coupon state by its code;
  • distinguishes transport errors from business errors.

Next step: understand authentication and JWT handling.