Green Studios

Green Studios · Integration

Integration API v1

The two directions

IntegrationDirectionWhat it carries
Catalogue & launch operator → provider which games exist, and opening a game for a player
Wallet provider → operator validate session, balance, debit, credit, rollback

Authentication: one scheme, both directions

X-Signature: hex(HMAC-SHA256(request_body, secret))

Sign the body exactly as sent.

timestamp goes inside the signed body, in milliseconds. There is no separate header. Requests outside a 5 minute window are rejected on both sides.

Every request carries operator and timestamp. Requests we send you also carry request_id and currency.

Authentication failures

Unknown operator, disabled operator, missing secret, wrong signature: all return the same 401 INVALID_SIGNATURE.

What the provider exposes

operator → provider

Base URL: https://api-games.greenstudios.com.br/v1

POST /v1/games every game enabled for the operator
{"operator":"test-operator", "timestamp":1755680000000,
 "currency":"BRL", "limit":100, "offset":0}
{
  "status": "ok",
  "operator": "test-operator",
  "count": 1,
  "total": 60,
  "offset": 0,
  "currencies": ["BRL", "USD"],
  "games": [
    {
      "game_id": "ronda-online",
      "name": "Ronda Online",
      "studio": "greenstudios",
      "category": "LIVE",
      "demo": true, "mobile": true, "desktop": true, "freebet": true,
      "image_url": "https://greenstudios.com.br/thumbnails/300x300/ronda-online-thumb.webp",
      "currency": "BRL",
      "min_bet": , "max_bet": , "max_win": 
    }
  ]
}

count is the size of this page, total is the whole catalogue. A total larger than count means there is more: ask for the next page with offset.

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 in integer cents.

FieldMeaning
min_betsmallest accepted stake
max_betlargest accepted stake
max_winpayout ceiling; a bigger prize is paid at the ceiling
Missing limits

A missing limit field means the limit is unknown, not that there is none.

image_url is absent when the game has no artwork. currencies is the set of currencies enabled for you.

POST /v1/launch opens a game for one player

Returns the URL to load in an iframe or redirect.

{
  "operator": "test-operator", "timestamp": 1755680000000,
  "game_id": "ronda-online",
  "player_id": "618004",
  "token": "your-session-token",
  "currency": "BRL",
  "language": "pt",
  "demo": false, "mobile": true,
  "lobby_url": "https://your-site/lobby",
  "deposit_url": "https://your-site/deposit"
}
FieldRequiredNotes
game_idyesmust be in your catalogue
tokenunless demosent on every wallet call
player_idunless demoyour player identifier
currencyrecommendedthe session currency
languagenoISO 639-1. Default: en
demo, mobilenodemo needs neither token nor player
{"status":"ok", "url":"https://…/?gameId=…&casinoId=…&session=…&lang=…"}

The URL carries a session id. Your token and player_id are not in it: we take them server to server and exchange them for that id. Open the URL within 15 minutes.

Errors: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID (400), GAME_NOT_FOUND (404).

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.

Currencies

29 currencies are supported. The set enabled for one operator comes back in currencies from POST /v1/games.

ARS BDT BOB BRL CAD CDF CLP COP CRC EUR GYD INR KES KRW LSL MXN NGN PEN PHP PKR PYG TOP TZS UAH USD UYU VES XAF ZAR

Languages

pt, en and es. Any other value, and an absent language, falls back to en.

What the operator exposes

provider → operator

Five routes.

POST {wallet_url}/session     token → player, balance, currency
POST {wallet_url}/balance     balance
POST {wallet_url}/bet         debit
POST {wallet_url}/win         credit
POST {wallet_url}/rollback    refund

Response format

{"status":"ok", "balance":98500, "currency":"BRL",
 "player_id":"618004", "transaction_id":"…"}
{"status":"error", "error_code":"INSUFFICIENT_FUNDS", "error_message":"…"}

balance is integer cents, after the operation, and is required on success.

currency is the currency of the account. Send it on every response.

The requests we send

RouteFields
/sessiontoken
/balanceplayer_id, token
/betplayer_id, token, amount, transaction_id, round_id
/winplayer_id, token, amount, transaction_id, bet_id, round_id, type
/rollbackplayer_id, token, amount, transaction_id, bet_id, round_id, external_bet_id

Plus timestamp, request_id and currency on every one, and game_id when the game is known.

Error codes

