Skip to content

라운드 · 거래 · 리포트 ​

게임 기록과 돈의 흐름을 조회하는 API 입니다. 플레이어 베팅 내역 화면, 관리자 라운드 조회, 지갑 원장 대사(reconciliation), 일별 GGR 집계에 씁니다.

메서드경로용도
GET/operator/v1/rounds플레이어별 라운드 목록
GET/operator/v1/rounds/{round_id}라운드 상세 (플레이어 시점 · 회차 전체)
GET/operator/v1/sessions/{session_id}바이인형 테이블 착석 1회(테이블 세션) 상세
GET/operator/v1/transactions지갑 거래 원장 (대사용)
GET/operator/v1/reports/ggr일 · 게임별 GGR 집계

모든 요청은 인증 · 서명 규칙대로 서명합니다. GET 요청은 본문 없이 빈 문자열로 서명합니다.

공통 조회 파라미터 ​

목록 API 는 기간 · 페이지 크기 파라미터를 같은 방식으로 읽습니다.

파라미터형식설명
fromRFC 3339 (2026-10-18T00:00:00Z) 또는 YYYY-MM-DD구간 시작(포함). 생략하면 to 의 24시간 전
toRFC 3339 또는 YYYY-MM-DD구간 끝(제외). 생략하면 지금(UTC)
limit정수한 페이지 행 수. 기본 100, 최대 500 (500 보다 크면 500)
  • YYYY-MM-DD 는 그 날짜 UTC 0시입니다. 다른 시간대의 하루를 조회하려면 오프셋을 붙인 RFC 3339 로 보냅니다(예: 2026-10-18T00:00:00+08:00).
  • 형식이 잘못된 from · to 는 오류 없이 기본값(최근 24시간) 으로 바뀝니다. 결과가 예상과 다르면 먼저 파라미터 인코딩을 확인하세요.
  • 쿼리 값은 퍼센트 인코딩해서 보내고, 보낸 문자열 그대로 서명합니다. 특히 +08:00 의 + 는 반드시 %2B 로 인코딩해야 합니다. 인코딩하지 않으면 + 가 공백으로 읽혀 날짜 파싱이 실패하고 기본값이 적용됩니다. UTC(Z)로 보내면 이 문제를 피할 수 있습니다.

연습 게임은 기록되지 않습니다

플레이어가 혼자 앉아 컴퓨터와 하는 연습 게임처럼 실제 돈이 오가지 않는 판은 라운드 · 거래 기록에 남지 않습니다.

GET /operator/v1/rounds ​

이 오퍼레이터 플레이어가 참여한 라운드를 플레이어 × 라운드 한 행씩 돌려줍니다. 한 판에 우리 플레이어가 세 명 있으면 세 행입니다. 정산(settled)되거나 무효(void) 처리된 판만 나오며, 진행 중인 판은 끝난 뒤에 나타납니다.

쿼리 파라미터 ​

파라미터타입필수설명
from · to시각아니오라운드 시작 시각 기준 구간 [from, to). sort=settled_at 이어도 구간은 시작 시각으로 거릅니다
external_idstring아니오이 플레이어의 라운드만
game_codestring아니오이 게임의 라운드만 (게임 코드)
sortstarted_at | settled_at아니오정렬 기준. 기본 started_at
orderdesc | asc아니오정렬 방향. 기본 desc(최신순)
limit정수아니오기본 100, 최대 500
cursorstring아니오직전 응답의 next_cursor

요청 예시 ​

http
GET /operator/v1/rounds?external_id=user_1001&from=2026-10-18T00:00:00Z&to=2026-10-19T00:00:00Z&limit=100 HTTP/1.1
Host: {API_HOST}
X-Operator: acme
X-Api-Key: ak_live_…
X-Timestamp: 1760839200123
X-Nonce: 9f2c4e1a7b3d5e6f8a9b0c1d
X-Signature: 3b6f…

응답 예시 ​

json
{
  "rounds": [
    {
      "round_id": "rnd_0199f3a2c4e57b1d9a2e4f6081c3d5e7",
      "game_code": "live_holdem",
      "table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
      "started_at": "2026-10-18T14:10:00.123456Z",
      "settled_at": "2026-10-18T14:11:03.5Z",
      "status": "settled",
      "external_id": "user_1001",
      "bet": 12000,
      "win": 30400,
      "rake": 600,
      "currency": "PHP",
      "hand_no": 66,
      "table_name": "Live Hold'em 1",
      "table_names": { "en": "Live Hold'em 1", "ko": "라이브 홀덤 1" }
    }
  ],
  "next_cursor": "AZnzosTlex2aLk9ggcPV5wGZ86LE5XsdmiwvYIHD1ec"
}

응답 필드 ​

필드타입설명
round_idstring라운드 ID(rnd_…)
game_codestring게임 코드
table_idstring테이블 ID(tbl_…)
started_at · settled_at시각시작 · 정산(무효 처리) 시각
statusstringsettled(정산) · void(무효 — 베팅을 돌려준 판)
external_idstring플레이어
betint64이 판에 낸 금액 (베팅 · 블라인드 · 앤티 · 콜 등 합)
winint64이 판에서 받은 금액 (레이크를 뗀 뒤). 진 판은 0
rakeint64이 플레이어 몫으로 뗀 레이크 · 수수료
currencystring테이블 통화
hand_noint64테이블 안 판 번호
table_name · table_namesstring · object테이블 이름 · 언어별 이름
next_cursorstring | null다음 페이지 커서. 마지막 페이지면 null
  • 손익은 win − bet 입니다. 바이인형 게임(홀덤 등)은 판마다 지갑을 부르지 않으므로 이 값은 칩 기준 손익이고, 지갑 거래는 테이블 세션 단위(buy_in · top_up · cash_out)로 따로 납니다. → GET /sessions/{session_id}
  • 같은 판의 플레이어 행은 회차 ID → 플레이어 순으로 이어집니다.

페이지 넘기기 ​

next_cursor 를 같은 sort · order · 필터와 함께 cursor 로 넘깁니다. 커서는 불투명 문자열이므로 해석하거나 만들지 마세요. 한 페이지 행 수가 limit 보다 적으면 next_cursor 는 null 입니다(행 수가 정확히 limit 이면 다음 호출이 빈 목록일 수 있습니다).

sort=settled_at 으로 정렬하면 정산 시각이 없는 행은 가장 늦은 것으로 취급됩니다.

오류 ​

