Errors

Every error is JSON with the same shape and the right HTTP status. The code is stable — branch on it, not on the message.

json
{
  "error": {
    "code": "ledger/insufficient_balance",
    "message": "insufficient session balance for bet",
    "details": { "balance": "100", "amount": "150" }
  }
}

Auth

auth/missing_tokenNo bearer token supplied
auth/invalid_tokenKey/session invalid, or out of scope
auth/expired_tokenSession access token expired — refresh it
auth/invalid_signatureSIWS signature did not verify
auth/challenge_expiredSIWS challenge too old
auth/invalid_init_dataTelegram init data did not verify

Wallet

wallet/not_foundNo such wallet for this user/scope
wallet/export_blockedExport not allowed (policy or balance)
withdrawal/insufficient_balanceNot enough balance to withdraw
withdrawal/limit_exceededCrypto withdrawal disabled for this app

Ledger

ledger/session_not_foundUnknown or wrong-app session token
ledger/session_closedSession already settling/settled
ledger/insufficient_balanceBet exceeds the session balance
ledger/bet_not_foundwin references a bet that does not exist
ledger/bet_rolled_backBet arrived after its rollback

General

validation/bad_requestBody/params failed validation (see details.issues)
ratelimit/exceededToo many requests
server/internalUnexpected server error

Idempotent operations (e.g. a duplicate ledger transactionUuid) are not errors — they return the stored original result.