The operator portal is the site's workspace for integration, finance, players and support. Access is limited by the site's identity and each staff member's permissions. This guide describes panel sessions; server API keys use a separate authentication flow.

## 1. Accounts and site provisioning
Provider administrators use `/admin/`; site staff use `/operator/`; players enter `/play/SITE_SLUG/` with a short-lived launch ticket created by the site's backend. These accounts, cookies and permissions are separate.

A provider administrator creates the site, configures allowed origins, games, buy-in limits, commission shares and wallet mode, then issues a server API key. Keys support read, launch, wallet and webhooks scopes, source-IP restrictions and expiry. The plaintext key is shown once; deliver it separately to the operator's backend secret store. Site staff can view key metadata with `keys.read` but cannot issue keys or change platform settings.

Staff accounts have an email, name, password, `tenantId` and permission list. Each account belongs to one site; staff emails are unique. Passwords are 12–128 characters. The initial password is set by the account manager and can be changed after login. Password, permission and activation changes revoke existing sessions. A paused site's permitted finance and support views remain available.

## 2. Panel sessions and two-factor authentication
The panel API base is `OPERATOR_ORIGIN`/operator-api. Browser requests use the panel origin; do not send server API keys to these routes.

```http Session routes
POST /operator-api/login
POST /operator-api/login/2fa
GET /operator-api/session
POST /operator-api/logout
POST /operator-api/password
```

Login accepts email and password. When 2FA is enrolled, the password response contains `mfaRequired` and a challenge; no panel session is granted until `POST /login/2fa` verifies challenge and code. A completed login/session response contains user, tenant, `csrfToken` and `expiresAt`. The user includes its current permissions.

The cookie is HttpOnly, SameSite=Strict and scoped to `/operator-api`; it is Secure when the operator origin uses HTTPS. Sessions last eight hours. Mutations require the configured Origin, Content-Type: application/json and the current session's `X-CSRF-Token`. Send cookies with same-origin credentials. Login and its 2FA challenge occur before a session exists and do not use a session CSRF token.

`POST /password` accepts `currentPassword` and password, then signs out all sessions. `X-Panel-Language`: en selects supported English validation messages; error codes remain stable. TOTP enrollment and recovery are described in ACCESS-SECURITY.en.txt. Each staff member enrolls their own authenticator.

## 3. Site data and reports
These routes return data for the site bound to the session. A query parameter cannot select another site. The corresponding read permission is required.

```http Read routes
GET /operator-api/dashboard?range=all
GET /operator-api/finance?range=month
GET /operator-api/players
GET /operator-api/rooms?status=running
GET /operator-api/keys
GET /operator-api/catalog
GET /operator-api/integrations
GET /operator-api/payouts
GET /operator-api/statement/export?format=csv&range=all
```

- range: all, month (last 30 days), week (last seven days), today. Day boundaries use Europe/Istanbul; timestamps are Unix milliseconds.
- status: all, waiting, running, completed, cancelled.
- Dashboard: scoped report, latest 12 rooms and open ticket count. Access requires `finance.read`, `rooms.read` and `tickets.read`.
- Players: up to 500 own-site players, including `availableBalance`, `lockedBalance` and online state.
- Rooms: latest 300 local/shared rooms involving the site. Other sites' private identities, member IDs, IP addresses and balances are not disclosed; opponents are pseudonymized per room.
- Keys: masked prefixes, scopes, IP restrictions, expiry and last use. Catalog: effective platform and site policy. These lists are bounded views, not unlimited historical archives.

## 4. Financial definitions
All money fields are integer TRY minor units: 20000 means 200.00 TRY. Do not send floating-point lira as `amountMinor`.

- `summary.operatorShare`: the site's accrued share of battle commissions.
- `summary.providerRevenue`: the provider share attributed to that site.
- `summary.providerNetProfit` and the retained `summary.netProfit` field: provider results, not operator profit.
- `summary.operatorNet`: `operatorShare` + site-assigned income − site-assigned expenses.
- `entryVolume`, `totalWinnings`, `paidPrizes`, refunds, `transferCredits` and `transferDebits` are separate measures; do not add them to commission revenue.

Manual adjustments are provider-entered bookkeeping records. Shared battles use the existing commission allocations and source wallets; the panel does not create another spendable balance. Wallet mode can be seamless or transfer; see SEAMLESS-WALLET.en.txt and API.en.txt.

`settlement.earnedOperatorShare` is the all-time accrued share. `reservedOperatorShare` includes pending and paid payments. `paidOperatorShare` and `pendingOperatorShare` track those states; `availableOperatorShare` is earned minus reserved, regardless of report period. A pending payment reserves the share; marking it paid does not deduct it again.

Payment records do not execute bank transfers. CSV includes summary shares, period adjustments and payments created in the period. Payment rows describe settlement cash flow, not another operational expense. The first column identifies the row type; do not sum all rows as profit. CSV values are quoted and leading spreadsheet formula characters are neutralized.

## 5. Support tickets
Ticket access requires `tickets.read`; creation, replies and status changes require `tickets.manage`. Staff can only access their assigned site's threads.

```http Support routes
GET /operator-api/tickets?status=all
POST /operator-api/tickets
GET /operator-api/tickets/TICKET_UUID
POST /operator-api/tickets/TICKET_UUID/replies
PATCH /operator-api/tickets/TICKET_UUID
```

