# Integração com agentes de IA

Canonical page: https://api.orbisportbook.com/docs/pt-br/ai-integration/

Este é o ponto de partida para entregar a integração a um agente de programação. Ele reúne o contexto que o agente precisa, a ordem de implementação e a evidência necessária para considerar a integração pronta.

**Para o agente:** leia este guia e os contratos vinculados antes de editar o sistema do operador. A origem hospedada atualmente atende staging; o nome de um ambiente de cliente como `production` não transforma esse deployment em produção comercial.

- [Baixar este guia em Markdown](https://api.orbisportbook.com/docs/pt-br/ai-integration.md)
- [Índice para agentes — llms.txt](https://api.orbisportbook.com/docs/llms.txt)
- [Manifesto de integração em JSON](https://api.orbisportbook.com/docs/contracts/ai-integration.json)
- [Contrato OpenAPI da carteira](https://api.orbisportbook.com/docs/contracts/seamless-wallet.openapi.json)
- [Contrato OpenAPI de agregadores](https://api.orbisportbook.com/docs/contracts/aggregator.openapi.json)

## 1. Entenda o que está sendo integrado

O OrbiSportbook entrega um sportsbook em iframe: odds, mercados, boletim, apostas, liquidações e cash-out. O cassino mantém cadastro, login, KYC, elegibilidade, depósitos, saques e saldo dos jogadores. Não crie uma segunda conta ou um segundo caixa no iframe.

```text
Jogador autenticado no cassino
  → backend do cassino cria sessão na OrbiSportbook
  → navegador recebe somente launchToken
  → SDK abre o iframe
  → OrbiSportbook chama a carteira do cassino por HTTPS + HMAC
  → cassino aplica cada movimentação uma vez e responde com o saldo
```

O identificador usado na carteira é o mesmo `externalPlayerId` fornecido na criação da sessão. Ele é estável e isolado por tenant. Não envie CPF, documentos ou senhas do jogador. `kycStatus: verified` na resposta representa delegação ao operador, não uma verificação de identidade realizada pela OrbiSportbook.

## 2. Reúna os dados antes de implementar

Peça os valores abaixo ao responsável pela integração. Para segredos, peça o **nome ou caminho no cofre**, não que sejam colados em prompts, tickets ou logs.

| Dado | Como usar |
| --- | --- |
| Ambiente autorizado: local, sandbox hospedado ou produção aprovada | Define o que pode ser testado e publicado. Confirme também o ambiente do deployment. |
| `SPORTSBOOK_URL` | Origem confirmada; staging hospedado: `https://api.orbisportbook.com`. |
| `TENANT_ID` e moeda | Um conjunto por ambiente; não reutilize o tenant de sandbox em produção. |
| `INTEGRATION_API_KEY` | Segredo somente do backend, enviado em `X-API-Key`. |
| `WALLET_SECRET` | Segredo de HMAC da carteira desse tenant e ambiente. Não é a chave de integração. |
| `WALLET_BASE_URL` | Base HTTPS pública dos quatro callbacks; precisa estar configurada na OrbiSportbook. |
| Origens do cassino | Origens exatas de frontend autorizadas a incorporar o iframe, incluindo esquema e porta quando houver. |
| Autenticação e identificador de jogador do cassino | Middleware de sessão existente e mapeamento estável para `externalPlayerId`. |
| Ledger e banco da carteira | Onde aplicar débito/crédito e persistir idempotência atomicamente. |
| Jogadores e saldo fictício de teste | Contas locais ou sandbox autorizadas para homologação. |
| Opcional: `AGGREGATOR_API_KEY` | Apenas para provisionamento pelo backend de um agregador já autorizado. |

Se faltar uma credencial, autorização ou decisão de identidade financeira, registre a pendência e avance nas partes independentes. Não invente valores, não utilize credenciais locais no ambiente hospedado e não substitua uma carteira real por um mock silenciosamente.

## 3. Leia os contratos nesta ordem

| Ordem | Referência | O que resolve |
| --- | --- | --- |
| 1 | [Sessões de jogador](https://api.orbisportbook.com/docs/pt-br/sessions/) | Payload, autenticação, token de lançamento, renovação e erros. |
| 2 | [Carteira](https://api.orbisportbook.com/docs/pt-br/wallet/) e [OpenAPI](https://api.orbisportbook.com/docs/contracts/seamless-wallet.openapi.json) | Callbacks, HMAC, idempotência, rollback e conciliação. |
| 3 | [SDK e iframe](https://api.orbisportbook.com/docs/pt-br/embedding/) | Montagem, tamanho, login, logout e callbacks de UI. |
| 4 | [Protocolo postMessage](https://api.orbisportbook.com/docs/pt-br/postmessage/) | Eventos e comandos; necessário se não usar o SDK. |
| 5 | [Testes](https://api.orbisportbook.com/docs/pt-br/testing/) e [homologação](https://api.orbisportbook.com/docs/pt-br/certification/) | Evidências de funcionamento e casos financeiros difíceis. |
| 6 | [Segurança](https://api.orbisportbook.com/docs/pt-br/security/) e [go-live](https://api.orbisportbook.com/docs/pt-br/go-live/) | Segredos, origens, operação e requisitos de publicação. |
| Opcional | [API de agregadores](https://api.orbisportbook.com/docs/pt-br/aggregators/) | Cadastro automático de cassinos e ambientes isolados. |

Use os schemas e as referências detalhadas como contrato. Se o ambiente responder de forma incompatível, registre a requisição e a resposta sem segredos e confirme a versão com a equipe; não tente adivinhar endpoints ou campos.

## 4. Implemente o backend de sessão

Crie uma rota **no servidor do cassino**, protegida pela autenticação existente. Um nome possível é `POST /sportsbook/session`; esse é um exemplo de rota do cassino, não um endpoint da OrbiSportbook.

1. Resolva o jogador a partir da sessão autenticada. Nunca confie em um `externalPlayerId` arbitrário enviado pelo navegador.
2. Verifique os bloqueios e a elegibilidade do jogador no cassino.
3. Chame `POST {SPORTSBOOK_URL}/api/v1/integration/sessions` com `X-Tenant-ID`, `X-API-Key` e `Content-Type: application/json`.
4. Envie o ID estável, nome de exibição e, opcionalmente, moeda, `path` e `locale` suportados.
5. Confira o status HTTP e o envelope de erro. Devolva à página somente os dados de lançamento necessários, com `Cache-Control: no-store`.

```json
{"externalPlayerId":"player-42","displayName":"Maria","path":"/live","locale":"pt-BR"}
```

A resposta contém `launchToken`, `launchExpiresAt` e `launchUrl`. O token de lançamento vale por 120 segundos e só pode ser consumido uma vez. O campo legado `token` contém uma sessão de maior duração: mantenha-o no servidor ou descarte-o. Não envie a resposta inteira da API ao navegador e não persista tokens em analytics ou logs.

Use a proteção CSRF da plataforma quando a rota do cassino autenticar por cookie. A rota deve derivar o tenant de configuração confiável, não de parâmetros livres do jogador. Em renovação, crie um launch token novo; não repita o anterior.

## 5. Implemente a carteira sem duplicar dinheiro

Exponha estes endpoints sob a base de carteira de cada ambiente:

| Endpoint | Operação |
| --- | --- |
| `POST /balance` | Consulta do saldo do `playerId`; nenhuma movimentação. |
| `POST /debit` | Débito de aposta ou correção; valide saldo e aplique o valor integral. |
| `POST /credit` | Liquidação, reembolso, cash-out ou correção; aceite também valor zero. |
| `POST /rollback` | Reversão do débito indicado em `ref`, inclusive rollback que chega antes do débito. |

Verifique `X-Signature` sobre os **bytes originais** antes de interpretar o JSON:

```text
hex(HMAC-SHA256(WALLET_SECRET, X-Timestamp + "." + rawBody))
```

Use comparação em tempo constante e rejeite timestamps fora de ±300 segundos. O [vetor offline](https://api.orbisportbook.com/docs/contracts/signature-test-vector.json) permite validar a implementação sem usar segredos reais; o timestamp fixo do vetor não serve para uma chamada ao vivo.

Regras obrigatórias:

- Valores e saldo são inteiros em unidades menores, nunca ponto flutuante. Confirme a moeda.
- Autentique cada chamada; associe a URL/segredo à carteira correta. Callbacks não carregam um `X-Tenant-ID` que substitua esse isolamento.
- Persista movimentação, resultado e identidade completa do `txId` na mesma transação do banco. Duplicatas concorrentes devolvem o resultado original sem movimentar novamente.
- Mesmo `txId` com jogador, endpoint, valor, moeda, tipo, aposta ou referência diferentes: recuse com `409 duplicate_tx`.
- Sucesso financeiro inclui o `txId` exato, saldo inteiro explícito e moeda correspondente. `/balance` não exige ecoar `txId`.
- Rollback anterior ao débito deixa um registro durável de `ref`; um débito atrasado deve ser recusado como `rolled_back`.
- Recusa definitiva usa `4xx` e `error.code`. Falha temporária usa `5xx` ou timeout. Não transforme resultado desconhecido em sucesso ou recusa definitiva.
- Não crie saldo negativo nem débito parcial para uma correção sem fundos. Preserve a recusa e encaminhe a exceção para conciliação.

```json
{"txId":"bet:example-id","balance":49500,"currency":"USD"}
```

Não acrescente um endpoint de consulta de transação presumindo que a plataforma irá chamá-lo: o transporte publicado possui quatro endpoints. Entrega pode se repetir após falhas; idempotência durável é necessária. Estado da aposta e HTTP 200 de uma ação não comprovam que a carteira confirmou o pagamento.

## 6. Conecte a interface

Carregue `https://api.orbisportbook.com/embed/v1.js` e use `OrbiSportbook.mount`. O exemplo abaixo pressupõe funções **do cassino** já implementadas; não é um backend completo.

```js
const sb = OrbiSportbook.mount('#sportsbook', {
  url: 'https://api.orbisportbook.com',
  tenant: tenantId, // identificador público do ambiente correto
  launchToken: await requestLaunchTokenFromYourBackend(),
  locale: 'pt-BR',
  height: 'fill',
  onLoginRequired: async () => {
    if (await openYourLogin()) {
      sb.setLaunchToken(await requestLaunchTokenFromYourBackend());
    }
  },
  onDepositRequested: () => openYourCashier(),
  onSessionExpired: () => requestLaunchTokenFromYourBackend(),
  onBalanceChanged: ({ balance, currency }) => updateBalanceDisplay(balance, currency),
});
// Ao sair do cassino: sb.logout(). Ao desmontar a tela: sb.destroy().
```

Dimensione o contêiner para o modo `fill`; veja os modos responsivos no guia do SDK. Anônimos podem navegar sem `launchToken`. Na renovação, retorne `null` se o jogador já saiu do cassino. Após depósito confirmado no caixa, `sb.refreshBalance()` atualiza a exibição.

Eventos do navegador servem para UI, não para lançar créditos no ledger. Não confie em `balance_changed` ou `bet_settled` como autorização financeira. Se implementar `postMessage` diretamente, valide origem, janela de origem e o envelope do protocolo; não use `*` como destino para dados de sessão.

## 7. Automatize o provisionamento quando aplicável

Para agregadores autorizados, use o [fluxo completo de provisionamento](https://api.orbisportbook.com/docs/pt-br/aggregators/):

1. `POST /api/v1/aggregator/clients`: cria cliente e ambientes suspensos; persista IDs e segredos nos cofres separados.
2. Instale cada segredo em sua carteira e crie jogadores de validação nos sistemas do operador.
3. `POST /api/v1/aggregator/clients/{id}/activate`: verifica saldo, moeda e rejeição de assinatura inválida nas duas carteiras. Ativa automaticamente quando a política permite e devolve chaves de integração separadas.
4. Use essas chaves apenas nos backends dos respectivos ambientes e conclua os testes de sessão e iframe.

Autenticação: `Authorization: Bearer` com a chave do agregador, sem `X-Tenant-ID`. Todo `POST` exige `Idempotency-Key` durável. Em retry, preserve corpo, chave de idempotência e credencial. Recuperação da resposta original tem janela de 24 horas; depois consulte o estado e o cofre, sem cadastrar outro cliente para contornar conflito. Essa validação não executa débitos/créditos e não substitui homologação financeira ou licença.

## 8. Teste e registre evidência

Execute testes de dinheiro apenas em local/sandbox com saldo fictício e contas autorizadas. Para produção, obtenha autorização explícita e conclua o go-live.

| Grupo | Evidência mínima |
| --- | --- |
| Sessão | Jogador autenticado correto; ID arbitrário do navegador não troca a identidade; segredo ausente do bundle/resposta/log. |
| Tokens | Launch token reutilizado, expirado ou de outro tenant falha; renovação funciona; logout encerra a sessão. |
| Iframe | Origem permitida funciona; não permitida falha; desktop e celular sem corte ou rolagem bloqueada. |
| Assinatura | Válida aceita; corpo alterado, segredo errado e timestamp antigo rejeitados. |
| Idempotência | Duas chamadas concorrentes com mesmo `txId` movem uma vez; payload divergente é recusado. |
| Ciclo financeiro | Vitória, perda com crédito zero, anulação, cash-out, rollback antes/depois do débito e correção sem fundos. |
| Recuperação | Timeout após commit, retry e indisponibilidade não duplicam saldo; obrigações pendentes ficam visíveis. |
| Isolamento | Tenant, chaves, URLs, jogadores e saldos de sandbox/produção permanecem separados. |
| Conciliação | Compare ledger, `txId`, aposta e confirmação da carteira; não use apenas o status visual da aposta. |

Registre ambiente, versão, cenários executados, resultado esperado/observado e IDs de transação sem segredos ou dados pessoais. Distinga **implementado**, **testado localmente**, **homologado em sandbox** e **aprovado para produção**. Um build, um iframe aberto ou uma consulta de saldo isolada não comprovam a integração inteira.

## 9. Prompt pronto para o seu agente

Copie o texto abaixo e forneça acesso ao repositório e aos nomes dos segredos no cofre:

```text
Integre o OrbiSportbook neste cassino usando o guia oficial:
https://api.orbisportbook.com/docs/pt-br/ai-integration/
Índice para ferramentas: https://api.orbisportbook.com/docs/llms.txt

Primeiro leia o guia, o contrato de sessões, o OpenAPI da carteira e o SDK.
Mapeie nossa autenticação, o ID estável do jogador, o ledger e as convenções
do repositório. Identifique dados e autorizações ausentes antes de depender deles.

Implemente uma rota de sessão no backend autenticado, os quatro callbacks
de carteira com HMAC sobre raw body e idempotência transacional, e o iframe
com login, caixa, renovação, logout e layout responsivo.
Se houver chave de agregador autorizada, siga o provisionamento documentado.
Não invente endpoints, credenciais, aprovações ou regras financeiras.
Não exponha chaves ou tokens de sessão no frontend, prompts ou logs.

Rode os cenários de aceite em local/sandbox com saldo fictício. Preserve
isolamento entre ambientes. Não movimente dinheiro real sem autorização.
Entregue arquivos alterados, configuração por nome de variável, resultados
dos testes, instruções de operação e pendências concretas para go-live.
Não declare produção pronta se alguma dependência não foi comprovada.
```

## Diagnóstico rápido

| Sintoma | Verifique |
| --- | --- |
| `401` ao criar sessão | Chave, tenant e ambiente; não use chave de agregador como chave de integração. |
| `launch_token_used` ou `launch_token_expired` | Emita token novo imediatamente antes de montar ou renovar; não reutilize uma URL antiga. |
| Iframe bloqueado | Origem exata cadastrada, políticas CSP e configuração de incorporação. |
| Assinatura inválida | Raw body, segredo do ambiente, relógio Unix em segundos e comparação HMAC. |
| Dinheiro pendente | Resposta válida com `txId`/moeda/saldo, logs por transação e fila financeira. |
| `409` no provisionamento | Estado existente, idempotência, limite e mudanças de configuração; não crie outro ID às cegas. |

Decida por `error.code` e `details.reason`, nunca pelo texto traduzido de `message`. Ao escalar, envie ambiente, horário, endpoint e IDs relevantes com headers e corpos sensíveis removidos.