CodeMeaningWe retry?
INSUFFICIENT_FUNDSnot enough balanceno
TOKEN_EXPIREDsession expiredno
TOKEN_INVALIDsession never existedno
PLAYER_NOT_FOUNDunknown playerno
BET_NOT_FOUNDthe referenced bet does not existno
CURRENCY_MISMATCHwrong currency for this accountno
INTERNAL_ERRORyour side failedyes

Any code we do not recognise is treated as retryable.

Identity and session

1

The token is the session identity.

2

The token is random.

It must not equal the player_id, be derived from it, or be your own site session id. We refuse a launch whose token equals the player_id or is shorter than 16 characters, with INVALID_TOKEN.

3

A new token for every /v1/launch.

4

A token belongs to one player.

If a second player arrives with a token already in use, we refuse the session and link nothing.

5

Your wallet attests the token owner.

Every /balance success response carries player_id: the player that token belongs to. When it differs from the player of the session, we refuse and the game does not open.

6

An expired token refuses every call.

/session, /balance, /bet, /win and /rollback all return TOKEN_EXPIRED.

The rules that actually break integrations

1

Idempotency

The same transaction_id must never debit twice. We retry when we do not get a response.

Store the response, not only the id: the second call returns the same balance as the first.

Business refusals are not memorised.

2

A zero-amount credit is valid and must be accepted

It is the terminal event of a losing round.

3

Business errors are HTTP 200, not 5xx

Insufficient funds is a 200 with an error_code. 5xx is treated as a transport failure and retried.

4

Currency belongs to the session, not to the operator

It is fixed at launch and is sent on every wallet call.

5

Exactly one terminal event per round

Every round ends exactly once, with a win or with a zero-amount credit.

Optional capabilities

Declared at provisioning.

CapabilityWhat it means
freebet_mode: per_rounddefault. Free rounds notified one by one; each prize credited as it happens
freebet_mode: aggregatefree rounds produce one credit at the end
zero_winyou require the zero-amount credit to close a lost free round

The two freebet modes are mutually exclusive.

Green Studios · Integração

Integration API v1

As duas direções

IntegraçãoDireçãoO que carrega
Catálogo e launch operador → provedor quais jogos existem, e abrir um jogo para um jogador
Carteira provedor → operador validar sessão, saldo, débito, crédito, estorno

Autenticação: um esquema só, nas duas direções

X-Signature: hex(HMAC-SHA256(corpo_da_requisicao, segredo))

Assinem o corpo exatamente como enviado.

O timestamp vai dentro do corpo assinado, em milissegundos. Não há header separado. Requisições fora de uma janela de 5 minutos são recusadas dos dois lados.

Toda requisição carrega operator e timestamp. As que enviamos a vocês carregam também request_id e currency.

Falhas de autenticação

Operador desconhecido, operador desativado, segredo ausente, assinatura errada: todos devolvem o mesmo 401 INVALID_SIGNATURE.

O que o provedor expõe

operador → provedor

URL base: https://api-games.greenstudios.com.br/v1

POST /v1/games todos os jogos liberados para o operador
{"operator":"test-operator", "timestamp":1755680000000,
 "currency":"BRL", "limit":100, "offset":0}
{
  "status": "ok",
  "operator": "test-operator",
  "count": 1,
  "total": 60,
  "offset": 0,
  "currencies": ["BRL", "USD"],
  "games": [
    {
      "game_id": "ronda-online",
      "name": "Ronda Online",
      "studio": "greenstudios",
      "category": "LIVE",
      "demo": true, "mobile": true, "desktop": true, "freebet": true,
      "image_url": "https://greenstudios.com.br/thumbnails/300x300/ronda-online-thumb.webp",
      "currency": "BRL",
      "min_bet": , "max_bet": , "max_win": 
    }
  ]
}

count é o tamanho desta página, total é o catálogo inteiro. total maior que count significa que há mais: peçam a página seguinte com offset.

freebet diz se o jogo aceita rodadas grátis concedidas pelo operador.

Os três limites

Eles aparecem somente quando vocês enviam currency, valem para aquela moeda, e estão em centavos inteiros.

CampoSignificado
min_betmenor aposta aceita
max_betmaior aposta aceita
max_winteto de pagamento; prêmio acima é pago no teto
Limite ausente

Um campo de limite ausente significa que o limite é desconhecido, não que não há limite.

image_url não aparece quando o jogo não tem arte. currencies é o conjunto de moedas habilitadas para vocês.

POST /v1/launch abre um jogo para um jogador

Devolve a URL para carregar num iframe ou redirecionar.

