Uma conexão.
Toda a experiência OrbiPrediction.
Integre mercados de previsão ao seu produto com uma chamada no servidor e um iframe no navegador. Seus jogadores, sua marca, um ambiente isolado.
01 / Primeiros passos
- Receba o login do backoffice e a API key da OrbiPrediction. Altere a senha em Minha conta.
- Em Minha integração → Configuração, cadastre a origem exata do seu site, como
https://app.seusite.com. Cadastre cada subdomínio separadamente; sem caminhos ou curingas. Para desenvolvimento,http://localhost:3000é aceito. - Guarde a chave
orb_sk_…em um secret manager ou variável de ambiente do seu backend. Nunca em HTML, JavaScript público, Git, URLs ou logs. - Seu backend autentica seu usuário e chama a API OrbiPrediction com um identificador estável desse usuário.
- Envie somente a
launchUrlao navegador autenticado e monte o iframe imediatamente.
User → Partner backend → OrbiPrediction /api/v1/launch
│ │
└── launchUrl ←────┘
│
Iframe OrbiPrediction
│
Isolated player sessionO identificador é vinculado ao seu cliente: o mesmo externalUserId em dois clientes representa duas contas independentes. Dentro de um cliente, o mesmo ID mantém saldo fictício e histórico entre aberturas.
02 / Contrato da API
Base URL de produção: https://orbiprediction.com. Transporte HTTPS, corpos JSON e autenticação Authorization: Bearer YOUR_API_KEY. Chamadas de integração são feitas entre servidores; a API não habilita CORS para uso da chave no navegador.
GET /api/v1/me
Valida a chave e retorna seu cliente, modo e origens autorizadas.
curl 'https://orbiprediction.com/api/v1/me' \ -H "Authorization: Bearer $ORBIT_API_KEY"
POST /api/v1/launch
Gera um link assinado, válido por 120 segundos e utilizável uma vez. O cliente é identificado pela API key; não envie um client ID para selecionar outro cliente.
curl 'https://orbiprediction.com/api/v1/launch' \
-H "Authorization: Bearer $ORBIT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{
"externalUserId": "user_123",
"parentOrigin": "https://app.seusite.com",
"mode": "simulation",
"locale": "pt-BR"
}'| Campo | Contrato |
|---|---|
| externalUserId | Obrigatório, string de 1–128 caracteres sem caracteres de controle. Use um ID opaco do usuário autenticado, obtido da sua sessão no servidor. |
| parentOrigin | Obrigatório. Origem exata autorizada no backoffice. Não aceite qualquer valor enviado pelo navegador; defina a origem do seu frontend no backend. |
| mode | Opcional, somente simulation. |
| locale | Opcional: pt-BR, en ou es. Títulos e regras dos mercados preservam o idioma da fonte. |
| Idempotency-Key | Header obrigatório. 16–100 letras, números, hífens ou underscores. UUID recomendado. |
Resposta · HTTP 201
{
"launchId": "LAUNCH_UUID",
"launchUrl": "https://orbiprediction.com/launch/ID.SIGNATURE",
"expiresAt": "2026-10-18T18:02:00.000Z",
"mode": "simulation",
"locale": "pt-BR"
}X-Request-Id identifica a chamada para diagnóstico. O backoffice mostra status HTTP e duração das requisições autenticadas dos últimos 30 dias, sem gravar seus corpos ou segredos.
Exemplo de backend · Node.js / Express
// requireUser validates your own authenticated user session.
// Enable CSRF protection in your application.
app.post('/orbit/session', requireUser, async (req, res) => {
const response = await fetch(
'https://orbiprediction.com/api/v1/launch',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ORBIT_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({
externalUserId: String(req.user.id),
parentOrigin: process.env.PUBLIC_SITE_ORIGIN,
mode: 'simulation'
}),
signal: AbortSignal.timeout(10000)
}
);
res.set('Cache-Control', 'no-store');
res.status(response.status).json(await response.json());
});O exemplo cria uma nova abertura por chamada. Para repetir uma chamada após timeout, preserve a mesma chave de idempotência e o mesmo corpo no seu backend.
03 / Iframe e SDK
Você pode atribuir a URL retornada ao src de um iframe com title="OrbiPrediction", referrerpolicy="no-referrer", largura 100% e altura inicial 800 px. Alternativamente, o SDK ajusta a altura e valida os eventos recebidos.
<div id="orbit"></div> <script src="https://orbiprediction.com/sdk/v1/orbit.js" defer></script> <script src="/orbit-integration.js" defer></script>
Conteúdo do arquivo /orbit-integration.js no seu site:
async function openOrbit() {
const response = await fetch('/orbit/session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: '{}'
});
const session = await response.json();
if (!response.ok) throw new Error(session.error);
window.orbitInstance?.destroy();
window.orbitInstance = Orbit.mount({
container: '#orbit',
launchUrl: session.launchUrl,
onReady: () => console.log('OrbiPrediction ready'),
onSessionExpired: () => {
// Show a reconnect button that calls openOrbit().
// Validate the user session again in your backend.
},
onError: event => console.warn(event.code)
});
}
openOrbit().catch(() => {
document.querySelector('#orbit').textContent =
'Could not open. Please try again.';
});A sua CSP precisa permitir frame-src https://orbiprediction.com e, se usar o SDK, esse domínio em script-src. Evite iframes ancestrais de domínios não cadastrados. Não aplique um sandbox que bloqueie scripts, a origem da OrbiPrediction ou armazenamento: isso impede o funcionamento da aplicação.
Eventos postMessage · versão 1
| Evento | Payload / finalidade |
|---|---|
| orbit:ready | {type, version: 1, mode: "simulation"}. Conta do jogador carregada. |
| orbit:resize | {type, version: 1, height}. Altura desejada em pixels. |
| orbit:session-expired | {type, version: 1}. Solicite uma nova abertura ao seu backend. |
| orbit:error | {type, version: 1, code}. Falha ao inicializar uma abertura válida. |
Sem SDK, valide event.origin e event.source === iframe.contentWindow antes de usar qualquer mensagem. Limite a altura a 480–20.000 px. Os eventos são notificações de interface, não comprovantes financeiros. Um link já expirado pode retornar HTTP 410 antes de carregar a interface; mantenha também um timeout de abertura no seu site.
04 / Ciclo de vida e segurança
- Launch: 120 segundos, uso único. Repetir a mesma idempotência e o mesmo corpo retorna o mesmo link enquanto estiver pendente. Corpo diferente, link consumido ou expirado: HTTP 409. Para reabrir, gere nova idempotência.
- Jogador: a troca do link cria um bearer interno com duração de uma hora. A aplicação retira o código da URL. Não compartilhe URLs de abertura, capture-as em analytics nem as registre em logs do seu site.
- Persistência: a aplicação tenta manter a sessão do iframe em sessionStorage. Com armazenamento bloqueado, a sessão funciona em memória até recarregar. Para recarregar nesse cenário, gere nova launchUrl. Não depende de cookies de terceiros.
- Rotação: gere nova API key, atualize o backend, valide
/api/v1/mee revogue a anterior. Chaves completas aparecem somente uma vez. - Revogação: bloqueia novas aberturas e links ainda não consumidos. Sessões de jogadores já abertas continuam até expirar. Suspender o cliente encerra também os acessos de jogadores e do backoffice.
- Domínios: controlados por allowlist e CSP frame-ancestors. Remover uma origem invalida as sessões associadas a ela. Domínios não substituem autenticação: proteja a API key.
- Limites: 240 requisições por minuto por IP nas rotas API, compartilhadas entre chamadas desse IP. HTTP 429 exige espera; use backoff com jitter. Máximo de 20 origens por cliente e corpo de 16 KB.
- Dados: valores de relatórios são créditos fictícios em centésimos (100 = 1 CR). Mercado indisponível ou preço sem conexão ao vivo bloqueia novas simulações. Não há garantia de execução no preço visualizado: o usuário precisa aceitar mudanças de cotação.
05 / Erros e repetição de chamadas
{
"error": "Cadastre este domínio no backoffice antes de abrir o iframe.",
"code": "ORIGIN_NOT_ALLOWED",
"requestId": "REQUEST_UUID"
}| HTTP | Código / ação |
|---|---|
| 400 | INVALID_EXTERNAL_USER, INVALID_ORIGIN, INVALID_IDEMPOTENCY_KEY, UNSUPPORTED_MODE, UNSUPPORTED_LOCALE. Corrija o contrato. |
| 401 | INVALID_API_KEY. Confira ou substitua a chave no backend. |
| 403 | ORIGIN_NOT_ALLOWED ou TENANT_SUSPENDED. Revise o domínio e o estado do cliente. |
| 409 | IDEMPOTENCY_CONFLICT ou LAUNCH_ALREADY_FINISHED. Corrija o corpo ou inicie uma nova abertura. |
| 410 | LAUNCH_EXPIRED no link de abertura. Solicite um novo link. |
| 415 | Envie Content-Type: application/json. |
| 429 | Limite excedido. Aguarde um minuto; evite loops de renovação. |
| 5xx / timeout | Repita com backoff, mesma idempotência e mesmo corpo. Se a abertura tiver expirado, inicie outra. |
As validações de limite e formato aplicadas antes da API podem retornar somente error e code. Trate o status HTTP e não dependa da mensagem traduzida. Campos adicionais nas respostas v1 são compatíveis; mudanças incompatíveis exigirão uma nova versão.
06 / Checklist do parceiro
- Validar a API key com
GET /api/v1/me. - Abrir dois usuários distintos e confirmar saldo/histórico independentes.
- Reabrir o mesmo usuário e confirmar persistência.
- Confirmar que domínio não cadastrado é recusado.
- Testar link consumido, expiração e reconexão com uma nova launchUrl.
- Validar iframe em desktop e mobile, inclusive com cookies de terceiros bloqueados.
- Trocar a chave e confirmar que a anterior foi revogada.
- Conferir requests e auditoria no backoffice.
A prévia do backoffice usa um jogador técnico separado, identificado por console-preview:. Essa prévia confirma a experiência; valide também o iframe no domínio real do parceiro.
07 / Agregadores e provisionamento automático
A plataforma cria o agregador em Admin → Agregadores. O parceiro recebe uma chave orb_agg_… para o seu backend central. A hierarquia é plataforma → agregador → clientes → jogadores. A chave só acessa clientes pertencentes à sua rede; clientes diretos e clientes de outras redes permanecem isolados.
Fluxo recomendado para o Pigmo
- No deploy de um cassino, obtenha o ID interno estável do cassino e sua origem HTTPS verificada.
- Crie um UUID de provisionamento e persista-o no job antes de enviar a requisição. Em timeout, repita o mesmo UUID e corpo.
- Chame o endpoint abaixo. Salve o
client.clientIdretornado no registro do cassino. - Quando um jogador autenticado abrir a experiência, resolva no backend o cliente vinculado ao cassino e o ID desse jogador; gere uma abertura pelo endpoint do cliente.
- Envie apenas a
launchUrlao navegador e use o mesmo SDK de iframe documentado acima.
Não distribua a chave do agregador aos cassinos. Ela pertence ao serviço central de integração. O backend precisa conferir a associação entre usuário, cassino e clientId em cada abertura. Nunca use um clientId arbitrário recebido do navegador.
Criar cliente · POST /api/v1/aggregator/clients
curl 'https://orbiprediction.com/api/v1/aggregator/clients' \
-H "Authorization: Bearer $ORBI_AGGREGATOR_KEY" \
-H "Idempotency-Key: $PERSISTED_PROVISIONING_UUID" \
-H 'Content-Type: application/json' \
-H 'Accept-Language: en' \
-d '{
"externalClientId": "pigmo-casino-482",
"name": "Casino Aurora",
"allowedOrigins": ["https://aurora.example"],
"branding": {
"name": "Aurora",
"tagline": "Discover a new perspective.",
"accent": "#9cb8ff",
"categories": ["Esportes", "Economia", "Crypto"],
"paused": false,
"theme": {
"version": 1,
"preset": "midnight",
"colors": {"accent": "#9cb8ff"},
"font": "system",
"fontSize": 16,
"radius": {"card": 20, "control": 12},
"density": "comfortable",
"shadow": "soft",
"showHero": false
}
}
}'HTTP 201 retorna {created: true, client: {clientId, aggregatorId, externalClientId, name, status, platformBlocked, allowedOrigins, branding, mode}, documentationUrl}. O cliente nasce ativo, sem login humano ou chave individual: a chave de agregador já permite a integração. Caso necessário, a plataforma gera acesso humano em Clientes → Gerenciar → Acesso ao backoffice. Nenhuma senha é armazenada na resposta de idempotência.
Idempotência e recuperação
O mesmo agregador, Idempotency-Key e corpo normalizado retornam HTTP 200, created: false e a configuração pública original. O registro não expira automaticamente. Se a configuração mudou depois, consulte GET para obter o estado atual. A mesma chave com outro corpo retorna 409 IDEMPOTENCY_CONFLICT. Uma nova chave com um externalClientId já existente retorna 409 EXTERNAL_CLIENT_EXISTS; recupere o vínculo com o filtro abaixo, confirme os dados e use PATCH para alterações. Não gere IDs externos aleatórios a cada deploy.
Consultar e configurar a rede
GET /api/v1/aggregator/me
GET /api/v1/aggregator/clients?page=1
GET /api/v1/aggregator/clients?externalClientId=pigmo-casino-482
GET /api/v1/aggregator/clients/{clientId}
PATCH /api/v1/aggregator/clients/{clientId}Listas têm 50 clientes por página. PATCH aceita somente name, allowedOrigins, branding e status. Campos omitidos permanecem iguais; branding, quando enviado, é um objeto completo. O vínculo do agregador e o externalClientId são imutáveis. Cliente alheio e cliente inexistente retornam o mesmo HTTP 404.
Abrir o iframe de um cliente
POST /api/v1/aggregator/clients/{clientId}/launch
Authorization: Bearer orb_agg_...
Idempotency-Key: LAUNCH_UUID
Content-Type: application/json
{
"externalUserId": "player_123",
"parentOrigin": "https://aurora.example",
"locale": "en",
"mode": "simulation"
}A resposta e o ciclo de vida são os mesmos da API direta: link de 120 segundos, uso único, sessão de uma hora, identidade isolada por cliente. A idempotência de abertura também considera a credencial emissora; após trocar a chave, use um novo UUID.
Permissões, rotação e bloqueios
clients:read: consultar agregador e clientes.clients:write: provisionar e configurar clientes.launch:write: abrir sessões.- A chave inicial inclui as três permissões. Para produção, gere uma chave de deploy com leitura/escrita de clientes e outra de runtime somente para aberturas. Valide a nova chave na ação permitida e revogue a anterior.
- Chaves completas aparecem uma vez; são armazenadas somente como hash. A API não permite criar agregadores, trocar a propriedade do cliente ou acessar leads comerciais.
- Suspender o agregador bloqueia todas as suas chaves, os acessos individuais dos clientes, os jogadores e o backoffice; links pendentes expiram. Reativar exige novas sessões e preserva suspensões individuais.
- Um cliente bloqueado pela plataforma possui
platformBlocked: true. O agregador não consegue reativá-lo: HTTP 403PLATFORM_BLOCKED. - Limite persistente de 120 chamadas por minuto por agregador, compartilhado entre suas chaves, além do limite por IP. Respeite
Retry-After. Logs guardam metadados por 30 dias, sem corpos nem segredos.
Esta documentação descreve a API disponível da OrbiPrediction. O hook no pipeline de deploy do Pigmo precisa chamar esses endpoints e persistir o vínculo do cassino; a publicação da API não instala esse hook automaticamente.
08 / Aparência e temas do iframe
Configure o mesmo tema pelo painel ou por branding.theme na API de agregadores. O contrato usa opções estruturadas versionadas para manter o tema consistente no catálogo, portfólio, formulários e modais. A prévia do painel permite testar a aparência antes de salvar.
| Opção | Valores e comportamento |
|---|---|
| version / preset | 1; dark, light ou midnight. Campos omitidos usam os padrões do preset. |
| colors | background, surface, elevated, text, muted, border, accent, positive e negative. Somente hexadecimal de seis dígitos. |
| font / fontSize | dm-sans, space-grotesk, system, serif ou mono. Escala base inteira entre 14 e 18. |
| radius | card de 0 a 28 pixels e control de 0 a 20 pixels. Zero produz cantos retos. |
| density / shadow | comfortable ou compact; none ou soft. |
| showHero | Booleano. Mostra ou oculta o banner de apresentação. Avisos de simulação e controles essenciais permanecem visíveis. |
Texto principal e secundário precisam manter pelo menos 4,5:1 de contraste em todos os três fundos. Texto sobre botões e resultados é calculado automaticamente para legibilidade. Valores inválidos retornam 400 INVALID_THEME e a configuração anterior é preservada. Não são aceitos CSS livre, seletores, HTML, URLs de fontes externas ou valores fora dos limites.
Precedência: preset → colors explícitas. Se theme estiver ausente na criação, a accent antiga continua funcionando com a base escura. Em atualizações sem theme, o tema existente é preservado; a accent antiga atualiza seu destaque. Se theme for enviado, seu preset e cores têm precedência e a accent legada é sincronizada. Alterações salvas são aplicadas no próximo carregamento da experiência.
Referências de desenho: a Appearance API da Stripe oferece controles de fontes, cores, bordas e sombras; a customização da TradingView separa paleta, tema, tipografia e opções de interface. A OrbiPrediction usa seu próprio contrato validado, documentado no OpenAPI.
09 / Idiomas
Landing, documentação, admin, backoffice e experiência do iframe oferecem português, inglês e espanhol. O seletor de idioma preserva sua preferência. Os códigos aceitos em locale são pt-BR, en e es; a abertura define o idioma inicial do iframe. Para mensagens da API, envie Accept-Language.
Códigos de erro, nomes de campos, IDs, categorias técnicas e status permanecem estáveis. Decida pelo status HTTP e pelo campo code, nunca pelo texto traduzido. Conteúdo cadastrado pelo cliente, nomes próprios e títulos/regras originais dos mercados não são traduzidos automaticamente.
10 / Guia para agentes de IA
Um roteiro completo para um agente implementar a integração no sistema do parceiro. Leia este guia junto do OpenAPI atual; não deduza endpoints a partir dos exemplos nem confunda funcionalidades do painel com APIs públicas. Contrato verificado em 18/10/2026: Integration API v1.1.0, SDK v1.
Fontes que o agente deve ler
Comece pelo guia em Markdown, consulte o OpenAPI para os schemas exatos e use as seções de agregadores, temas e iframe para os exemplos completos. Os arquivos abaixo são públicos, sem autenticação e legíveis sem executar JavaScript.
1. Escopo e informações necessárias
- Esta versão é somente simulação, com créditos fictícios e dados públicos reais. Não implemente depósitos, saques, callbacks de carteira, apostas com dinheiro, ordens na Polymarket ou liquidação financeira. O feed público não exige credenciais da Polymarket.
- Antes de alterar código, localize o backend, a autenticação do jogador, a associação entre jogador e cassino, o pipeline de deploy, a persistência e a CSP do frontend. Confirme o modelo direto ou agregador, as origens exatas, os IDs estáveis, o idioma e a marca.
- Receba referências de segredos já configurados no ambiente; não peça chaves em chats ou commits. Sem credencial ou origem autorizada, implemente e teste localmente com respostas simuladas e registre a pendência. Não invente credenciais, permissões ou um ambiente de staging: este guia publica apenas a URL de produção.
ORBI_BASE_URL=https://orbiprediction.com # Server-only environment variables; use your secret manager. # Direct client: ORBI_CLIENT_API_KEY=<secret-reference> # Aggregator: separate deployment and runtime credentials. ORBI_PROVISION_API_KEY=<secret-reference:clients:read,clients:write> ORBI_LAUNCH_API_KEY=<secret-reference:launch:write> # A direct client can use one configured origin. Aggregators resolve # the verified origin per casino from their trusted database. PUBLIC_SITE_ORIGIN=https://casino.example
2. Escolha um único modelo de credencial
- Cliente direto: use orb_sk_ no servidor. A plataforma cria o cliente e seu acesso; o backoffice configura origens, marca e chaves. GET /api/v1/me identifica o cliente da chave; POST /api/v1/launch abre o jogador. Não envie clientId para selecionar outro cliente.
- Agregador: use orb_agg_ somente no backend central. A plataforma cria o agregador em Admin → Agregadores. A API pública permite criar e configurar clientes da própria rede e abrir seus jogadores; não permite criar agregadores ou emitir chaves. Clientes provisionados não recebem senha nem chave individual automaticamente.
# Direct client (orb_sk_)
GET /api/v1/me
POST /api/v1/launch
# Aggregator (orb_agg_): required scope on the right
GET /api/v1/aggregator/me # clients:read
GET /api/v1/aggregator/clients # clients:read
POST /api/v1/aggregator/clients # clients:write
GET /api/v1/aggregator/clients/{clientId} # clients:read
PATCH /api/v1/aggregator/clients/{clientId} # clients:write
POST /api/v1/aggregator/clients/{clientId}/launch # launch:write
Uma chave de runtime com apenas launch:write não pode validar acesso em /aggregator/me, que exige clients:read. Valide cada chave em uma operação autorizada. As rotas /api/console/* são internas ao painel; /api/launch/consume e o bearer do jogador são gerenciados pelo iframe. Não integre com essas rotas nem use /demo ou /embed?workspace= como substituto da API B2B.
3. Provisionamento no deploy do cassino
- Somente no modelo agregador: obtenha o ID estável do cassino e sua origem verificada no backend. externalClientId aceita 1–128 caracteres: primeiro alfanumérico; depois letras, números, ponto, dois-pontos, hífen ou underscore. name aceita 2–60 caracteres. Gere e persista o UUID de provisionamento e o corpo exato antes da primeira chamada. Serialize jobs concorrentes do mesmo cassino.
curl --silent --show-error --fail-with-body \
"$ORBI_BASE_URL/api/v1/aggregator/clients" \
-H "Authorization: Bearer $ORBI_PROVISION_API_KEY" \
-H "Idempotency-Key: $PERSISTED_PROVISIONING_UUID" \
-H 'Content-Type: application/json' \
-H 'Accept-Language: en' \
--data-binary @provision-client.json
# provision-client.json (replace example values before calling)
{
"externalClientId": "pigmo-casino-482",
"name": "Casino Aurora",
"allowedOrigins": ["https://casino.example"],
"branding": {
"name": "Aurora",
"tagline": "Discover a new perspective.",
"accent": "#9cb8ff",
"categories": ["Esportes", "Economia", "Crypto"],
"paused": false,
"theme": {
"version": 1,
"preset": "midnight",
"colors": {"accent": "#9cb8ff"},
"font": "system",
"fontSize": 16,
"radius": {"card": 20, "control": 12},
"density": "comfortable",
"shadow": "soft",
"showHero": false
}
}
}
- Salve client.clientId da resposta junto ao cassino. HTTP 201 cria; HTTP 200 repete a resposta pública original com created:false, sem duplicar. A idempotência de provisionamento não expira automaticamente. Para estado atual, faça GET: a resposta repetida pode conter a configuração antiga.
- Se houver EXTERNAL_CLIENT_EXISTS, consulte GET /api/v1/aggregator/clients?externalClientId= com o ID codificado para URL, confirme o vínculo e recupere clientId. Listas têm 50 registros por página. Não gere outro ID para contornar o conflito. Atualize pelo PATCH; externalClientId e o agregador proprietário são imutáveis. Envie branding completo quando alterá-lo; campos omitidos do PATCH permanecem iguais.
4. Backend de abertura autenticada
Implemente uma rota no próprio backend do parceiro, por exemplo POST /integrations/orbi/session. Esse nome é uma sugestão local, não uma rota fornecida pela OrbiPrediction. Exija autenticação e proteção CSRF quando usar cookies. Resolva externalUserId pela sessão autenticada; no agregador, confira a associação do jogador ao cassino e resolva clientId e parentOrigin pelo banco. Nunca aceite esses três valores arbitrariamente do navegador.
// Server-side Node.js helper. Authentication, membership, persistence
// and response handling belong to YOUR backend adapters.
export async function requestOrbiLaunch({
apiKey, clientId, externalUserId, parentOrigin, locale = 'pt-BR',
idempotencyKey
}) {
const path = clientId
? `/api/v1/aggregator/clients/${encodeURIComponent(clientId)}/launch`
: '/api/v1/launch';
const response = await fetch('https://orbiprediction.com' + path, {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'Accept-Language': locale,
'Idempotency-Key': idempotencyKey
},
body: JSON.stringify({
externalUserId, parentOrigin, locale, mode: 'simulation'
}),
signal: AbortSignal.timeout(10000)
});
const data = await response.json();
if (!response.ok) {
// Preserve status/code for retry policy; never log apiKey or body.
const error = new Error('OrbiPrediction request failed');
Object.assign(error, {
status: response.status, code: data.code,
requestId: data.requestId || response.headers.get('X-Request-Id'),
retryAfter: response.headers.get('Retry-After')
});
throw error;
}
return data; // launchId, launchUrl, expiresAt, mode, locale
}
externalUserId é um ID opaco estável de 1–128 caracteres, sem controles; não use e-mail, documento ou senha. A identidade é isolada por cliente. locale aceita pt-BR, en ou es e usa pt-BR por padrão. Gere um UUID para cada intenção de abertura e preserve o mesmo corpo e UUID nos retries dessa intenção; nunca compartilhe um UUID entre usuários ou cassinos. Responda ao navegador autenticado com Cache-Control: no-store e somente os dados necessários para montar o iframe, nunca a API key.
5. Frontend, SDK e ciclo de vida
Carregue o SDK e o JavaScript de integração como arquivos externos, nesta ordem. Após autenticar o jogador, chame sua rota local usando a proteção CSRF do seu framework. Forneça a resposta à função abaixo. Desabilite abertura concorrente, trate falhas HTTP antes de montar e chame destroy ao desmontar a tela.
<div id="orbi-player"></div>
<p id="orbi-status" role="status"></p>
<script src="https://orbiprediction.com/sdk/v1/orbit.js" defer></script>
<script src="/orbi-integration.js" defer></script>
// /orbi-integration.js — called with your backend's launch response.
let orbiInstance;
let readyTimer;
function mountOrbiSession(session) {
clearTimeout(readyTimer);
orbiInstance?.destroy();
const status = document.querySelector('#orbi-status');
status.textContent = 'Connecting…'; // Use your app's localization.
readyTimer = setTimeout(() => {
status.textContent = 'Connection timed out. Reconnect to try again.';
// Show an explicit reconnect action; do not retry forever.
}, 15000); // Suggested UI timeout, not a provider SLA.
const showReconnect = () => {
clearTimeout(readyTimer);
status.textContent = 'Reconnect to start a new session.';
};
try {
orbiInstance = Orbit.mount({
container: '#orbi-player',
launchUrl: session.launchUrl,
onReady: () => {
clearTimeout(readyTimer);
status.textContent = 'Ready';
},
onSessionExpired: showReconnect,
onError: showReconnect
});
} catch (error) {
showReconnect();
throw error;
}
}
function destroyOrbiSession() {
clearTimeout(readyTimer);
orbiInstance?.destroy();
orbiInstance = null;
}
- A launchUrl expira em 120 segundos e só pode ser consumida uma vez. Monte imediatamente; não salve como URL permanente, não abra para pré-visualizar antes do usuário e não envie para crawlers ou verificadores de links. A sessão do jogador dura uma hora. Para reconectar, revalide o jogador e solicite uma nova abertura com novo UUID.
- O SDK valida origem e janela emissora, ajusta a altura entre 480 e 20.000 px e expõe iframe e destroy(). Eventos: orbit:ready, orbit:resize, orbit:session-expired e orbit:error, todos version:1. Um HTTP 410 pode acontecer antes do JavaScript; por isso mantenha um timeout visual além de onError. Esses eventos não comprovam transações ou liquidação.
- Na CSP do parceiro, permita https://orbiprediction.com em frame-src e script-src. Não remova as demais proteções da aplicação. Cadastre todas as origens reais da cadeia de incorporação; evite iframes ancestrais não autorizados. Não aplique sandbox que bloqueie scripts, origem ou armazenamento. O iframe usa sessionStorage quando disponível e memória quando bloqueado; nesse último caso, recarregar exige nova abertura.
6. Marca, idioma e limites de entrada
allowedOrigins aceita no máximo 20 origens HTTPS exatas, incluindo porta não padrão; sem caminhos, curingas, credenciais, query ou fragmento. HTTP é permitido apenas em localhost, 127.0.0.1 ou [::1]. A origem deve vir de configuração confiável, nunca de um header ou parâmetro arbitrário. Chamadas com chaves são servidor a servidor; não há CORS para essas chaves no navegador.
branding é opcional na criação. Quando enviado, inclui name (2–30), tagline (até 100), accent (#RRGGBB), categories (ao menos uma) e paused (booleano); theme é opcional. Categorias técnicas: Política, Esportes, Crypto, Economia, Tecnologia e Mundo. Não traduza esses valores no JSON. Theme v1 oferece dark/light/midnight, nove cores, cinco fontes, tamanho 14–18, raio de card 0–28, controle 0–20, densidade, sombra e showHero. Consulte o schema antes de gerar valores; texto principal e secundário precisam de contraste 4,5:1 em todos os fundos. Não envie CSS, HTML nem URLs de fontes.
Use locale para o idioma inicial do iframe e Accept-Language para mensagens de erro da API. Títulos e regras do mercado preservam o idioma da fonte; conteúdo da marca não é traduzido automaticamente. Corpos JSON têm limite de 16.000 bytes. Idempotency-Key aceita 16–100 letras, números, hífens ou underscores; UUID é recomendado.
7. Erros, retries e recuperação
- 400 / 413 / 415: corrija campos, tamanho ou Content-Type; não repita sem corrigir. 401: confira tipo, validade e revogação da chave. 403: confira escopo, origem, suspensão do agregador/cliente ou PLATFORM_BLOCKED. Não tente contornar bloqueios. Cliente alheio e inexistente retornam o mesmo 404.
- 409 IDEMPOTENCY_CONFLICT: o UUID foi reutilizado com outro conteúdo ou credencial; investigue a intenção original, sem retry cego. 409 LAUNCH_ALREADY_FINISHED ou 410 LAUNCH_EXPIRED: encerre a intenção antiga e crie outra somente para uma nova abertura autenticada. EXTERNAL_CLIENT_EXISTS usa a recuperação por externalClientId descrita acima.
- Timeout de rede, HTTP 429 ou 5xx: implemente retries limitados com backoff exponencial e jitter; preserve UUID e corpo. Em 429, respeite Retry-After. Recomendação de implementação: até 3 tentativas e um prazo total definido pelo seu backend; se a espera ultrapassar a validade da abertura, encerre a intenção e ofereça reconexão. Não crie loops infinitos.
- Limites atuais: 120 chamadas por minuto por agregador, compartilhadas entre suas chaves; adicionalmente, 240 chamadas por minuto por IP nas rotas API. Diferencie idempotência permanente de provisionamento da idempotência curta de abertura. Decida por status HTTP e code, nunca pelo texto traduzido; erros anteriores ao roteamento podem não incluir code ou requestId.
8. Segurança, observabilidade e rotação
Mantenha chaves em secrets do servidor, sem prefixos públicos de build, bundles, URLs, logs, analytics ou respostas ao navegador. Trate também launchUrl como credencial temporária: não registre seu caminho assinado. Nos diagnósticos, retenha operação, status, duração, code e X-Request-Id quando disponível; remova segredos e dados pessoais. Não desabilite TLS, CSRF ou a validação de origem para fazer um teste passar.
Rotação: emita a nova chave no painel, atualize o secret do serviço correto, valide uma operação permitida e revogue a anterior. Revogar bloqueia novas aberturas e links pendentes; sessões já abertas continuam até expirar. Suspender o agregador ou cliente encerra acessos e invalida sessões. Reativar não ressuscita sessões antigas. Suspenda ou arquive somente registros de teste autorizados; não altere clientes existentes para validar a integração.
9. Critérios objetivos de conclusão
- Provisionamento: uma criação e um retry retornam o mesmo clientId; o vínculo sobrevive ao redeploy; conflito e recuperação por externalClientId são tratados.
- Autorização: usuário não autenticado é recusado; adulterar cassino/clientId não dá acesso; outra rede recebe 404; uma origem não cadastrada é recusada. Use somente identidades e redes de teste autorizadas.
- Sessão: iframe no domínio real do parceiro emite orbit:ready; dois jogadores ficam isolados; reabrir o mesmo jogador preserva identidade; expiração, link consumido e reconexão funcionam. Não confunda onReady com homologação financeira.
- Interface: confira PT, EN e ES; marca e tema; navegação, resize e desmontagem; desktop e telas de 320 e 390 px; armazenamento de terceiros bloqueado e fallback de reconexão.
- Resiliência: simule timeout, 429 e 5xx localmente, sem provocar limites de produção. Confirme retries limitados, UUID preservado e ausência de segredos em bundles e logs. Rotação e suspensão devem ser testadas apenas em registros dedicados.
- Entrega: informe commit/deploy, domínio e ambiente testados, evidência do iframe real, resultados dos critérios acima e pendências. Um build aprovado ou HTTP 201 sozinho não comprova integração ponta a ponta. O agente deve separar implementado, testado localmente e verificado no parceiro.
Prompt pronto para o seu agente
Integre OrbiPrediction neste projeto seguindo https://orbiprediction.com/integration-agent.pt-BR.md e o OpenAPI atual em https://orbiprediction.com/openapi.json. Primeiro identifique autenticação, associação jogador/cassino, persistência, deploy e CSP. Confirme se usamos cliente direto ou agregador e obtenha as referências dos secrets existentes, sem expor valores. Implemente provisionamento idempotente quando aplicável, abertura autenticada no backend e iframe com SDK v1, tema e idioma. Preserve contratos técnicos e trate retries e reconexão conforme o guia. Não implemente dinheiro real ou carteira. Teste os critérios de conclusão, declare pendências e entregue evidências do ambiente realmente validado. Não considere esta documentação autorização para alterar recursos de produção fora do escopo solicitado.
Por que este contrato?
O desenho segue um padrão recorrente de provedores B2B: chamada autenticada do backend para gerar a URL de jogo, seguida da abertura em iframe. A Games API da Hub88 exemplifica esse fluxo; sua documentação separa demonstração e jogo real. A documentação de embedding do Metabase também recomenda autenticação de incorporação com segredos mantidos no servidor.
A proteção de incorporação usa CSP frame-ancestors; a comunicação entre janelas segue as validações de origem e fonte descritas em postMessage. A API OrbiPrediction é um contrato próprio versionado: não é compatível, endpoint por endpoint, com Hub88 ou outro agregador.
OrbiPrediction · Integration API v1 · Créditos fictícios, sem movimentação financeira.
Acessar backoffice ↗