HTTP코드상황
500INTERNAL_ERROR일시적인 서버 오류 — 잠시 뒤 다시 시도

인증 · 서명 · 속도 제한 오류는 모든 엔드포인트에 공통입니다. → 오류 코드

GET /operator/v1/rounds/{round_id} ​

라운드 하나의 상세입니다. external_id 를 주는지에 따라 두 가지 보기가 있습니다.

보기요청용도담기는 것
플레이어 시점?external_id=user_1001사이트가 회원 본인에게 보여 주는 베팅 상세그 회원의 홀카드(cards.player), 베팅 요약(bets), 그 회원 몫 레이크, 그 회원 지갑 거래
회차 전체external_id 없음오퍼레이터 관리자 조회 · 분쟁 확인회차 머니(money), 진행 기록(history), 카드 흐름(hands), 독립운영 자기 테이블이면 딜러 카드 입력(card_log)

두 보기 모두 회차 머니(money)를 싣습니다.

경로 · 쿼리 파라미터 ​

파라미터타입필수설명
round_idstring (경로)예라운드 ID(rnd_…)
external_idstring (쿼리)아니오플레이어 시점으로 볼 플레이어. 그 플레이어가 이 판에 없으면 ROUND_NOT_FOUND

보이는 범위 ​

  • 이 오퍼레이터 플레이어가 한 명도 참여하지 않은 판은 404 ROUND_NOT_FOUND 입니다. 진행 중인 판도 아직 참가자 정산 기록이 없으므로 같은 오류가 납니다.
    • 예외: 독립운영 오퍼레이터의 자기 전용 테이블 판은 참가자가 없어도 회차 전체 보기(external_id 없이)로 열립니다(딜러 카드 입력 확인용). 이때 money 는 빈 모양입니다.
  • 공용 테이블에는 다른 오퍼레이터 플레이어가 함께 앉습니다. 그 플레이어는 좌석과 금액만 보이고 신원(external_id · 닉네임)과 공개되지 않은 홀카드는 보이지 않습니다.
  • 지갑 거래 · 베팅 항목은 이 오퍼레이터 플레이어 것만 담깁니다.

플레이어 시점 응답을 회원에게 그대로 전달하지 마세요

플레이어 시점(external_id) 응답에도 money 가 회차 전체 모양으로 실리며, 같은 판에 앉은 다른 회원의 external_id · 닉네임 · 금액과 그 회원들의 지갑 거래(money.transactions)가 들어 있습니다. 회원 화면에는 cards · bets · rake · transactions 처럼 본인 몫만 골라 보여 주세요.

요청 예시 ​

http
GET /operator/v1/rounds/rnd_0199f3a2c4e57b1d9a2e4f6081c3d5e7 HTTP/1.1
Host: {API_HOST}
X-Operator: acme
X-Api-Key: ak_live_…
X-Timestamp: 1760839200123
X-Nonce: 1c7d0e5b9a2f4c6e8d1b3a5f
X-Signature: 8e1a…

응답 — 최상위 필드 ​

필드타입설명
round_id · game_code · table_id · hand_no라운드 식별 정보
statusstringsettled · void (독립운영 자기 테이블 판은 진행 중이면 open 도 나옵니다)
started_at · settled_at시각시작 · 정산 시각
currencystring테이블 통화
resultobject | null게임 엔진의 판정 결과 원본. 게임마다 모양이 다릅니다(아래 result)
video_urlnull예약 필드. 현재 항상 null
moneyobject회차 머니 — 누가 얼마를 내고 받았는지 (money)
cardsobject{ "player": [...] } — 플레이어 시점일 때 그 회원의 최종 카드, 아니면 null
betsarray플레이어 시점일 때 [{ "spot": "hand", "amount": 낸 금액, "win": 받은 금액 }] 한 줄 요약, 아니면 []
rakeint64플레이어 시점이면 그 회원 몫, 아니면 판 전체 레이크(money.totals.rake)
transactionsarray플레이어 시점이면 그 회원의 지갑 거래, 아니면 money.transactions 와 같음
historyarray회차 전체 보기만. 진행 기록 (history)
handsarray회차 전체 보기만. 이 오퍼레이터 플레이어별 카드 흐름 (hands)
card_logarray회차 전체 보기 + 독립운영 자기 테이블 판만. 딜러 카드 입력 기록 (GET /dealer-card-log 의 entries 와 같은 모양)

플레이어 시점의 bets 는 게임과 관계없이 한 줄 요약입니다. 바카라 스팟별 · 블랙잭 박스별 베팅은 money.bets 에 있습니다.

money — 회차 머니 ​

필드타입설명
kindstringp2p(플레이어끼리 — 홀덤 · 오마하 · 라이브 홀덤 · 섯다 · 바둑이 · 맞고 · 고스톱 · 통잇) · banked(하우스 상대 — 스피드 홀덤 · 블랙잭 · 바카라 · 레드독)
currencystring통화
players[]array참가자별 합계 (아래 표)
pots[]array팟별 머니 이동. 홀덤 계열 · 섯다 · 바둑이만, 기록이 있는 판만 (없으면 필드 생략)
returns[]array콜 받지 못해 돌려준 초과 베팅 [{seat, external_id, amount}] (없으면 생략)
rake_ruleobject그 판에 적용된 레이크 규칙 (홀덤 계열, 없으면 생략)
rake_on_profitbooltrue 면 딜러비를 팟이 아니라 승자 순이익에서 뗍니다(섯다 · 바둑이). 이때 팟 shares 는 딜러비를 떼기 전 금액이고 실제 딜러비는 좌석별 rake 입니다
bets[]array이 오퍼레이터 플레이어의 베팅 항목 (뱅크형)
transactions[]array이 회차에 걸린 이 오퍼레이터 플레이어의 지갑 거래 (뱅크형. 바이인형 게임은 지갑 거래가 테이블 세션에 걸리므로 보통 빈 배열)
totalsobject합계

players[]

필드타입설명
external_idstring | null이 오퍼레이터 플레이어면 값, 다른 오퍼레이터 플레이어면 null
nicknamestring이 오퍼레이터 플레이어만 (없으면 생략)
seatint좌석 번호. 좌석이 없는 게임(바카라 등)은 -1
debitint64이 판에 낸 금액
creditint64이 판에 받은 금액 (레이크 뒤)
rakeint64이 사람 몫 레이크 · 수수료
netint64credit − debit
stack_before · stack_afterint64판 전 · 뒤 좌석 칩 (좌석 칩으로 치는 게임만 — P2P, 레드독)
minebool이 오퍼레이터 플레이어인지