{
  "operator": "test-operator", "timestamp": 1755680000000,
  "game_id": "ronda-online",
  "player_id": "618004",
  "token": "seu-token-de-sessao",
  "currency": "BRL",
  "language": "pt",
  "demo": false, "mobile": true,
  "lobby_url": "https://seu-site/lobby",
  "deposit_url": "https://seu-site/deposito"
}
CampoObrigatórioObservações
game_idsimtem que estar no seu catálogo
tokenexceto em demovai em toda chamada de carteira
player_idexceto em demoo seu identificador de jogador
currencyrecomendadoa moeda da sessão
languagenãoISO 639-1. Padrão: en
demo, mobilenãodemo dispensa token e jogador
{"status":"ok", "url":"https://…/?gameId=…&casinoId=…&session=…&lang=…"}

A URL leva um identificador session. O token e o player_id de vocês não vão nela: nós os recebemos de servidor para servidor e trocamos pelo identificador. Abram a URL dentro de 15 minutos.

Erros: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID (400), GAME_NOT_FOUND (404).

Moedas e idiomas

Todo valor monetário é em centavos inteiros. 1500 significa 15,00 na moeda da sessão.

Campo monetário em unidades da moeda, ou em ponto flutuante, é inválido.

Moedas

São 29 moedas suportadas. O conjunto habilitado para um operador volta em currencies no POST /v1/games.

ARS BDT BOB BRL CAD CDF CLP COP CRC EUR GYD INR KES KRW LSL MXN NGN PEN PHP PKR PYG TOP TZS UAH USD UYU VES XAF ZAR

Idiomas

pt, en e es. Qualquer outro valor, e a ausência de language, cai em en.

O que o operador expõe

provedor → operador

Cinco rotas.

POST {wallet_url}/session     token → jogador, saldo, moeda
POST {wallet_url}/balance     saldo
POST {wallet_url}/bet         débito
POST {wallet_url}/win         crédito
POST {wallet_url}/rollback    estorno

Formato da resposta

{"status":"ok", "balance":98500, "currency":"BRL",
 "player_id":"618004", "transaction_id":"…"}
{"status":"error", "error_code":"INSUFFICIENT_FUNDS", "error_message":"…"}

balance é centavos inteiros, depois da operação, e é obrigatório no sucesso.

currency é a moeda da conta. Enviem em toda resposta.

As requisições que enviamos

RotaCampos
/sessiontoken
/balanceplayer_id, token
/betplayer_id, token, amount, transaction_id, round_id
/winplayer_id, token, amount, transaction_id, bet_id, round_id, type
/rollbackplayer_id, token, amount, transaction_id, bet_id, round_id, external_bet_id

Mais timestamp, request_id e currency em todas, e game_id quando o jogo é conhecido.

Códigos de erro

CódigoSignificadoRetentamos?
INSUFFICIENT_FUNDSsaldo insuficientenão
TOKEN_EXPIREDsessão expiradanão
TOKEN_INVALIDsessão nunca existiunão
PLAYER_NOT_FOUNDjogador desconhecidonão
BET_NOT_FOUNDa aposta referenciada não existenão
CURRENCY_MISMATCHmoeda errada para esta contanão
INTERNAL_ERRORo seu lado falhousim

Qualquer código que não reconhecemos é tratado como retentável.

Identidade e sessão

1

O token é a identidade da sessão.

2

O token é aleatório.

Ele não pode ser igual ao player_id, derivado dele, nem ser o identificador de sessão do site de vocês. Recusamos com INVALID_TOKEN o launch cujo token seja igual ao player_id ou tenha menos de 16 caracteres.

3

Um token novo a cada /v1/launch.

4

Um token pertence a um jogador só.

Se um segundo jogador chegar com um token já em uso, recusamos a sessão e nada é vinculado.

5

A carteira de vocês atesta o dono do token.

Toda resposta de sucesso do /balance traz player_id: o jogador a quem aquele token pertence. Quando ele diverge do jogador da sessão, recusamos e o jogo não abre.

6

Token vencido recusa toda chamada.

/session, /balance, /bet, /win e /rollback devolvem TOKEN_EXPIRED.

As regras que realmente quebram integrações

1

Idempotência

O mesmo transaction_id nunca pode debitar duas vezes. Retentamos quando não recebemos resposta.

Guardem a resposta, não só o id: a segunda chamada devolve o mesmo saldo da primeira.

Recusas de negócio não são memorizadas.