```json Create ticket body
{
  "subject": "Launch issue",
  "category": "api",
  "priority": "normal",
  "message": "Describe the issue and non-secret reference IDs."
}
```

Categories: general, api, wallet, billing, game, other. Priorities: low, normal, high, urgent. Status: open, pending, resolved, closed. A site reply sets open; support replies set pending. Site staff can reopen or close a ticket; provider support can set any status. Reopen a closed ticket before replying.

```json Reply body
{
  "message": "Additional details"
}
```

```json Reopen ticket
{
  "status": "open"
}
```

```json Close ticket
{
  "status": "closed"
}
```

Subject length is 3–160 characters, opening message 3–5000, reply 1–5000. Lists contain the latest 300 tickets; a thread holds up to 500 messages. Attachments are not supported. List responses contain tickets; detail and mutation responses contain ticket and messages.

Support replies use the Support label without exposing a platform staff email. Threads persist across restarts. Actions are audited without storing passwords, session tokens or message contents in the audit event. Do not put secrets in a ticket.

## 6. Team, reviews and chat
Authorized site managers use `GET/POST /operator-api/team` and `PATCH /operator-api/team/USER_UUID`. Creation accepts name, email, password and permissions; edits accept name, password, active and permissions. Managers cannot grant permissions they lack, edit stronger accounts or remove the last active team manager. `team.read`/`team.manage` govern this area.

Room reviews use `reviews.read`/`reviews.manage`. Operators can review their own rooms; only provider staff can resolve a cross-site room fault. Refund decisions use the existing accounting and recovery flow. See ROOM-REVIEWS.en.txt. Chat access and moderation use `chat.read`/`chat.manage`; see CHAT-MODERATION.en.txt. Risk notification access uses `risk.read`/`risk.manage`; see FRAUD-RISK.en.txt.

Provider administrators manage site accounts under `/control/api/operator-users` and support under `/control/api/tickets`. These use the provider panel session and `sites.read`/`sites.manage` grants, not an operator cookie or server API key. Creating site staff never creates a platform administrator.

## 7. Integration test console and downloads
`POST /operator-api/integrations/test` requires the operator session, Origin, CSRF and `integrations.test`. It supports two request forms:

```json Catalog check
{"kind":"catalog"}
```

```json Launch configuration check
{
  "kind": "launch-contract",
  "origin": "https://site.example",
  "mode": "iframe",
  "route": "lobby"
}
```

The console sends a same-origin HTTP request. Catalog mode reads the effective site catalog (first 20 records and the full count). Launch-contract checks site state, maintenance, exact origin, mode/start route and whether an unexpired launch key is configured. It does not use that key, issue a ticket, create a player/room, move money or buy a bonus.

HTTP 200 means these checks passed; 422 indicates configuration needs attention. Input/session/verification/rate-limit failures use 400/401/403/429. The panel shows method, path, request/response JSON, status and elapsed time. Tests are limited to 12 per minute per account and audited. They do not validate the external server's API authentication/IP policy, actual embedding, wallet callbacks or game/audio/video playback.

`GET /operator-api/integrations/collection.json` downloads a site-specific Postman v2.1 collection with a blank API-key variable. Add the key only in a private secret environment. Read examples need read scope. Executing the separate launch example requires launch scope and creates a short-lived ticket; it may create/update a player. It does not transfer funds or create an isolated wallet sandbox.

## 8. Connect the site's backend
Use `PROVIDER_ORIGIN`/provider/v1 with a server API key. Derive `externalId` and `siteUsername` from the authenticated site member. `tenantId` + `externalId` maps to the same permanent player. Each browser opening gets its own short-lived launch response; never expose the API key.

README.en.txt contains the checked iframe/module setup examples. API.en.txt and `/sdk/openapi.json` describe routes and fields. IDENTITY-WALLET.en.txt covers stable identity; SEAMLESS-WALLET.en.txt describes the shared site balance. Transfer and seamless modes are different contracts.

The iframe helper exposes `onIdentity({player})` and `onWalletChange()`; the latter is only a change hint. Read the authoritative balance from the site's authenticated backend. Module integration supports `launchMethod`: POST and `launchCsrfToken` from the server. The legacy profile-selection example is not an authentication system.

## 9. Language and deployment
Panel interface language is Turkish or English, stored in ss-panel-locale. The documentation language is selected independently with ?lang=tr or ?lang=en; section links preserve that selection. Language changes do not translate user-generated ticket text or modify money, identifiers, permissions or game state.

Use HTTPS for deployed origins and keep operator, admin and public origin configuration separate. Local HTTP is allowed only for loopback development. RESULT-AUTHORITY.en.txt explains the current public-demo result boundary; panel checks do not replace real game/media, production wallet or network acceptance tests.

## Period battles — site reporting

Track daily, weekly and monthly entries in Operator / Period battles. Only your site's participants, private member identities, amounts and prizes are visible; ranks are computed across all sites. Staff require `rooms.read`, `players.read` and `finance.read`. From your backend use `GET /provider/v1/competitions?kind=daily&limit=50&offset=0` (`read` scope) or `client.competitions({kind: 'daily'})`. Currency is TRY and amounts are minor units. Paid and pending awards are separate. Follow pagination, event-context and package-update guidance in [PERIOD-WARS.en.txt](PERIOD-WARS.en.txt). Existing iframe integration remains valid; modules require the updated client ZIP.