bets[] — { external_id, spot, amount, win, status }. spot 은 바카라 player · banker · tie · player_pair · banker_pair · either_pair · perfect_pair · player_bonus · banker_bonus, 스피드 홀덤 · 블랙잭 box_N(블랙잭 추가 결정은 box_N:extra) 처럼 게임마다 다릅니다. win 은 받은 금액(원금 포함), status 는 settled · rolled_back.

transactions[] — { tx_id, external_id, type, reason, amount, status, balance_after, created_at, completed_at, ref_tx_id }. 각 필드 뜻은 GET /transactions 와 같습니다.

totals — { debit, credit, rake, house, balanced }

필드설명
debit · credit · rake참가자 전원(다른 오퍼레이터 포함)의 합
house하우스 쪽 손익 = debit − credit. P2P 는 레이크와 같습니다
balancedP2P 는 debit = credit + rake 이면 true(칩이 새지 않음). 뱅크형은 항상 true

pots[] (홀덤 계열 예)

필드설명
index0 = 메인 팟, 1~ = 사이드 팟
amount팟 총액
rake · rake_full · rake_cum실제로 뗀 레이크 · 비율대로라면 뗐을 레이크(상한 전) · 메인 팟부터 이 팟까지 누적
capped판당 최고 수수료(상한)에 닿아 덜 뗐는지
floored소수점 버림으로 덜 뗀 금액 (있을 때만)
eligible이 팟을 받을 자격이 있는 좌석
contributions[] · shares[]넣은 · 받은 좌석과 금액 {seat, external_id, amount} (다른 오퍼레이터 플레이어는 external_id: null)
rank이긴 족보 (있을 때만)
balanced넣은 합 = 팟 총액 = 받은 합 + 레이크

rake_rule — { percent, cap, no_flop_no_drop, floor?, skip? }. percent 는 bp(500 = 5%), cap 은 판당 최고 수수료(0 = 없음), skip 은 레이크를 떼지 않은 이유(off · no_flop).

history — 진행 기록 ​

판이 어떻게 진행됐는지를 시각순으로 펼친 목록입니다. 항목마다 ts 와 kind 가 있고, 나머지는 kind 에 따라 채워집니다(값이 없는 필드는 생략).

kind뜻주로 쓰는 필드
start판 시작no(판 번호) · seats[]({seat, player, chips}) · button · sb · bb · amount(앤티)
deal홀카드 배분seat · player · cards
card카드 한 장(라이브 딜러 입력 · 자동)position · cards · stage · source(scanner · wedge · manual · virtual · auto) · dealer · reason(거절 코드)
street다음 스트리트stage · board
betting베팅 열림 · 마감action(open · closed) · stage · amount
action플레이어 결정seat · player · action(fold · check · call · bet · raise · allin · hit · stand · go · stop …) · amount · total · pot · stack · auto(시간 초과 자동 결정)
bet · bet_undo뱅크형 베팅 · 베팅 취소player · amount · items[]({spot, amount, win, status})
showdown패 공개seat · player · cards · rank · best
result판정 · 분배pots[]({index, amount, rake, rank, winners[]}) · rake · board · outcome
tx지갑 거래player · action(debit · credit · rollback) · reason · amount · status
void무효reason
settle마지막 정산 (항상 마지막 줄)rows[]({seat, player, invested, won, rake, net, stack_after}) · amount · won · rake
event그 밖의 이벤트type · data
  • player 는 { "external_id", "nickname" } 이고, 다른 오퍼레이터 플레이어는 { "other": true } 입니다.
  • cards 의 원소가 null 이면 가린 카드입니다(다른 오퍼레이터 플레이어의 공개되지 않은 홀카드).
  • 딜러 이름(dealer)은 독립운영의 자기 테이블 판에서만 채워집니다.
  • 진행 기록은 화면 표시용입니다. kind 와 필드는 늘어날 수 있으니 모르는 값은 건너뛰도록 구현하세요. 돈 계산은 money 를 기준으로 합니다.

hands — 카드 흐름 ​

이 오퍼레이터 플레이어마다 처음 받은 카드 → 판 중 바꾼 · 버린 카드 → 판이 끝난 뒤 카드를 한 줄로 정리합니다. 좌석 순으로 정렬되며, 다른 오퍼레이터 플레이어는 빠집니다.

필드설명
seat · player좌석 · {external_id, nickname}
dealt처음 받은 카드 (홀덤 계열 홀카드, 바둑이 4장, 섯다 2장, 통잇 · 맞고 첫 손패)
steps[]판 중 손패 변화 {stage?, out, in} — out 버린(낸) 카드, in 받은 카드. 바둑이는 stage 가 교체 차례(draw_1 아침 · draw_2 점심 · draw_3 저녁)이고 바꾸지 않은 차례도 빈 배열로 남습니다
held판이 끝날 때 남은 손패 (final 과 다를 때만 — 맞고 · 고스톱)
final판이 끝난 뒤 카드 (맞고 · 고스톱은 먹은 패)
board공용 카드 (홀덤 계열)
best · rank패를 공개했을 때의 베스트 카드 · 족보

카드 표기는 트럼프 카드 2글자(AS · TD · 9H), 화투는 월 2자리 + 글자(01a · 05b)입니다.

예시 1 — 텍사스 홀덤 (P2P, 회차 전체 보기) ​