2

Um crédito de valor zero é válido e tem que ser aceito

Ele é o evento terminal de uma rodada perdida.

3

Erro de negócio é HTTP 200, não 5xx

Saldo insuficiente é um 200 com error_code. Tratamos 5xx como falha de transporte e retentamos.

4

A moeda pertence à sessão, não ao operador

Ela é fixada no launch e é enviada em toda chamada de carteira.

5

Exatamente um evento terminal por rodada

Toda rodada termina exatamente uma vez: com um prêmio, ou com um crédito de valor zero.

Capacidades opcionais

Declaradas no provisionamento.

CapacidadeO que significa
freebet_mode: per_roundpadrão. Rodadas grátis notificadas uma a uma; cada prêmio creditado na hora
freebet_mode: aggregaterodadas grátis produzem um crédito no fim
zero_winvocês exigem o crédito de valor zero para fechar uma rodada grátis perdida

Os dois modos de freebet são mutuamente exclusivos.

Green Studios · Integración

Integration API v1

Las dos direcciones

IntegraciónDirecciónQué transporta
Catálogo y launch operador → proveedor qué juegos existen, y abrir un juego para un jugador
Billetera proveedor → operador validar sesión, saldo, débito, crédito, reembolso

Autenticación: un solo esquema, en ambas direcciones

X-Signature: hex(HMAC-SHA256(cuerpo_de_la_peticion, secreto))

Firmen el cuerpo exactamente como se envía.

El timestamp va dentro del cuerpo firmado, en milisegundos. No hay cabecera aparte. Las peticiones fuera de una ventana de 5 minutos se rechazan en ambos lados.

Cada petición lleva operator y timestamp. Las que les enviamos llevan además request_id y currency.

Fallos de autenticación

Operador desconocido, operador desactivado, secreto ausente, firma incorrecta: todos devuelven el mismo 401 INVALID_SIGNATURE.

Lo que expone el proveedor

operador → proveedor

URL base: https://api-games.greenstudios.com.br/v1

POST /v1/games todos los juegos habilitados para el operador
{"operator":"test-operator", "timestamp":1755680000000,
 "currency":"BRL", "limit":100, "offset":0}
{
  "status": "ok",
  "operator": "test-operator",
  "count": 1,
  "total": 60,
  "offset": 0,
  "currencies": ["BRL", "USD"],
  "games": [
    {
      "game_id": "ronda-online",
      "name": "Ronda Online",
      "studio": "greenstudios",
      "category": "LIVE",
      "demo": true, "mobile": true, "desktop": true, "freebet": true,
      "image_url": "https://greenstudios.com.br/thumbnails/300x300/ronda-online-thumb.webp",
      "currency": "BRL",
      "min_bet": , "max_bet": , "max_win": 
    }
  ]
}

count es el tamaño de esta página, total es el catálogo completo. Un total mayor que count significa que hay más: pidan la página siguiente con offset.

freebet dice si el juego acepta rondas gratis concedidas por el operador.

Los tres límites

Aparecen solo cuando envían currency, valen para esa moneda, y van en céntimos enteros.

CampoSignificado
min_betapuesta mínima aceptada
max_betapuesta máxima aceptada
max_wintecho de pago; un premio mayor se paga en el techo
Límite ausente

Un campo de límite ausente significa que el límite es desconocido, no que no haya límite.

image_url no aparece cuando el juego no tiene arte. currencies es el conjunto de monedas habilitadas para ustedes.

POST /v1/launch abre un juego para un jugador

Devuelve la URL para cargar en un iframe o redirigir.

{
  "operator": "test-operator", "timestamp": 1755680000000,
  "game_id": "ronda-online",
  "player_id": "618004",
  "token": "su-token-de-sesion",
  "currency": "BRL",
  "language": "es",
  "demo": false, "mobile": true,
  "lobby_url": "https://su-sitio/lobby",
  "deposit_url": "https://su-sitio/deposito"
}
CampoObligatorioNotas
game_iddebe estar en su catálogo
tokensalvo en demova en cada llamada de billetera
player_idsalvo en demosu identificador de jugador
currencyrecomendadola moneda de la sesión
languagenoISO 639-1. Por defecto: en
demo, mobilenodemo no necesita token ni jugador
{"status":"ok", "url":"https://…/?gameId=…&casinoId=…&session=…&lang=…"}

La URL lleva un identificador session. Su token y su player_id no van en ella: los recibimos de servidor a servidor y los cambiamos por ese identificador. Abran la URL dentro de 15 minutos.

