Jumbo · jogo de crash
API de Integração v1
As duas direções
| Integração | Sentido | O que carrega |
|---|---|---|
Catálogo e lançamento | operador → provedor | quais jogos existem, e abrir uma partida para um jogador |
Carteira | provedor → operador | resolver a sessão, saldo, débito, crédito, estorno |
As oito que quebram integração
Todas contrariam uma convenção comum, e é por isso que estão juntas e antes das rotas: são os pontos em que implementar o que costuma ser produz um cliente que compila, passa no teste feliz e erra em produção.
| o palpite | o contrato |
|---|---|
Recusa vem em 4xx | Erro de negócio vem em HTTP 200, com status:"error" e error_code. Ramifique em status, nunca no status HTTP. Um cliente que teste response.ok lê uma recusa como sucesso. |
Um código de erro desconhecido é final | A regra padrão é retentar, até 20 vezes. São finais só sete: INSUFFICIENT_FUNDS, TOKEN_EXPIRED, TOKEN_INVALID, PLAYER_NOT_FOUND, BET_NOT_FOUND, CURRENCY_MISMATCH e PLAYER_BLOCKED. Inventar um nome para recusar em definitivo produz 20 tentativas idênticas contra a sua carteira. |
Assinar o JSON | Assine os bytes exatos do corpo. Desserializar e serializar de novo antes do HMAC muda espaçamento e ordem de chaves, e a assinatura deixa de bater com um conteúdo idêntico. |
<code>request_id</code> é a chave de idempotência | A chave é o transaction_id. O request_id nomeia a tentativa e muda a cada uma, junto com o timestamp. Deduplicar por request_id não deduplica nada; comparar o corpo inteiro rejeita toda retentativa. |
<code>/balance</code> sempre traz <code>player_id</code> | A primeira chamada de cada sessão vai só com o token: é ela que descobre o jogador. Exigir player_id ali recusa a entrada de todo mundo. |
Valor monetário é decimal | É inteiro, em centavos. R$ 3,56 é 356. O bundle do jogo já mandou 114.99999999999999 para uma aposta de R$ 1,15 quando o campo era decimal. |
As duas direções seguem a mesma convenção | Não seguem. A regra do 200 vale para a carteira; as duas rotas do jogo respondem 4xx, porque ali não há decisão de negócio, só pedido inválido. Os dois conjuntos de error_code quase não se tocam, e a exceção importa: INTERNAL_ERROR e INVALID_SIGNATURE estão nos dois, então o código sozinho não diz de que lado veio a falha. |
<code>freebet_id</code> só vem quando é brinde | O campo existe sempre, valendo null na aposta comum. Ramifique em freebet_id !== null, nunca na presença da chave. |
Autenticação: um esquema só, nas duas direções
X-Signature: hex(HMAC-SHA256(corpo_da_requisição, segredo))
Authorization: Bearer <chave>Assine os bytes exatos do corpo, e confira sobre esses mesmos bytes. Decodificar o JSON e serializá-lo de novo antes do HMAC muda o espaçamento e a ordem das chaves, e a assinatura deixa de bater com um conteúdo idêntico. É o erro mais comum, nos dois lados.
O timestamp vai dentro do corpo assinado, em milissegundos, sem cabeçalho próprio. Fora de uma janela de 5 minutos o pedido é recusado, nos dois sentidos: é o que impede reenviar um pedido capturado.
Todo pedido leva operator e timestamp; os que saem daqui levam também request_id, currency e game_id. O request_id nomeia a tentativa, não o movimento: duas tentativas do mesmo transaction_id têm ids diferentes, e é assim que você acha uma delas no seu log.
O Bearer vale só na direção que sai daqui. Nas duas rotas que expomos não há chave nossa, e a assinatura autentica sozinha: por isso o jogo recusa subir em modo operador sem segredo. Sem segredo configurado, o X-Signature não é enviado e a janela não se aplica.
Gere as credenciais
Os dois valores saem do crypto.getRandomValues do seu navegador e não saem dele: esta página não faz uma única requisição. Letras e números, sem palavra de dicionário, 32 e 48 caracteres. O mínimo que o jogo aceita é 24, e ele recusa subir abaixo disso.
O que nós expomosoperador → provedor
Duas rotas, sobre https://jumbo.aircrash.net, que é também a base das URLs de lançamento que o /v1/launch devolve. Uma instalação em outro endereço publica o dela.
/v1/gamestodos os jogos habilitados para o operador{"operator":"casa-do-norte", "timestamp":1755680000000,
"currency":"BRL"}{
"status": "ok",
"operator": "casa-do-norte",
"currencies": ["BRL", "USD"],
"games": [
{
"game_id": "jumbo-crash",
"name": "Jumbo",
"studio": "jumbo",
"category": "CRASH",
"demo": false, "mobile": true, "desktop": true, "freebet": true,
"currency": "BRL",
"min_bet": 100, "max_bet": 50000, "max_win": 5000000
}
]
}freebet diz se o jogo aceita rodadas grátis concedidas pelo operador.
Os três limites
Só aparecem quando você envia currency, valem para aquela moeda, e são centavos inteiros.
| Campo | Significado |
|---|---|
min_bet | menor aposta aceita |
max_bet | maior aposta aceita |
max_win | teto de pagamento; prêmio maior é pago no teto |
currencies é o conjunto de moedas habilitadas para você. É daí que sai em que moedas você pode conceder freebet: uma concessão numa moeda que a mesa não aceita é uma promessa que nunca se cumpre.
/v1/launchabre uma partida para um jogadorDevolve a URL para carregar em iframe ou redirecionar.
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"game_id": "jumbo-crash",
"player_id": "618004",
"token": "e7c1f0a9d3b84e2f95a6",
"currency": "BRL",
"language": "pt",
"demo": false, "mobile": true,
"lobby_url": "https://seu-site/lobby",
"deposit_url": "https://seu-site/deposito"
}| Campo | Obrigatório | Notas |
|---|---|---|
game_id | sim | tem de ser o jogo desta instalação |
token | salvo em demo | vai em toda chamada de carteira |
player_id | salvo em demo | o identificador do jogador no seu sistema |
currency | recomendado | a moeda da sessão |
language | não | pt, en ou es |
player_name | não | apelido ou nome; é ofuscado ao exibir |
theme | não | o skin: JUMBO ou SUPERAVIATOR (com 5 no fim, cinco caixas); a url já sai no domínio do skin |
demo, mobile | não | demo não precisa de token nem de jogador |
lobby_url, deposit_url | não | guardados na sessão; a mesa ainda não os exibe |
{"status":"ok",
"url":"https://jumbo.aircrash.net/?sid=v3Nq8Lm2&lang=pt&cur=BRL"}Erros: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID, INVALID_TOKEN (400), GAME_NOT_FOUND (404), DEMO_NOT_AVAILABLE (400).
Moedas e idiomas
Todo dinheiro é centavo inteiro. 1500 quer dizer 15,00 na moeda da sessão. Um campo monetário em unidades da moeda, ou em ponto flutuante, é inválido.
As moedas habilitadas para um operador voltam em currencies no POST /v1/games. Não há lista fixa aqui de propósito: a lista é a configuração da sua instalação, e publicá-la em dois lugares é garantir que um dia divirjam.
Idiomas
pt, en e es. Qualquer outro valor, e a ausência do campo, caem no idioma padrão da instalação, e não em en. A divergência com a referência é deliberada: cair num idioma que a maioria da base não lê, por causa de um campo esquecido, é pior do que cair no idioma da casa.
O que o operador expõeprovedor → operador
Quatro rotas.
POST {wallet_url}/balance token → jogador, saldo, moeda
POST {wallet_url}/bet débito
POST {wallet_url}/win crédito
POST {wallet_url}/rollback estornoFormato da resposta
{"status":"ok", "balance":98500, "currency":"BRL",
"player_id":"618004", "transaction_id":"w-77120"}{"status":"error", "error_code":"INSUFFICIENT_FUNDS",
"error_message":"saldo insuficiente"}balance é centavo inteiro, depois da operação, e é obrigatório no sucesso.
currency é a moeda da conta. Mande em toda resposta.
transaction_id na resposta é o seu número para o movimento, não o nosso. Ele existe para a conciliação: é o que se cita ao abrir um chamado sobre um movimento específico.
Campos por rota
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"request_id": "req-9f1464ae0da0664c",
"game_id": "jumbo-crash", "currency": "BRL",
"token": "e7c1f0a9d3b84e2f95a6", "player_id": "618004",
"transaction_id": "b-4471902", "round_id": "88213",
"amount": 1500
}| Rota | Campos |
|---|---|
/balance | player_id, token |
/bet | player_id, token, amount, transaction_id, round_id |
/win | player_id, token, amount, transaction_id, bet_id, round_id, type |
/rollback | player_id, token, amount, transaction_id, bet_id, round_id |
Mais operator, timestamp, request_id e currency em todas, e game_id quando o jogo é conhecido. O ciclo de freebet acrescenta freebet_id ao /bet e ao /win; o estorno acrescenta reason, que é diagnóstico e não muda nada do lado de lá.
Códigos de erro
| Código | Significado | Retentamos? |
|---|---|---|
INSUFFICIENT_FUNDS | saldo insuficiente | não |
TOKEN_EXPIRED | sessão expirada | não |
TOKEN_INVALID | sessão que nunca existiu | não |
PLAYER_NOT_FOUND | jogador desconhecido | não |
BET_NOT_FOUND | a aposta referenciada não existe | não |
CURRENCY_MISMATCH | moeda errada para esta conta | não |
PLAYER_BLOCKED | jogador impedido de apostar | não |
INTERNAL_ERROR | falha do seu lado | sim |
Jumbo · crash game
Integration API v1
The two directions
| Integration | Direction | What it carries |
|---|---|---|
Catalogue and launch | operator → provider | which games exist, and opening a game for a player |
Wallet | provider → operator | resolve the session, balance, debit, credit, rollback |
The eight that break integrations
Every one of them contradicts a common convention, which is why they sit together and before the routes: these are the points where implementing what usually holds yields a client that compiles, passes the happy-path test, and is wrong in production.
| the guess | the contract |
|---|---|
A refusal comes as 4xx | Business errors come as HTTP 200, with status:"error" and an error_code. Branch on status, never on the HTTP status. A client testing response.ok reads a refusal as success. |
An unknown error code is final | The default is to retry, up to 20 times. Only seven are final: INSUFFICIENT_FUNDS, TOKEN_EXPIRED, TOKEN_INVALID, PLAYER_NOT_FOUND, BET_NOT_FOUND, CURRENCY_MISMATCH and PLAYER_BLOCKED. Inventing a name to refuse for good produces 20 identical attempts against your wallet. |
Sign the JSON | Sign the exact bytes of the body. Deserialising and serialising again before the HMAC changes whitespace and key order, and the signature stops matching identical content. |
<code>request_id</code> is the idempotency key | The key is transaction_id. The request_id names the attempt and changes on each one, together with the timestamp. Deduplicating by request_id deduplicates nothing; comparing the whole body rejects every retry. |
<code>/balance</code> always carries <code>player_id</code> | The first call of each session carries only the token: it is the call that discovers the player. Requiring player_id there refuses everyone at the door. |
Money is a decimal | It is an integer, in cents. R$ 3.56 is 356. The game bundle once sent 114.99999999999999 for a R$ 1.15 bet, back when the field was decimal. |
Both directions follow the same convention | They do not. The 200 rule is for the wallet; the two game routes answer 4xx, because there is no business decision there, only an invalid request. The two error_code sets barely overlap, and the exception matters: INTERNAL_ERROR and INVALID_SIGNATURE are in both, so the code alone does not say which side failed. |
<code>freebet_id</code> only shows up on a freebet | The field is always there, and is null on an ordinary bet. Branch on freebet_id !== null, never on the key being present. |
Authentication: one scheme, both directions
X-Signature: hex(HMAC-SHA256(request_body, secret))
Authorization: Bearer <key>Sign the exact bytes of the body, and verify over those same bytes. Decoding the JSON and serialising it again before the HMAC changes whitespace and key order, and the signature stops matching identical content. It is the most common mistake, on both sides.
The timestamp goes inside the signed body, in milliseconds, with no header of its own. Outside a 5 minute window the request is refused, in both directions: that is what stops a captured request from being replayed.
Every request carries operator and timestamp; the ones leaving here also carry request_id, currency and game_id. The request_id names the attempt, not the movement: two attempts of the same transaction_id carry different ids, and that is how you find one of them in your log.
The Bearer applies only on the direction leaving here. On the two routes we expose there is no key of ours, and the signature authenticates on its own: that is why the game refuses to start in operator mode without a secret. With no secret configured, X-Signature is not sent and the window does not apply.
Generate the credentials
Both values come from your browser's crypto.getRandomValues and never leave it: this page makes no requests at all. Letters and digits, no dictionary words, 32 and 48 characters. The game accepts a minimum of 24 and refuses to start below that.
What we exposeoperator → provider
Two routes, on https://jumbo.aircrash.net, which is also the base of the launch URLs /v1/launch returns. An installation at another address publishes its own.
/v1/gamesevery game enabled for the operator{"operator":"casa-do-norte", "timestamp":1755680000000,
"currency":"BRL"}{
"status": "ok",
"operator": "casa-do-norte",
"currencies": ["BRL", "USD"],
"games": [
{
"game_id": "jumbo-crash",
"name": "Jumbo",
"studio": "jumbo",
"category": "CRASH",
"demo": false, "mobile": true, "desktop": true, "freebet": true,
"currency": "BRL",
"min_bet": 100, "max_bet": 50000, "max_win": 5000000
}
]
}freebet says whether the game accepts free rounds granted by the operator.
The three limits
They appear only when you send currency, hold for that currency, and are integer cents.
| Field | Meaning |
|---|---|
min_bet | smallest accepted stake |
max_bet | largest accepted stake |
max_win | payout ceiling; a bigger prize is paid at the ceiling |
currencies is the set of currencies enabled for you. It is where you read which currencies you may grant freebets in: a grant in a currency the table does not accept is a promise that never comes due.
/v1/launchopens a game for one playerReturns the URL to load in an iframe or redirect to.
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"game_id": "jumbo-crash",
"player_id": "618004",
"token": "e7c1f0a9d3b84e2f95a6",
"currency": "BRL",
"language": "pt",
"demo": false, "mobile": true,
"lobby_url": "https://seu-site/lobby",
"deposit_url": "https://seu-site/deposito"
}| Field | Required | Notes |
|---|---|---|
game_id | yes | must be this installation’s game |
token | unless demo | sent on every wallet call |
player_id | unless demo | your player identifier |
currency | recommended | the session currency |
language | no | pt, en or es |
player_name | no | nickname or name; masked before display |
theme | no | the skin: JUMBO or SUPERAVIATOR (a trailing 5 means five bet boxes); the url comes back on the skin’s domain |
demo, mobile | no | demo needs neither token nor player |
lobby_url, deposit_url | no | stored on the session; the table does not surface them yet |
{"status":"ok",
"url":"https://jumbo.aircrash.net/?sid=v3Nq8Lm2&lang=pt&cur=BRL"}Errors: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID, INVALID_TOKEN (400), GAME_NOT_FOUND (404), DEMO_NOT_AVAILABLE (400).
Currencies and languages
All money is integer cents. 1500 means 15.00 in the session currency. A monetary field in currency units, or in floating point, is invalid.
The currencies enabled for an operator come back in currencies from POST /v1/games. There is no fixed list here on purpose: the list is your installation’s configuration, and publishing it in two places guarantees they diverge one day.
Languages
pt, en and es. Any other value, and an absent field, fall back to the installation’s default language, not to en. The divergence from the market reference is deliberate: falling back to a language most of the player base cannot read, because of a forgotten field, is worse than falling back to the house language.
What the operator exposesprovider → operator
Four routes.
POST {wallet_url}/balance token → player, balance, currency
POST {wallet_url}/bet debit
POST {wallet_url}/win credit
POST {wallet_url}/rollback refundResponse format
{"status":"ok", "balance":98500, "currency":"BRL",
"player_id":"618004", "transaction_id":"w-77120"}{"status":"error", "error_code":"INSUFFICIENT_FUNDS",
"error_message":"saldo insuficiente"}balance is integer cents, after the operation, and is required on success.
currency is the currency of the account. Send it on every response.
transaction_id in the response is your number for the movement, not ours. It exists for reconciliation: it is what you quote when opening a ticket about one specific movement.
Fields per route
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"request_id": "req-9f1464ae0da0664c",
"game_id": "jumbo-crash", "currency": "BRL",
"token": "e7c1f0a9d3b84e2f95a6", "player_id": "618004",
"transaction_id": "b-4471902", "round_id": "88213",
"amount": 1500
}| Route | Fields |
|---|---|
/balance | player_id, token |
/bet | player_id, token, amount, transaction_id, round_id |
/win | player_id, token, amount, transaction_id, bet_id, round_id, type |
/rollback | player_id, token, amount, transaction_id, bet_id, round_id |
Plus operator, timestamp, request_id and currency on every one, and game_id when the game is known. The freebet cycle adds freebet_id to /bet and /win; the rollback adds reason, which is diagnostic and changes nothing on your side.
Error codes
| Code | Meaning | We retry? |
|---|---|---|
INSUFFICIENT_FUNDS | not enough balance | no |
TOKEN_EXPIRED | session expired | no |
TOKEN_INVALID | session never existed | no |
PLAYER_NOT_FOUND | unknown player | no |
BET_NOT_FOUND | the referenced bet does not exist | no |
CURRENCY_MISMATCH | wrong currency for this account | no |
PLAYER_BLOCKED | player barred from betting | no |
INTERNAL_ERROR | your side failed | yes |
Jumbo · juego de crash
API de Integración v1
Las dos direcciones
| Integración | Sentido | Qué transporta |
|---|---|---|
Catálogo y lanzamiento | operador → proveedor | qué juegos existen, y abrir una partida para un jugador |
Billetera | proveedor → operador | resolver la sesión, saldo, débito, crédito, reverso |
Las ocho que rompen integraciones
Todas contradicen una convención común, y por eso están juntas y antes de las rutas: son los puntos en los que implementar lo que suele ser produce un cliente que compila, pasa la prueba feliz y se equivoca en producción.
| la suposición | el contrato |
|---|---|
El rechazo llega como 4xx | El error de negocio llega como HTTP 200, con status:"error" y error_code. Ramifique en status, nunca en el estado HTTP. Un cliente que compruebe response.ok lee un rechazo como éxito. |
Un código de error desconocido es final | Lo predeterminado es reintentar, hasta 20 veces. Solo siete son finales: INSUFFICIENT_FUNDS, TOKEN_EXPIRED, TOKEN_INVALID, PLAYER_NOT_FOUND, BET_NOT_FOUND, CURRENCY_MISMATCH y PLAYER_BLOCKED. Inventar un nombre para rechazar en definitiva produce 20 intentos idénticos contra su cartera. |
Firmar el JSON | Firme los bytes exactos del cuerpo. Deserializar y volver a serializar antes del HMAC cambia los espacios y el orden de las claves, y la firma deja de coincidir con un contenido idéntico. |
<code>request_id</code> es la clave de idempotencia | La clave es transaction_id. El request_id nombra el intento y cambia en cada uno, junto con el timestamp. Deduplicar por request_id no deduplica nada; comparar el cuerpo entero rechaza todo reintento. |
<code>/balance</code> siempre trae <code>player_id</code> | La primera llamada de cada sesión va solo con el token: es la que descubre al jugador. Exigir player_id ahí rechaza la entrada de todos. |
El importe es decimal | Es entero, en céntimos. R$ 3,56 es 356. El bundle del juego llegó a enviar 114.99999999999999 para una apuesta de R$ 1,15 cuando el campo era decimal. |
Las dos direcciones siguen la misma convención | No la siguen. La regla del 200 vale para la cartera; las dos rutas del juego responden 4xx, porque ahí no hay decisión de negocio, solo petición inválida. Los dos conjuntos de error_code casi no se tocan, y la excepción importa: INTERNAL_ERROR e INVALID_SIGNATURE están en los dos, así que el código por sí solo no dice de qué lado vino el fallo. |
<code>freebet_id</code> solo llega cuando es un premio | El campo está siempre, y vale null en la apuesta común. Ramifique en freebet_id !== null, nunca en la presencia de la clave. |
Autenticación: un solo esquema, en ambas direcciones
X-Signature: hex(HMAC-SHA256(cuerpo_de_la_petición, secreto))
Authorization: Bearer <clave>Firme los bytes exactos del cuerpo, y compruebe sobre esos mismos bytes. Decodificar el JSON y volver a serializarlo antes del HMAC cambia los espacios y el orden de las claves, y la firma deja de coincidir con un contenido idéntico. Es el error más común, en ambos lados.
El timestamp va dentro del cuerpo firmado, en milisegundos, sin cabecera propia. Fuera de una ventana de 5 minutos la petición se rechaza, en ambos sentidos: es lo que impide reenviar una petición capturada.
Toda petición lleva operator y timestamp; las que salen de aquí llevan además request_id, currency y game_id. El request_id nombra el intento, no el movimiento: dos intentos del mismo transaction_id llevan ids distintos, y así encuentra uno de ellos en su log.
El Bearer vale solo en la dirección que sale de aquí. En las dos rutas que exponemos no hay clave nuestra, y la firma autentica sola: por eso el juego se niega a arrancar en modo operador sin secreto. Sin secreto configurado, X-Signature no se envía y la ventana no se aplica.
Genere las credenciales
Los dos valores salen del crypto.getRandomValues de su navegador y no salen de él: esta página no hace ni una petición. Letras y números, sin palabras de diccionario, 32 y 48 caracteres. El mínimo que el juego acepta es 24, y se niega a arrancar por debajo de eso.
Lo que exponemosoperador → proveedor
Dos rutas, sobre https://jumbo.aircrash.net, que es también la base de las URLs de lanzamiento que devuelve /v1/launch. Una instalación en otra dirección publica la suya.
/v1/gamestodos los juegos habilitados para el operador{"operator":"casa-do-norte", "timestamp":1755680000000,
"currency":"BRL"}{
"status": "ok",
"operator": "casa-do-norte",
"currencies": ["BRL", "USD"],
"games": [
{
"game_id": "jumbo-crash",
"name": "Jumbo",
"studio": "jumbo",
"category": "CRASH",
"demo": false, "mobile": true, "desktop": true, "freebet": true,
"currency": "BRL",
"min_bet": 100, "max_bet": 50000, "max_win": 5000000
}
]
}freebet indica si el juego acepta rondas gratis concedidas por el operador.
Los tres límites
Aparecen solo cuando usted envía currency, valen para esa moneda, y son céntimos enteros.
| Campo | Significado |
|---|---|
min_bet | apuesta mínima aceptada |
max_bet | apuesta máxima aceptada |
max_win | techo de pago; un premio mayor se paga en el techo |
currencies es el conjunto de monedas habilitadas para usted. De ahí sale en qué monedas puede conceder freebets: una concesión en una moneda que la mesa no acepta es una promesa que nunca se cumple.
/v1/launchabre una partida para un jugadorDevuelve la URL para cargar en un iframe o redirigir.
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"game_id": "jumbo-crash",
"player_id": "618004",
"token": "e7c1f0a9d3b84e2f95a6",
"currency": "BRL",
"language": "pt",
"demo": false, "mobile": true,
"lobby_url": "https://seu-site/lobby",
"deposit_url": "https://seu-site/deposito"
}| Campo | Obligatorio | Notas |
|---|---|---|
game_id | sí | debe ser el juego de esta instalación |
token | salvo en demo | se envía en cada llamada de billetera |
player_id | salvo en demo | su identificador de jugador |
currency | recomendado | la moneda de la sesión |
language | no | pt, en o es |
player_name | no | apodo o nombre; se ofusca al mostrarlo |
theme | no | el skin: JUMBO o SUPERAVIATOR (con 5 al final, cinco cajas); la url ya sale en el dominio del skin |
demo, mobile | no | demo no necesita token ni jugador |
lobby_url, deposit_url | no | guardados en la sesión; la mesa aún no los muestra |
{"status":"ok",
"url":"https://jumbo.aircrash.net/?sid=v3Nq8Lm2&lang=pt&cur=BRL"}Errores: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID, INVALID_TOKEN (400), GAME_NOT_FOUND (404), DEMO_NOT_AVAILABLE (400).
Monedas e idiomas
Todo el dinero es céntimo entero. 1500 significa 15,00 en la moneda de la sesión. Un campo monetario en unidades de la moneda, o en coma flotante, es inválido.
Las monedas habilitadas para un operador vuelven en currencies del POST /v1/games. Aquí no hay lista fija a propósito: la lista es la configuración de su instalación, y publicarla en dos sitios garantiza que algún día diverjan.
Idiomas
pt, en y es. Cualquier otro valor, y la ausencia del campo, caen en el idioma por defecto de la instalación y no en en. La divergencia con la referencia del mercado es deliberada: caer en un idioma que la mayoría de la base no lee, por un campo olvidado, es peor que caer en el idioma de la casa.
Lo que expone el operadorproveedor → operador
Cuatro rutas.
POST {wallet_url}/balance token → jugador, saldo, moneda
POST {wallet_url}/bet débito
POST {wallet_url}/win crédito
POST {wallet_url}/rollback reversoFormato de la respuesta
{"status":"ok", "balance":98500, "currency":"BRL",
"player_id":"618004", "transaction_id":"w-77120"}{"status":"error", "error_code":"INSUFFICIENT_FUNDS",
"error_message":"saldo insuficiente"}balance es céntimo entero, después de la operación, y es obligatorio en el éxito.
currency es la moneda de la cuenta. Envíela en cada respuesta.
transaction_id en la respuesta es su número para el movimiento, no el nuestro. Existe para la conciliación: es lo que se cita al abrir un ticket sobre un movimiento concreto.
Campos por ruta
{
"operator": "casa-do-norte", "timestamp": 1755680000000,
"request_id": "req-9f1464ae0da0664c",
"game_id": "jumbo-crash", "currency": "BRL",
"token": "e7c1f0a9d3b84e2f95a6", "player_id": "618004",
"transaction_id": "b-4471902", "round_id": "88213",
"amount": 1500
}| Ruta | Campos |
|---|---|
/balance | player_id, token |
/bet | player_id, token, amount, transaction_id, round_id |
/win | player_id, token, amount, transaction_id, bet_id, round_id, type |
/rollback | player_id, token, amount, transaction_id, bet_id, round_id |
Más operator, timestamp, request_id y currency en todas, y game_id cuando el juego se conoce. El ciclo de freebet añade freebet_id al /bet y al /win; el reverso añade reason, que es diagnóstico y no cambia nada de su lado.
Códigos de error
| Código | Significado | ¿Reintentamos? |
|---|---|---|
INSUFFICIENT_FUNDS | saldo insuficiente | no |
TOKEN_EXPIRED | sesión expirada | no |
TOKEN_INVALID | sesión que nunca existió | no |
PLAYER_NOT_FOUND | jugador desconocido | no |
BET_NOT_FOUND | la apuesta referenciada no existe | no |
CURRENCY_MISMATCH | moneda incorrecta para esta cuenta | no |
PLAYER_BLOCKED | jugador impedido de apostar | no |
INTERNAL_ERROR | fallo de su lado | sí |