json
{
  "round_id": "rnd_0199f3a2c4e57b1d9a2e4f6081c3d5e7",
  "game_code": "holdem_nlh",
  "table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
  "hand_no": 66,
  "status": "settled",
  "started_at": "2026-10-18T14:10:00.123456Z",
  "settled_at": "2026-10-18T14:11:03.5Z",
  "currency": "PHP",
  "result": {
    "board": ["2C", "3D", "4H", "9S", "TC"],
    "awards": [{ "pot_index": 0, "seats": [3], "amount": 1520, "shares": [{ "seat": 3, "amount": 1520 }], "rake": 80, "rank": "two_pair", "best5": ["9S", "9D", "4H", "4C", "TC"] }],
    "rake": 80,
    "showdown": true,
    "pots": [ "…" ],
    "returns": [],
    "rake_rule": { "percent": 500, "cap": 0, "no_flop_no_drop": true }
  },
  "video_url": null,
  "money": {
    "kind": "p2p",
    "currency": "PHP",
    "players": [
      { "external_id": null, "seat": 3, "debit": 800, "credit": 1520, "rake": 40, "net": 720, "stack_before": 20000, "stack_after": 20720, "mine": false },
      { "external_id": "user_1001", "nickname": "lucky7", "seat": 4, "debit": 800, "credit": 0, "rake": 40, "net": -800, "stack_before": 32000, "stack_after": 31200, "mine": true }
    ],
    "pots": [
      {
        "index": 0, "amount": 1600, "rake": 80, "rake_full": 80, "rake_cum": 80, "capped": false,
        "eligible": [3, 4],
        "contributions": [ { "seat": 3, "external_id": null, "amount": 800 }, { "seat": 4, "external_id": "user_1001", "amount": 800 } ],
        "shares": [ { "seat": 3, "external_id": null, "amount": 1520 } ],
        "rank": "two_pair",
        "balanced": true
      }
    ],
    "rake_rule": { "percent": 500, "cap": 0, "no_flop_no_drop": true },
    "bets": [],
    "transactions": [],
    "totals": { "debit": 1600, "credit": 1520, "rake": 80, "house": 80, "balanced": true }
  },
  "cards": { "player": null },
  "bets": [],
  "rake": 80,
  "transactions": [],
  "history": [
    { "ts": "2026-10-18T14:10:00.2Z", "kind": "start", "type": "hand_start", "no": 66, "button": 3, "sb": 3, "bb": 4,
      "seats": [ { "seat": 3, "player": { "other": true }, "chips": 20000 }, { "seat": 4, "player": { "external_id": "user_1001", "nickname": "lucky7" }, "chips": 32000 } ] },
    { "ts": "2026-10-18T14:10:00.3Z", "kind": "deal", "seat": 3, "player": { "other": true }, "cards": [null, null] },
    { "ts": "2026-10-18T14:10:00.3Z", "kind": "deal", "seat": 4, "player": { "external_id": "user_1001", "nickname": "lucky7" }, "cards": ["AS", "KD"] },
    { "ts": "2026-10-18T14:10:05.1Z", "kind": "action", "type": "action", "seat": 3, "player": { "other": true }, "action": "call", "amount": 200, "pot": 400, "stack": 19800 },
    { "ts": "2026-10-18T14:10:09.8Z", "kind": "street", "stage": "flop", "board": ["2C", "3D", "4H"] },
    { "ts": "2026-10-18T14:11:02.9Z", "kind": "showdown", "seat": 3, "player": { "other": true }, "cards": ["9D", "4C"], "rank": "two_pair", "best": ["9S", "9D", "4H", "4C", "TC"] },
    { "ts": "2026-10-18T14:11:03.5Z", "kind": "settle", "amount": 1600, "won": 1520, "rake": 80,
      "rows": [ { "seat": 3, "player": { "other": true }, "invested": 800, "won": 1520, "rake": 40, "net": 720, "stack_after": 20720 },
                { "seat": 4, "player": { "external_id": "user_1001", "nickname": "lucky7" }, "invested": 800, "won": 0, "rake": 40, "net": -800, "stack_after": 31200 } ] }
  ],
  "hands": [
    { "seat": 4, "player": { "external_id": "user_1001", "nickname": "lucky7" },
      "dealt": ["AS", "KD"], "final": ["AS", "KD"], "board": ["2C", "3D", "4H", "9S", "TC"], "best": ["AS", "KD", "TC", "9S", "4H"], "rank": "high_card" }
  ]
}

같은 판을 ?external_id=user_1001 로 조회하면 history · hands 가 빠지고 다음 값이 바뀝니다.

json
{
  "cards": { "player": ["AS", "KD"] },
  "bets": [ { "spot": "hand", "amount": 800, "win": 0 } ],
  "rake": 40,
  "transactions": []
}

예시 2 — 라이브 바카라 (뱅크형) ​

뱅크형은 판마다 지갑이 움직이므로 money.bets 에 스팟별 베팅이, money.transactions 에 그 판의 debit · credit 이 담깁니다. pots 는 없습니다.

json
{
  "round_id": "rnd_0199f3b0aa127c3e8f45d6a7b8c9d0e1",
  "game_code": "live_baccarat",
  "status": "settled",
  "currency": "PHP",
  "result": {
    "winner": "banker",
    "player": { "cards": ["9H", "7C", "KD"], "total": 6, "natural": false, "pair": false, "perfect": false },
    "banker": { "cards": ["8S", "QH"], "total": 8, "natural": true, "pair": false, "perfect": false },
    "shoe_no": 12, "hand_no": 31,
    "winning_spots": ["banker"], "push_spots": [],
    "total_bet": 150000, "total_win": 97500, "players": 14,
    "winners": [ { "name": "lucky7", "amount": 9500 } ]
  },
  "money": {
    "kind": "banked",
    "currency": "PHP",
    "players": [
      { "external_id": "user_1001", "nickname": "lucky7", "seat": -1, "debit": 6000, "credit": 9500, "rake": 0, "net": 3500, "mine": true }
    ],
    "bets": [
      { "external_id": "user_1001", "spot": "banker", "amount": 5000, "win": 9500, "status": "settled" },
      { "external_id": "user_1001", "spot": "tie", "amount": 1000, "win": 0, "status": "settled" }
    ],
    "transactions": [
      { "tx_id": "tx_0199f3b0ab3c7d118e2f3a4b5c6d7e8f", "external_id": "user_1001", "type": "debit", "reason": "bet", "amount": 6000,
        "status": "ok", "balance_after": 1244000, "created_at": "2026-10-18T14:20:11.402Z", "completed_at": "2026-10-18T14:20:11.455Z", "ref_tx_id": null },
      { "tx_id": "tx_5c0e9a7d3b1f5e2a8c4d6b0f9e1a3c5d", "external_id": "user_1001", "type": "credit", "reason": "settle", "amount": 9500,
        "status": "ok", "balance_after": 1253500, "created_at": "2026-10-18T14:20:41.020Z", "completed_at": "2026-10-18T14:20:41.071Z", "ref_tx_id": null }
    ],
    "totals": { "debit": 6000, "credit": 9500, "rake": 0, "house": -3500, "balanced": true }
  }
}

(위 예시는 일부 필드를 줄였습니다.)

예시 3 — 게임별 hands ​

바둑이 — 세 번의 교체(steps)가 차례 이름과 함께 남습니다.