Errores: MISSING_GAME_ID, MISSING_TOKEN, MISSING_PLAYER_ID (400), GAME_NOT_FOUND (404).

Monedas e idiomas

Todo importe monetario va en céntimos enteros. 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.

Monedas

Son 29 monedas admitidas. El conjunto habilitado para un operador vuelve en currencies en POST /v1/games.

ARS BDT BOB BRL CAD CDF CLP COP CRC EUR GYD INR KES KRW LSL MXN NGN PEN PHP PKR PYG TOP TZS UAH USD UYU VES XAF ZAR

Idiomas

pt, en y es. Cualquier otro valor, y la ausencia de language, cae en en.

Lo que expone el operador

proveedor → operador

Cinco rutas.

POST {wallet_url}/session     token → jugador, saldo, moneda
POST {wallet_url}/balance     saldo
POST {wallet_url}/bet         débito
POST {wallet_url}/win         crédito
POST {wallet_url}/rollback    reembolso

Formato de la respuesta

{"status":"ok", "balance":98500, "currency":"BRL",
 "player_id":"618004", "transaction_id":"…"}
{"status":"error", "error_code":"INSUFFICIENT_FUNDS", "error_message":"…"}

balance es céntimos enteros, después de la operación, y es obligatorio en el éxito.

currency es la moneda de la cuenta. Envíenla en cada respuesta.

Las peticiones que enviamos

RutaCampos
/sessiontoken
/balanceplayer_id, token
/betplayer_id, token, amount, transaction_id, round_id
/winplayer_id, token, amount, transaction_id, bet_id, round_id, type
/rollbackplayer_id, token, amount, transaction_id, bet_id, round_id, external_bet_id

Más timestamp, request_id y currency en todas, y game_id cuando el juego es conocido.

Códigos de error

CódigoSignificado¿Reintentamos?
INSUFFICIENT_FUNDSsaldo insuficienteno
TOKEN_EXPIREDsesión expiradano
TOKEN_INVALIDla sesión nunca existióno
PLAYER_NOT_FOUNDjugador desconocidono
BET_NOT_FOUNDla apuesta referenciada no existeno
CURRENCY_MISMATCHmoneda equivocada para esta cuentano
INTERNAL_ERRORel lado del operador falló

Cualquier código que no reconozcamos se trata como reintentable.

Identidad y sesión

1

El token es la identidad de la sesión.

2

El token es aleatorio.

No puede ser igual al player_id, derivado de él, ni ser el identificador de sesión de su sitio. Rechazamos con INVALID_TOKEN el launch cuyo token sea igual al player_id o tenga menos de 16 caracteres.

3

Un token nuevo en cada /v1/launch.

4

Un token pertenece a un solo jugador.

Si un segundo jugador llega con un token ya en uso, rechazamos la sesión y no vinculamos nada.

5

Su billetera atesta al dueño del token.

Toda respuesta de éxito de /balance trae player_id: el jugador al que pertenece ese token. Cuando difiere del jugador de la sesión, rechazamos y el juego no abre.

6

Un token vencido rechaza toda llamada.

/session, /balance, /bet, /win y /rollback devuelven TOKEN_EXPIRED.

Las reglas que de verdad rompen integraciones

1

Idempotencia

El mismo transaction_id nunca debe debitar dos veces. Reintentamos cuando no recibimos respuesta.

Guarden la respuesta, no solo el id: la segunda llamada devuelve el mismo saldo que la primera.

Los rechazos de negocio no se memorizan.

2

Un crédito de importe cero es válido y debe aceptarse

Es el evento terminal de una ronda perdida.

3

Los errores de negocio son HTTP 200, no 5xx

Saldo insuficiente es un 200 con error_code. Tratamos 5xx como fallo de transporte y reintentamos.

4

La moneda pertenece a la sesión, no al operador

Se fija en el launch y se envía en cada llamada de billetera.

5

Exactamente un evento terminal por ronda

Cada ronda termina exactamente una vez: con un premio, o con un crédito de importe cero.

Capacidades opcionales

Se declaran en el aprovisionamiento.

CapacidadQué significa
freebet_mode: per_roundpor defecto. Rondas gratis notificadas una a una; cada premio se acredita al momento
freebet_mode: aggregatelas rondas gratis producen un crédito al final
zero_winnecesitan el crédito de importe cero para cerrar una ronda gratis perdida

Los dos modos de freebet son mutuamente excluyentes.