API Response Format
The new Client API methods use a common JSON envelope.
Key rule:
HTTP
200confirms that the HTTP request was processed, but does not always mean that the business operation succeeded. Always check thecodefield.
Successful Response
{
"code": 1,
"body": {},
"error_code": null,
"error_message": null,
"date": 1784970000000,
"time_ms": 12,
"path": "/api/partner/coupons/get"
}
Business Error
{
"code": 0,
"body": null,
"error_code": 471,
"error_message": "Coupon not found",
"date": 1784970000000,
"time_ms": 5,
"path": "/api/partner/coupons/get"
}
A business error usually also returns HTTP 200.
Envelope Fields
| Field | Type | Description |
|---|---|---|
code | integer | Business operation result: 1 — success, 0 — error. |
body | any/null | Operation result or additional details. Its structure depends on the endpoint. |
error_code | integer/null | Machine-readable business error code. Usually null on success. |
error_message | string/null | Text error description. Usually null on success. |
date | integer | Response generation time as Unix milliseconds. |
time_ms | integer | Server-side request processing time in milliseconds. |
path | string | Path of the method that processed the request. |
code and error_code
These fields serve different purposes:
code → whether the business operation succeeded
error_code → why the operation failed
Example:
{
"code": 0,
"error_code": 503,
"error_message": "Bet outcome is blocked"
}
Here:
- the HTTP API is available;
- the request was processed;
- the coupon was not created;
- the reason is a blocked outcome.
Use error_code in program logic. error_message is intended for diagnostics and may be refined, so do not compare it as a stable error identifier.
The body Shape Depends on the Method
body does not have one type across the whole API.
| Method | body type | Data location |
|---|---|---|
GET /api/partner/health | string | Directly in body. |
POST /api/partner/login | object | Token in body.token. |
POST /api/partner/coupons/place | object | Coupons in body.coupons[]. |
GET /api/partner/coupons/get | object | One coupon directly in body. |
POST /api/partner/coupons/results | object | body.query_type and body.coupons[]. |
GET /api/partner/coupons/calculated | array | Coupons directly in body[]. |
GET /api/partner/coupons/active | array | Coupons directly in body[]. |
GET /api/partner/balance | object | Balance in body.balance. |
Do not use one universal path such as body.coupons[0] for every endpoint.
Coupon Creation
{
"code": 1,
"body": {
"coupons": [
{
"coupon_code": "000000000272"
}
]
}
}
Retrieving One Coupon
{
"code": 1,
"body": {
"coupon_code": "000000000272"
}
}
Active or Settled Coupons
{
"code": 1,
"body": [
{
"coupon_code": "000000000272"
}
]
}
Empty Successful Result
An empty array is not an error:
{
"code": 1,
"body": [],
"error_code": null,
"error_message": null
}
This response is possible, for example, when:
- there are no active coupons;
- there are no settled coupons in the selected window;
- none of the supplied codes were found in the available data.
For /coupons/results, the empty array is inside an object:
{
"code": 1,
"body": {
"query_type": "ids",
"coupons": []
}
}
body in a Business Error
For an error, body may be:
null;- an object with additional details;
- an array in the compatible legacy contract.
For example, when odds change, the new API returns the reasons in body.changes:
{
"code": 0,
"body": {
"changes": [
{
"game_id": 737779544,
"bet_coefficient": 2.19,
"actual_coefficient": 2.09,
"change_type": 2,
"status": "rejected"
}
]
},
"error_code": 501,
"error_message": "Coefficient is change",
"date": 1784970000000,
"time_ms": 20,
"path": "/api/partner/coupons/place"
}
Therefore, with code = 0, first read error_code, then process the body structure documented for that error.
HTTP Status and Business Result
| HTTP result | Meaning | Client action |
|---|---|---|
2xx, code = 1 | Operation completed. | Process the data from body. |
2xx, code = 0 | Business error. | Read error_code, error_message, and additional data. |
400 | Invalid JSON or parameter format. | Correct the request. |
401 | JWT is missing, invalid, expired, or revoked. | Log in again and use a new JWT. |
403 | The token lacks the required role or access is denied. | Check the token type and account state. |
5xx | Server or temporary error. | Record the error and use a safe retry strategy. |
Checking only the HTTP status gives an incorrect result for a business error:
HTTP 200 + code 0 ≠ success
Recommended Client Algorithm
1. Send the HTTP request.
2. Check the transport result.
3. With HTTP 401, obtain a new JWT.
4. With HTTP 403, check access.
5. With HTTP 5xx, use the temporary-error strategy.
6. For a JSON response, check code.
7. With code = 0, process error_code.
8. With code = 1, parse body according to the specific endpoint contract.
Pseudocode:
response = send_request()
if response.status == 401:
refresh_login()
stop
if response.status == 403:
report_access_error()
stop
if response.status >= 500:
handle_server_error()
stop
payload = parse_json(response.body)
if payload.code != 1:
handle_business_error(payload.error_code, payload.body)
stop
handle_success(payload.body)
Retrying Requests
The retry strategy depends on the operation.
Read methods can be safely retried after a temporary network or server error:
/coupons/get;/coupons/results;/coupons/calculated;/coupons/active;/balance.
Do not automatically retry POST /api/partner/coupons/place after an indeterminate network or server error until you have ruled out the possibility that the first request was processed. Otherwise, one user selection may create multiple coupons.
Coupon creation business errors 501–504 are outcome-validation results, not transport errors. Do not treat them as a normal automatic retry of the unchanged request.
Diagnostic Fields
date
Top-level date is the response generation time:
{
"date": 1784970000000
}
It is a Unix timestamp in milliseconds.
Do not confuse it with:
body.date— coupon creation time;event_date— event start time;calculate_date— settlement time.
time_ms
{
"time_ms": 12
}
This is the server-side request processing time in milliseconds. The field is useful for monitoring, but does not include the partner’s total network latency.
path
{
"path": "/api/partner/coupons/get"
}
This helps identify which route formed the response. Do not use path as a business identifier for a coupon or operation.
Dates and null
API dates use Unix milliseconds:
{
"date": 1784970000000,
"calculate_date": null
}
Before settlement, calculate_date is always null. The value 0 is not used for an unsettled coupon or bet.
Do not replace null with the number 0: they have different meanings.
Decimal Numbers
Amounts, odds, and payouts are JSON numbers without a fixed number of decimal places:
{
"amount": 10,
"coef": 1.5,
"real_win": 15
}
The integration must not depend on the textual number of decimal places:
10 = 10.0 = 10.00
The partner defines its own display and rounding rules. A decimal data type is recommended for storing money.
Optional and Absent Fields
Depending on the endpoint and result, individual optional envelope fields may be null or absent.
The client must:
- check whether an optional field is present;
- handle
nullcorrectly; - not replace an absent field with an arbitrary value;
- not treat an empty array as an error;
- not depend on JSON field order.
Legacy API Format
Legacy routes use the previous five-field envelope:
{
"code": 1,
"body": {},
"error_code": null,
"error_message": null,
"date": 1784970000000
}
It does not contain:
time_ms;path.
For a protected legacy route, an invalid JWT may be returned as a business error with HTTP 200:
{
"code": 0,
"body": false,
"error_code": 1003,
"error_message": "Wrong token",
"date": 1784970000000
}
Do not apply a legacy-structure handler to the new API without accounting for the additional fields and new HTTP 401/403 behavior.
More information:
Callback Uses a Different Contract
An incoming callback is not wrapped in code, body, error_code, or other Client API fields.
The callback payload begins with:
{
"event": "coupons.settled",
"batchId": "...",
"couponCount": 1,
"coupons": []
}
The partner response to a callback also has a separate contract:
{
"success": true,
"processed": 1
}
Do not use the common Client API envelope to process callbacks.
See Result Callbacks for details.
Checklist
- The HTTP status is checked first.
- Then
codeis checked. - With
code = 0,error_codeis read. error_messageis not used as a programmatic identifier.- The
bodyshape is determined by the endpoint. - An empty array with
code = 1is treated as success. dateis read as Unix milliseconds.time_msis used only for diagnostics.- Before settlement,
calculate_dateisnull, not0. - Decimal values do not depend on the number of displayed digits.
- Coupon creation is not retried blindly.
- Callbacks are processed according to their separate contract.
Next section: Error Codes.