json
{ "seat": 2, "player": { "external_id": "user_1001", "nickname": "lucky7" },
  "dealt": ["AS", "2H", "KS", "QS"],
  "steps": [
    { "stage": "draw_1", "out": ["KS", "QS"], "in": ["3D", "QS"] },
    { "stage": "draw_2", "out": [], "in": [] },
    { "stage": "draw_3", "out": ["QS"], "in": ["4C"] }
  ],
  "final": ["AS", "2H", "3D", "4C"], "rank": "badugi" }

맞고 · 고스톱 — steps 는 낸 패, final 은 먹은 패, held 는 판이 끝날 때 손에 남은 패입니다.

json
{ "seat": 0, "player": { "external_id": "user_1001", "nickname": "lucky7" },
  "dealt": ["01a", "05b", "07c"],
  "steps": [ { "out": ["01a"], "in": [] } ],
  "held": ["05b", "07c"],
  "final": ["01a", "01b"] }

result — 게임 판정 원본 ​

result 는 게임 엔진이 판을 끝내며 남긴 판정 원본이라 게임마다 모양이 다르고 예고 없이 필드가 늘 수 있습니다. 화면에 판정을 보여 줄 때 참고하되, 금액 계산 · 대사에는 money 를 쓰세요.

게임주요 필드
홀덤 계열(holdem_nlh · holdem_plo4 · live_holdem)board · awards[]({pot_index, seats, amount, shares, rake, rank, best5}) · rake · showdown · pots · returns · rake_rule
바카라(live_baccarat)winner(player · banker · tie) · player · banker({cards, total, natural, pair, perfect}) · shoe_no · hand_no · winning_spots · push_spots · total_bet · total_win · players · winners[]({name, amount})
무효 판(모든 게임){ "void_reason": "…" }

오류 ​

HTTP코드상황
404ROUND_NOT_FOUND형식이 틀린 ID, 없는 라운드, 이 오퍼레이터 플레이어가 없는 판, 진행 중인 판, external_id 플레이어가 이 판에 없음
500INTERNAL_ERROR일시적인 서버 오류

GET /operator/v1/sessions/{session_id} ​

바이인형 게임(홀덤 · 오마하 · 라이브 홀덤 · 섯다 · 맞고 · 통잇 · 레드독 등)의 테이블 세션(한 번 앉아서 일어날 때까지) 상세입니다. 이 게임들은 판마다 지갑을 부르지 않고 착석(buy_in) · 충전(top_up) · 이석(cash_out) 때만 지갑 거래를 만들며, 그 거래의 round_id 가 테이블 세션 ID(tss_…)입니다. 이 API 는 세션 동안의 판별 손익을 모아 바이인 · 캐시아웃과 판별 손익이 맞는지를 보여 줍니다.

session_id 는 GET /transactions 의 round_id(값이 tss_ 로 시작), 또는 지갑 콜백 본문의 round_id 에서 얻습니다.

경로 파라미터 ​

파라미터타입필수설명
session_idstring예테이블 세션 ID(tss_…)

요청 예시 ​

bash
curl {API_BASE}/operator/v1/sessions/tss_0199f2e1d0c3b4a5968778695a4b3c2d \
  -H 'X-Operator: acme' -H 'X-Api-Key: ak_live_…' \
  -H 'X-Timestamp: 1760839200123' -H 'X-Nonce: 5e8f…' -H 'X-Signature: 0d4c…'

응답 예시 ​

json
{
  "session_id": "tss_0199f2e1d0c3b4a5968778695a4b3c2d",
  "external_id": "user_1001",
  "nickname": "lucky7",
  "table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
  "table_name": "Hold'em 2/4",
  "table_names": { "en": "Hold'em 2/4" },
  "game_code": "holdem_nlh",
  "currency": "PHP",
  "status": "closed",
  "opened_at": "2026-10-18T13:02:11.08Z",
  "closed_at": "2026-10-18T14:30:45.91Z",
  "buy_in_total": 960000,
  "cash_out": 302582,
  "chips": 0,
  "rounds": [
    { "round_id": "rnd_0199f3a2c4e57b1d9a2e4f6081c3d5e7", "hand_no": 68, "status": "settled",
      "started_at": "2026-10-18T13:05:00.1Z", "settled_at": "2026-10-18T13:06:12.4Z",
      "seat": 3, "debit": 324000, "credit": 944000, "rake": 8000, "net": 620000, "stack_after": 944000 }
  ],
  "transactions": [
    { "tx_id": "tx_7a1b2c3d4e5f60718293a4b5c6d7e8f9", "external_id": "user_1001", "type": "debit", "reason": "buy_in", "amount": 480000,
      "status": "ok", "balance_after": 1520000, "created_at": "2026-10-18T13:02:11.1Z", "completed_at": "2026-10-18T13:02:11.2Z", "ref_tx_id": null },
    { "tx_id": "tx_1f2e3d4c5b6a79880f1e2d3c4b5a6978", "external_id": "user_1001", "type": "credit", "reason": "cash_out", "amount": 302582,
      "status": "ok", "balance_after": 1342582, "created_at": "2026-10-18T14:30:45.9Z", "completed_at": "2026-10-18T14:30:46.0Z", "ref_tx_id": null }
  ],
  "totals": { "rounds": 15, "debit": 1997529, "credit": 1340111, "rake": 58319, "net": -657418 },
  "reconcile": { "paid_in": 960000, "paid_out": 302582, "unsettled": 0, "expected_end": 302582, "actual_end": 302582, "balanced": true, "closed": true }
}

응답 필드 ​

필드타입설명
session_id · external_id · nickname세션 · 플레이어
table_id · table_name · table_names · game_code · currency테이블 정보
statusstringopening(바이인 처리 중) · seated(앉아 있음) · kept(라이브 홀덤 — 자리를 비우고 칩을 맡겨 둔 상태) · closing(이석 처리 중) · closed(끝남)
opened_at · closed_at시각착석 · 이석 시각 (closed_at 은 끝나기 전 null)
buy_in_totalint64요청한 바이인 · 충전 합계. 지갑 차감이 실패한 요청 금액도 포함하므로 대사에는 reconcile.paid_in 을 쓰세요
cash_outint64 | null캐시아웃 금액 (끝나기 전 null)
chipsint64지금 좌석 칩 (끝난 세션은 보통 0)
rounds[]array세션 동안 참여한 판(시작 순, 최대 5,000판): round_id · hand_no · status · started_at · settled_at · seat · debit · credit · rake · net · stack_after
transactions[]array이 세션의 지갑 거래 (생성 순)
totalsobjectrounds(판 수) · debit · credit · rake · net 합
reconcileobject세션 대사 결과 (아래)

