# Integrate with AI agents

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

Give this guide to your coding agent together with access to your repository and the names of secrets in your vault. It defines the integration boundaries, implementation sequence and evidence required for delivery.

**For the agent:** read this guide and the linked contracts before editing the operator application. The currently hosted deployment is staging. A customer environment named `production` does not establish commercial production readiness.

- [Download this guide as Markdown](https://api.orbisportbook.com/docs/ai-integration.md)
- [Agent index — llms.txt](https://api.orbisportbook.com/docs/llms.txt)
- [Machine-readable integration manifest](https://api.orbisportbook.com/docs/contracts/ai-integration.json)
- [Wallet OpenAPI contract](https://api.orbisportbook.com/docs/contracts/seamless-wallet.openapi.json)
- [Aggregator OpenAPI contract](https://api.orbisportbook.com/docs/contracts/aggregator.openapi.json)

## 1. Understand the boundary

OrbiSportbook provides an iframe sportsbook: odds, markets, betslip, betting, settlement and cash-out. The casino owns registration, login, KYC, eligibility, deposits, withdrawals and player balances. Do not build a second player account or cashier inside the iframe.

```text
Authenticated casino player
  → casino backend creates an OrbiSportbook session
  → browser receives only a launchToken
  → embed SDK opens the iframe
  → OrbiSportbook calls the casino wallet over HTTPS + HMAC
  → casino applies each transaction once and returns the balance
```

Wallet `playerId` is the stable `externalPlayerId` supplied when creating a session, isolated by tenant. Do not send national IDs, identity documents or player passwords. A session response with `kycStatus: verified` records delegation to the operator; it is not identity verification performed by OrbiSportbook.

## 2. Obtain the required inputs

For credentials, request a **vault reference**, not secret values pasted into prompts, tickets or logs.

| Input | Purpose |
| --- | --- |
| Authorized target: local, hosted sandbox or approved production | Defines permitted testing and publication. Confirm the deployment environment too. |
| `SPORTSBOOK_URL` | Confirmed origin; hosted staging is `https://api.orbisportbook.com`. |
| `TENANT_ID` and currency | Separate values for each environment. |
| `INTEGRATION_API_KEY` | Backend-only credential sent as `X-API-Key`. |
| `WALLET_SECRET` | HMAC signing secret for this tenant/environment; different from the integration key. |
| `WALLET_BASE_URL` | Public HTTPS base for the four callbacks, configured in OrbiSportbook. |
| Casino frontend origins | Exact allowed embedding origins, including scheme and port when applicable. |
| Existing authentication and player ID | Casino session middleware and stable `externalPlayerId` mapping. |
| Wallet ledger and database | Where balance changes and idempotency results commit atomically. |
| Test players and fictitious balances | Authorized local/sandbox acceptance fixtures. |
| Optional `AGGREGATOR_API_KEY` | Only for backend provisioning by an already authorized aggregator. |

List missing credentials, authorizations and financial identity decisions explicitly. Continue independent work, but do not invent values, use local development keys against hosted services or silently replace a real wallet with a mock.

## 3. Read the contracts in order

| Order | Reference | What it defines |
| --- | --- | --- |
| 1 | [Player sessions](https://api.orbisportbook.com/docs/sessions/) | Authentication, payload, launch tokens, renewal and errors. |
| 2 | [Wallet API](https://api.orbisportbook.com/docs/wallet/) and [OpenAPI](https://api.orbisportbook.com/docs/contracts/seamless-wallet.openapi.json) | Callbacks, HMAC, idempotency, rollback and reconciliation. |
| 3 | [Embed SDK](https://api.orbisportbook.com/docs/embedding/) | Mounting, sizing, login, logout and UI callbacks. |
| 4 | [postMessage protocol](https://api.orbisportbook.com/docs/postmessage/) | Events and commands when implementing without the SDK. |
| 5 | [Testing](https://api.orbisportbook.com/docs/testing/) and [certification](https://api.orbisportbook.com/docs/certification/) | Acceptance evidence and financial edge cases. |
| 6 | [Security](https://api.orbisportbook.com/docs/security/) and [go-live](https://api.orbisportbook.com/docs/go-live/) | Secrets, origins, operation and release requirements. |
| Optional | [Aggregator API](https://api.orbisportbook.com/docs/aggregators/) | Automatic casino provisioning and isolated environments. |

Use schemas and detailed references as the contract. If the environment behaves differently, capture sanitized request/response evidence and confirm its version with the integration team. Do not guess endpoints or fields.

## 4. Implement the session backend

Create a route in the **casino server**, protected by existing player authentication. `POST /sportsbook/session` is one possible casino route name, not an OrbiSportbook endpoint.

1. Derive the player from the authenticated casino session. Do not trust a browser-supplied arbitrary player ID.
2. Check eligibility and restrictions in the casino.
3. Call `POST {SPORTSBOOK_URL}/api/v1/integration/sessions` with `X-Tenant-ID`, `X-API-Key` and `Content-Type: application/json`.
4. Send the stable player ID, display name and optional supported currency, path and locale.
5. Check HTTP status and the error envelope. Return only necessary launch data to the page with `Cache-Control: no-store`.

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

The response includes `launchToken`, `launchExpiresAt` and `launchUrl`. Launch tokens are single-use and valid for 120 seconds. The legacy `token` field is a longer-lived session: keep it server-side or discard it. Never forward the complete API response to the browser, or log tokens in analytics.

Use your platform's CSRF protection for cookie-authenticated routes. Resolve the tenant from trusted server configuration, not unrestricted player input. Renewal requires a new launch token, not reuse of the previous one.

## 5. Implement the wallet without duplicating money

Expose these endpoints under each environment's wallet base URL:

| Endpoint | Operation |
| --- | --- |
| `POST /balance` | Read the player's balance; no movement. |
| `POST /debit` | Bet or correction debit; validate funds and apply the full amount. |
| `POST /credit` | Settlement, refund, cash-out or correction; accept zero as well. |
| `POST /rollback` | Reverse the debit identified by `ref`, including rollback arriving before debit. |

Verify `X-Signature` against the **original bytes** before parsing JSON:

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

Use constant-time comparison and reject timestamps outside ±300 seconds. The [offline test vector](https://api.orbisportbook.com/docs/contracts/signature-test-vector.json) verifies your implementation without real secrets. Its fixed timestamp is not valid for a live request.

Mandatory behavior:

- Amounts and balances are integers in minor units, never floating point; validate currency.
- Authenticate every request and bind URL/secret to the correct wallet. Callbacks do not provide an `X-Tenant-ID` that replaces environment isolation.
- Commit movement, complete transaction identity and original result in one database transaction. Concurrent retries return that result without moving funds twice.
- A known `txId` with a different player, endpoint, amount, currency, kind, bet or reference returns `409 duplicate_tx`.
- Financial success must echo the exact `txId`, an explicit integer balance and matching currency. `/balance` need not echo `txId`.
- A rollback received before its debit records a durable `ref` tombstone; reject a late debit as `rolled_back`.
- Definitive rejection uses `4xx` with `error.code`; temporary failures use `5xx` or timeout. Do not turn an unknown outcome into success or definitive rejection.
- Do not partially debit or create a negative balance for an underfunded correction. Preserve the rejection and escalate for reconciliation.

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

The published transport has four endpoints; do not assume OrbiSportbook will call a transaction-status endpoint you invent. Network delivery may repeat after failures, requiring durable idempotency. A displayed bet result or HTTP 200 from a bet action does not prove that the wallet confirmed payment.

## 6. Connect the frontend

Load `https://api.orbisportbook.com/embed/v1.js` and call `OrbiSportbook.mount`. Functions below are **casino-side functions you must implement**, not supplied backend APIs.

```js
const sb = OrbiSportbook.mount('#sportsbook', {
  url: 'https://api.orbisportbook.com',
  tenant: tenantId,
  launchToken: await requestLaunchTokenFromYourBackend(),
  locale: 'en',
  height: 'fill',
  onLoginRequired: async () => {
    if (await openYourLogin()) {
      sb.setLaunchToken(await requestLaunchTokenFromYourBackend());
    }
  },
  onDepositRequested: () => openYourCashier(),
  onSessionExpired: () => requestLaunchTokenFromYourBackend(),
  onBalanceChanged: ({ balance, currency }) => updateBalanceDisplay(balance, currency),
});
// Casino logout: sb.logout(). Screen unmount: sb.destroy().
```

Size the container for `fill`; see the SDK guide for responsive modes. Anonymous visitors may browse without `launchToken`. Return `null` from renewal when the casino session has ended. After a confirmed cashier deposit, call `sb.refreshBalance()`.

Browser events drive UI, not ledger credits. Never treat `balance_changed` or `bet_settled` as financial authorization. Direct `postMessage` integrations must validate origin, source window and protocol envelope; do not use `*` as the target for session data.

## 7. Provision through an aggregator when applicable

For authorized aggregators, follow the [complete provisioning contract](https://api.orbisportbook.com/docs/aggregators/):

1. `POST /api/v1/aggregator/clients` creates a client and suspended environments; save IDs and secrets in separate vault entries.
2. Install each secret in its wallet and create validation players in the operator systems.
3. `POST /api/v1/aggregator/clients/{id}/activate` verifies balance, currency and rejection of invalid signatures in both wallets. When policy allows, it activates automatically and returns separate integration keys.
4. Store each key in its environment backend and complete session/iframe acceptance tests.

Use aggregator `Authorization: Bearer`, without `X-Tenant-ID`. Every POST requires a durable `Idempotency-Key`. Preserve body, idempotency key and API credential when retrying. Original response retrieval lasts 24 hours; afterward inspect client state and your vault rather than creating another client to bypass conflict. Activation performs no debit or credit and does not replace financial certification or licensing.

## 8. Test and retain evidence

Run financial tests only in local/sandbox with fictitious balances and authorized accounts. Production requires explicit authorization and go-live completion.

| Group | Minimum evidence |
| --- | --- |
| Sessions | Correct authenticated player; arbitrary browser IDs cannot impersonate; no secrets in bundles, responses or logs. |
| Tokens | Reused, expired and wrong-tenant launch tokens fail; renewal and logout work. |
| Iframe | Allowed origin works, unapproved origin fails; desktop/mobile layout and scrolling work. |
| Signatures | Valid request passes; changed body, wrong secret and stale timestamp fail. |
| Idempotency | Concurrent identical `txId` applies once; mismatched payload is rejected. |
| Financial lifecycle | Win, loss with zero credit, void, cash-out, rollback before/after debit and underfunded correction. |
| Recovery | Timeout after commit, retry and downtime do not duplicate funds; pending obligations remain observable. |
| Isolation | Sandbox/production tenant, keys, URLs, players and balances stay separate. |
| Reconciliation | Match ledger, `txId`, bet and wallet confirmation, not just the displayed bet status. |

Record environment, revision, executed scenarios, expected/observed results and sanitized transaction IDs. Distinguish **implemented**, **tested locally**, **certified in sandbox** and **approved for production**. A build, loaded iframe or isolated balance check does not establish complete readiness.

## 9. Copy-ready agent prompt

```text
Integrate OrbiSportbook into this casino using the official guide:
https://api.orbisportbook.com/docs/ai-integration/
Tool index: https://api.orbisportbook.com/docs/llms.txt

Read the guide, session contract, wallet OpenAPI and embed SDK first.
Map our authentication, stable player ID, ledger and repository conventions.
Identify missing inputs and authorizations before depending on them.

Implement an authenticated server-side session route, the four wallet
callbacks with raw-body HMAC and transactional idempotency, and an iframe
with login, cashier, renewal, logout and responsive sizing.
Use documented provisioning only if an authorized aggregator key exists.
Do not invent endpoints, credentials, approvals or financial rules.
Keep API keys and session tokens out of the frontend, prompts and logs.

Run acceptance scenarios locally/in sandbox with fictitious funds.
Keep environments isolated; do not move real money without authorization.
Deliver changed files, configuration variable names, test results,
operation instructions and concrete go-live blockers.
Do not claim production readiness for unverified dependencies.
```

## Quick diagnosis

| Symptom | Check |
| --- | --- |
| Session `401` | Correct key, tenant and environment; aggregator keys are not integration keys. |
| `launch_token_used` / `launch_token_expired` | Issue a fresh token immediately before mounting or renewing. |
| Blocked iframe | Exact registered origin, CSP and embedding configuration. |
| Invalid signature | Raw bytes, environment secret, Unix seconds and HMAC comparison. |
| Pending money | Valid response with `txId`/currency/balance, transaction logs and financial queue. |
| Provisioning `409` | Existing state, idempotency, quota or changed configuration; do not blindly create another ID. |

Branch on `error.code` and `details.reason`, never translated `message` text. Escalate with environment, timestamp, endpoint and relevant IDs, removing sensitive headers and body fields.
