Casino Api Pro

Get started

Errors

The error envelope, status codes, the retryable flag, and how to handle failures well.

Every error, from any endpoint, has the same shape. Parse the code — the message is written for a human reading a log and may change without notice.

The envelope

json
{
  "error": {
    "code": "INSUFFICIENT_FUNDS",
    "message": "player balance is below the requested stake",
    "request_id": "fa1bc6b7-bd54-480e-92c1-6ffa700d6039",
    "retryable": false
  }
}
code
stringrequired
Stable machine-readable identifier. Branch on this.
message
stringrequired
Human-readable detail. Not stable; do not parse.
request_id
stringrequired
Quote this to support and we can find the exact request. Also returned as the X-Request-Id header on every response.
retryable
booleanrequired
Whether retrying the identical request with the same transaction_id can succeed.

iretryable is the field that matters

It removes the guesswork from your retry loop. If it is true, back off and send the same request again. If it is false, retrying will fail the same way forever — fix the request or surface it.

Status codes

400
Bad Request
Malformed body — not JSON, or a field of the wrong shape.
401
Unauthorized
Missing, expired or invalid token.
403
Forbidden
Authenticated, but not permitted — wrong audience, suspended account, or an IP outside the allowlist.
404
Not Found
No such resource, or it belongs to another operator. We do not distinguish the two.
409
Conflict
Idempotency conflict — same transaction_id, different body.
422
Unprocessable
Well-formed but invalid: a stake outside limits, an unsupported currency, an illegal move.
429
Rate limited
Too many requests. Honour Retry-After.
500
Server error
Our fault. Retryable. Quote the request id if it persists.
504
Wallet timeout
Your wallet did not answer in time. Retryable with the same id — see Idempotency.

Why 404 and not 403

Asking for another operator's session returns 404, not 403. Answering "forbidden" would confirm the resource exists, which leaks the shape of other tenants' data to anyone willing to enumerate ids. Absence and denial look identical from outside.

Handling errors well

js
const res = await fetch(url, options);
const body = await res.json();

if (!res.ok) {
  const { code, retryable, request_id } = body.error;

  // Log the request id with everything. It is the only thing that lets
  // support find your exact call in our logs.
  logger.warn({ code, request_id, status: res.status }, "casinoapipro error");

  if (retryable) return scheduleRetry();

  switch (code) {
    case "INSUFFICIENT_FUNDS": return tellPlayer("Not enough balance");
    case "BET_LIMIT_EXCEEDED": return tellPlayer("Stake above the table limit");
    case "IDEMPOTENCY_CONFLICT": return alertEngineering(request_id);
    default: return alertEngineering(request_id);
  }
}

A full list of codes lives in Error codes.