reconcile

필드설명
paid_in실제로 지갑에서 들어온 돈 = 성공한 debit(바이인 · 충전) − 그 debit 의 성공한 rollback
paid_out지갑으로 나간 돈 = 캐시아웃 credit 합 (실패가 아닌 것)
unsettled아직 끝나지 않은(pending · uncertain) credit · rollback 수
expected_endpaid_in + Σcredit − Σdebit — 판별 손익으로 계산한 끝 금액
actual_end끝난 세션은 paid_out, 열린 세션은 지금 chips
balancedexpected_end = actual_end 이고 unsettled = 0 이면 true
closed캐시아웃까지 끝났는지

balanced: false 이면서 unsettled > 0 이면 캐시아웃 credit 이 아직 재시도 중이라는 뜻입니다. 잠시 뒤 다시 조회하세요.

오류 ​

HTTP코드상황
404SESSION_NOT_FOUND형식이 틀린 ID, 없는 세션, 다른 오퍼레이터의 세션
500INTERNAL_ERROR일시적인 서버 오류

GET /operator/v1/transactions ​

플랫폼이 이 오퍼레이터 지갑으로 보낸 debit · credit · rollback 거래 원장입니다(balance 조회는 기록하지 않습니다). 오퍼레이터 지갑 원장과 tx_id 로 맞춰 보는 대사에 씁니다.

쿼리 파라미터 ​

파라미터타입필수설명
from · to시각아니오플랫폼이 거래를 만든 시각(created_at) 기준 [from, to). 기본 최근 24시간
statusok | failed | pending | uncertain아니오이 상태만
typedebit | credit | rollback아니오이 종류만
external_idstring아니오이 플레이어만
limit정수아니오기본 100, 최대 500
cursorstring아니오직전 응답의 next_cursor

요청 예시 ​

http
GET /operator/v1/transactions?from=2026-10-18T00:00:00Z&to=2026-10-19T00:00:00Z&limit=500 HTTP/1.1
Host: {API_HOST}
X-Operator: acme
X-Api-Key: ak_live_…
X-Timestamp: 1760839200123
X-Nonce: 2b4d6f8a0c1e3a5b7d9f1a3c
X-Signature: c71e…

응답 예시 ​

json
{
  "transactions": [
    {
      "tx_id": "tx_0199f3b0ab3c7d118e2f3a4b5c6d7e8f",
      "type": "debit",
      "ref_tx_id": null,
      "external_id": "user_1001",
      "amount": 6000,
      "currency": "PHP",
      "reason": "bet",
      "round_id": "rnd_0199f3b0aa127c3e8f45d6a7b8c9d0e1",
      "game_code": "live_baccarat",
      "table_id": "tbl_0198d2e3f4a57b6c9d0e1f2a3b4c5d6e",
      "status": "ok",
      "operator_tx_id": "w-1a2b3c4d5e6f",
      "balance_after": 1244000,
      "created_at": "2026-10-18T14:20:11.402Z",
      "completed_at": "2026-10-18T14:20:11.455Z"
    },
    {
      "tx_id": "tx_7a1b2c3d4e5f60718293a4b5c6d7e8f9",
      "type": "debit",
      "ref_tx_id": null,
      "external_id": "user_2002",
      "amount": 480000,
      "currency": "PHP",
      "reason": "buy_in",
      "round_id": "tss_0199f2e1d0c3b4a5968778695a4b3c2d",
      "game_code": "holdem_nlh",
      "table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
      "status": "ok",
      "operator_tx_id": "w-9f8e7d6c5b4a",
      "balance_after": 1520000,
      "created_at": "2026-10-18T13:02:11.1Z",
      "completed_at": "2026-10-18T13:02:11.2Z"
    }
  ],
  "next_cursor": "tx_7a1b2c3d4e5f60718293a4b5c6d7e8f9"
}

응답 필드 ​

필드타입설명
tx_idstring거래 ID(tx_…). 지갑 콜백 본문의 tx_id 와 같습니다
typestringdebit · credit · rollback
ref_tx_idstring | nullrollback 이 취소하는 debit 의 tx_id. 그 밖에는 null
external_idstring플레이어
amountint64금액 (통화 최소 단위, 0 이상)
currencystring통화
reasonstring사유 (buy_in · top_up · cash_out · bet · ante · double · split · settle · rollback 사유 등). 값 목록은 debit · credit · rollback 참고
round_idstring | null지갑 요청에 보낸 값 그대로 — 베팅형은 라운드(rnd_…), 바이인형은 테이블 세션(tss_…)
game_code · table_idstring | null지갑 요청에 보낸 값 그대로
statusstring아래 표
operator_tx_idstring | null지갑 응답에 오퍼레이터가 돌려준 operator_tx_id
balance_afterint64 | null지갑 응답의 balance (응답에 없었으면 null)
created_at시각플랫폼이 거래를 만든 시각 (첫 시도 직전)
completed_at시각 | null끝난 시각 (ok · failed · uncertain 이 된 때). 진행 중이면 null
next_cursorstring | null다음 페이지 커서. 마지막 페이지면 null

status

값뜻오퍼레이터 지갑에 반영돼 있어야 하는 상태
ok지갑이 OK 로 응답했습니다반영됨
faileddebit 이 거절됐습니다 — 지갑이 OK 가 아닌 status 를 돌려줬거나, 알방식에서 알이 모자라 지갑을 부르지 않고 실패 처리했습니다반영 안 됨 (호출 자체가 없었을 수 있음)
uncertaindebit 응답을 받지 못했습니다(시간 초과 · 연결 오류 · UNKNOWN_ERROR). 플랫폼은 곧바로 이 debit 을 ref_tx_id 로 하는 rollback 을 보냅니다debit 과 그 rollback 을 합쳐 순변화 0
pending처리 중이거나, credit · rollback 이 OK 를 받을 때까지 재시도 중입니다아직 확정 아님 — 나중에 다시 확인
  • credit · rollback 은 OK 를 받을 때까지 계속 재시도하므로 최종 상태는 ok 입니다. 오래 pending 으로 남는 credit · rollback 이 있으면 지갑 쪽 응답을 점검하세요. → 지갑 콜백 개요
  • 너무 오래 pending 에 머문 debit 은 플랫폼이 rollback 을 보내 정리합니다.

정렬과 페이지 넘기기 ​

  • 결과는 tx_id 내림차순입니다. 새 거래 ID 는 시간순으로 커지지만, 정산 credit · rollback 처럼 다른 거래에서 결정적으로 만든 ID 는 시간순이 아니므로 엄밀한 최신순이 아닙니다. 시각 순서가 필요하면 받은 뒤 created_at 으로 정렬하세요.
  • next_cursor 는 그 페이지 마지막 행의 tx_id 입니다. 같은 필터 · 같은 from · to 로 cursor 에 넘기면 그보다 작은 tx_id 부터 이어집니다. 구간이 고정돼 있으면 페이지 사이 누락 · 중복이 없습니다.
  • 행 수가 limit 보다 적으면 next_cursor 는 null 입니다(정확히 limit 이면 다음 호출이 빈 목록일 수 있습니다).
  • to 를 생략하면 "지금"이 호출마다 바뀝니다. 끝까지 받을 때는 from · to 를 고정하세요.

끝까지 받기 — 예시 코드 ​

ts
import { createHmac, randomBytes } from 'node:crypto';

const ORIGIN = '{API_BASE}';        // 환경별 주소 (온보딩 때 안내)
const OPERATOR = process.env.OPERATOR_CODE!;     // 예: acme
const API_KEY = process.env.OPERATOR_API_KEY!;
const API_SECRET = process.env.OPERATOR_API_SECRET!;

// 서명한 GET — path 는 쿼리까지 인코딩된 그대로 서명하고 그대로 보낸다
async function signedGet<T>(path: string): Promise<T> {
  const ts = String(Date.now());
  const nonce = randomBytes(12).toString('hex');
  const sig = createHmac('sha256', API_SECRET)
    .update(`${ts}\n${nonce}\nGET\n${path}\n`) // GET 은 본문 없음(빈 문자열)
    .digest('hex');
  const res = await fetch(ORIGIN + path, {
    headers: { 'X-Operator': OPERATOR, 'X-Api-Key': API_KEY, 'X-Timestamp': ts, 'X-Nonce': nonce, 'X-Signature': sig },
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return res.json() as Promise<T>;
}

type Tx = { tx_id: string; type: string; ref_tx_id: string | null; external_id: string; amount: number; status: string; created_at: string };

export async function fetchAllTransactions(from: string, to: string): Promise<Tx[]> {
  const all: Tx[] = [];
  let cursor: string | null = null;
  do {
    const q = new URLSearchParams({ from, to, limit: '500' }); // ':' → %3A 로 인코딩된다
    if (cursor) q.set('cursor', cursor);
    const page = await signedGet<{ transactions: Tx[]; next_cursor: string | null }>(`/operator/v1/transactions?${q}`);
    all.push(...page.transactions);
    cursor = page.next_cursor;
  } while (cursor);
  return all;
}

// 예: 어제 하루(UTC). to 는 현재보다 충분히 과거로 고정한다
const rows = await fetchAllTransactions('2026-10-18T00:00:00Z', '2026-10-19T00:00:00Z');
python
import hashlib, hmac, os, secrets, time
from urllib.parse import urlencode
import requests

ORIGIN = "{API_BASE}"
OPERATOR = os.environ["OPERATOR_CODE"]
API_KEY = os.environ["OPERATOR_API_KEY"]
API_SECRET = os.environ["OPERATOR_API_SECRET"]

def signed_get(path: str) -> dict:
    """path 는 쿼리까지 인코딩된 문자열 — 서명한 그대로 보낸다."""
    ts = str(int(time.time() * 1000))
    nonce = secrets.token_hex(12)
    msg = f"{ts}\n{nonce}\nGET\n{path}\n".encode()  # GET 은 본문 없음
    sig = hmac.new(API_SECRET.encode(), msg, hashlib.sha256).hexdigest()
    r = requests.get(ORIGIN + path, timeout=10, headers={
        "X-Operator": OPERATOR, "X-Api-Key": API_KEY,
        "X-Timestamp": ts, "X-Nonce": nonce, "X-Signature": sig,
    })
    r.raise_for_status()
    return r.json()

def fetch_all_transactions(frm: str, to: str) -> list[dict]:
    rows, cursor = [], None
    while True:
        params = {"from": frm, "to": to, "limit": 500}
        if cursor:
            params["cursor"] = cursor
        page = signed_get("/operator/v1/transactions?" + urlencode(params))
        rows.extend(page["transactions"])
        cursor = page["next_cursor"]
        if not cursor:
            return rows

rows = fetch_all_transactions("2026-10-18T00:00:00Z", "2026-10-19T00:00:00Z")

호출 수는 오퍼레이터당 초당 200건으로 제한됩니다. 대량으로 받을 때는 limit=500 으로 호출 수를 줄이세요.

오류 ​

HTTP코드상황
500INTERNAL_ERROR일시적인 서버 오류

형식이 틀린 cursor 는 오류 없이 무시되고 첫 페이지부터 돌려줍니다.

GET /operator/v1/reports/ggr ​

정산된 판을 날짜 × 게임별로 묶은 GGR(총 게임 수익) 집계입니다.

쿼리 파라미터 ​

파라미터타입필수설명
from · to시각아니오판의 정산 시각 기준 [from, to). 기본 최근 24시간
game_codestring아니오이 게임만
external_idstring아니오이 플레이어의 베팅 · 당첨 · 레이크만. 없는 플레이어면 빈 결과 { "currency": "", "rows": [] }

이 밖의 파라미터(묶음 기준 · 시간대 지정 등)는 지원하지 않으며 보내도 무시됩니다.

요청 예시 ​

http
GET /operator/v1/reports/ggr?from=2026-10-01T00:00:00Z&to=2026-10-19T00:00:00Z HTTP/1.1
Host: {API_HOST}
X-Operator: acme
X-Api-Key: ak_live_…
X-Timestamp: 1760839200123
X-Nonce: 7c9e1a3b5d7f9a1c3e5b7d9f
X-Signature: 52aa…

응답 예시 ​

json
{
  "currency": "PHP",
  "rows": [
    { "day": "2026-10-18", "game_code": "live_baccarat", "rounds": 640, "players": 57, "bet": 18250000, "win": 17310000, "rake": 0, "ggr": 940000 },
    { "day": "2026-10-18", "game_code": "live_holdem", "rounds": 1203, "players": 81, "bet": 0, "win": 0, "rake": 412000, "ggr": 412000 }
  ]
}

응답 필드 ​

필드타입설명
currencystring금액의 통화 (아래 주의 참고)
rows[].daystring날짜 YYYY-MM-DD — 정산 시각을 UTC 날짜로 끊습니다
rows[].game_codestring게임 코드
rows[].roundsint64판 수
rows[].playersint64참여한 플레이어 수 (그 날 · 그 게임 안에서 중복 제외)
rows[].bet · winint64뱅크형 게임의 베팅 합 · 지급 합. P2P 게임은 0
rows[].rakeint64P2P 게임에서 이 오퍼레이터 플레이어 몫으로 귀속된 레이크. 뱅크형은 0
rows[].ggrint64bet − win + rake
  • P2P 게임(홀덤 등)의 GGR 은 레이크입니다. 플레이어끼리 주고받은 칩은 GGR 에 들어가지 않습니다.
  • 뱅크형 게임(바카라 등)의 GGR 은 bet − win 입니다.
  • 행은 날짜 → 게임 코드 순입니다. 무효 판은 GGR 금액에 영향이 없지만, 게임에 따라 rounds · players 수에는 포함될 수 있습니다.

통화

모든 금액은 통화 최소 단위 정수입니다(예: PHP 는 센타보, 1250000 = ₱12,500.00). 자릿수는 GET /currencies 의 exponent 로 확인합니다.

응답의 currency 는 하나뿐이고 rows 에는 통화 칸이 없습니다. 내부적으로는 통화별로 따로 집계하므로, 두 가지 이상 통화의 테이블을 쓰는 오퍼레이터는 같은 날짜 · 게임 행이 통화별로 여러 번 나오지만 구분할 수 없습니다. 여러 통화를 쓴다면 통화별 수치는 GET /rounds(행마다 currency)로 직접 집계하세요.

오류 ​

HTTP코드상황
500INTERNAL_ERROR일시적인 서버 오류

대사(reconciliation) 방법 ​

플레이어 잔액의 원본은 오퍼레이터 지갑이므로, 플랫폼 원장(GET /transactions)과 오퍼레이터 지갑 원장이 거래 단위로 일치하는지 정기적으로 확인하는 것을 권장합니다. 두 원장의 공통 키는 tx_id 입니다.

준비 — 오퍼레이터 지갑 원장에 남길 것 ​

지갑 콜백(debit · credit · rollback)을 처리할 때 최소한 다음을 저장하세요.

항목이유
tx_id (고유 키)대사 키이자 멱등 처리 키
type · amount · currency · external_id금액 · 대상 비교
ref_tx_id (rollback)어떤 debit 을 취소했는지
round_id · reason원인 추적 (tss_… 면 GET /sessions 로 이어 볼 수 있음)
처리 결과 (반영 · 거절 · 무시)debit 을 거절했는지, rollback 대상이 없어 아무것도 안 했는지
응답한 operator_tx_id플랫폼 원장의 operator_tx_id 와 교차 확인

절차 ​

  1. 구간을 정합니다. 예: 어제 하루 [2026-10-18T00:00:00Z, 2026-10-19T00:00:00Z). to 는 최소 몇 분 이상 과거여야 진행 중인 거래가 끝난 상태로 나옵니다. 고정한 from · to 로 받으세요.
  2. 플랫폼 원장을 끝까지 받습니다. 위 예시 코드처럼 next_cursor 가 null 이 될 때까지 반복합니다.
  3. 같은 구간의 오퍼레이터 원장을 준비합니다. 플랫폼의 created_at 은 플랫폼이 거래를 만든 시각이고, 오퍼레이터가 요청을 받은 시각은 그보다 조금 늦거나(재시도 시) 많이 늦을 수 있습니다. 경계 누락을 막으려면 오퍼레이터 쪽은 구간 앞뒤로 여유(예: ±1시간)를 두고 뽑은 뒤, 플랫폼 행에 없는 것만 따로 확인합니다.
  4. tx_id 로 맞춥니다. 플랫폼 행마다 아래 규칙으로 판정합니다.
플랫폼 type / status오퍼레이터 원장의 정상 상태어긋나면
debit / ok같은 tx_id 로 같은 금액이 차감됨차감 기록이 없거나 금액이 다르면 이상 — 플랫폼은 칩 · 베팅을 내줬습니다
debit / failed차감 안 됨 (거절 기록만 있거나, 알 부족으로 호출 자체가 없어 기록이 없음)차감돼 있으면 플레이어 돈이 빠졌는데 게임에는 반영되지 않은 것 — 환불 필요
debit / uncertain차감됐든 안 됐든, 같은 debit 을 ref_tx_id 로 하는 rollback 까지 합쳐 순변화 0차감은 됐는데 rollback 이 반영되지 않았으면 이상
rollback / ok원 debit 을 차감했었다면 되돌림, 원 debit 을 받은 적이 없으면 아무것도 하지 않고 OK원 debit 이 차감된 채 남아 있으면 이상
credit / ok같은 tx_id 로 같은 금액이 입금됨 (금액 0 인 settle 도 기록)입금 기록이 없거나 금액이 다르면 이상
모든 종류 / pending아직 확정 아님다음 대사 때 다시 확인. credit · rollback 은 OK 를 받을 때까지 재시도되므로 지갑 응답 상태를 점검
  1. 반대 방향도 확인합니다. 오퍼레이터 원장에는 있는데 플랫폼 원장(넓은 구간 포함)에 없는 tx_id 는 다른 환경 · 다른 오퍼레이터 코드로 들어온 요청이거나 서명 검증을 거치지 않은 요청일 수 있으니 조사하세요.
  2. 합계를 검산합니다(선택). 플레이어별로 Σ(ok debit) − Σ(ok rollback 중 원 debit 이 ok 였던 것) − Σ(ok credit) 이 오퍼레이터 쪽 같은 계산과 같아야 합니다.

바이인형 게임 추가 확인 ​

홀덤 등 바이인형 게임은 판별 지갑 거래가 없으므로, 플레이어가 "칩이 사라졌다"고 문의하면 테이블 세션 단위로 확인합니다.

  1. 그 플레이어의 buy_in · top_up · cash_out 거래에서 round_id(tss_…)를 얻습니다.
  2. GET /sessions/{session_id} 의 reconcile.balanced 를 봅니다. true 면 바이인 + 판별 손익 = 캐시아웃이 맞습니다.
  3. 판별 내역은 rounds[] 의 각 round_id 로 라운드 상세를 조회합니다.

협의 사항

대사 주기, 불일치 발견 시 조정 절차 · 연락 창구는 계약 시 협의합니다.

문서 v1.0.0 · Operator API v1