프라이빗 테이블
자기 전용 라이브 홀덤 테이블을 정해진 시간 동안 비밀번호를 아는 플레이어만 앉는 프라이빗 테이블로 예약합니다. VIP 게임 · 이벤트 테이블 등에 씁니다.
| 메서드 | 경로 | 용도 |
|---|---|---|
| GET | /operator/v1/private-tables | 예약할 수 있는 테이블과 예약 목록 |
| POST | /operator/v1/private-tables | 예약 만들기 |
| DELETE | /operator/v1/private-tables/{private_id} | 예약 취소 |
독립운영 전용
독립운영(independent) 오퍼레이터만 쓸 수 있으며, 대상은 자기 전용 live_holdem 테이블뿐입니다. 알방식(prepaid) 오퍼레이터는 모든 요청이 403 PRIVATE_FORBIDDEN 입니다.
동작
예약 하나는 테이블 · 시작 시각 · 기간 · 비밀번호로 이뤄지며, 시각에 따라 상태가 바뀝니다.
상태 (status) | 기간 | 테이블 동작 |
|---|---|---|
reserved | 시작 5분 전까지 | 평소처럼 공개 테이블 |
standby | 시작 5분 전 ~ 시작 | 대기 — 새로 들어오는 플레이어는 비밀번호가 있어야 입장 |
active | 시작 ~ 끝 | 프라이빗 진행. 시작 시각에 진행 중이던 게임이 공개 게임의 마지막 판이 되고, 그 판이 끝나면 비밀번호 없이 앉아 있던 플레이어는 정산 후 테이블에서 내보냅니다 |
ended | 끝난 뒤 | 다시 공개 테이블 |
cancelled | 취소 뒤 | 진행 중이었다면 바로 공개 테이블로 돌아감 |
플레이어를 프라이빗 테이블로 보낼 때는 게임 실행 요청에 table_id 와 table_password 를 함께 보냅니다.
- 예약이 걸린 시간(시작 5분 전 ~ 끝)에 비밀번호가 틀리면 launch 가
PRIVATE_PASSWORD로 실패합니다. 같은 플레이어 · 테이블로 분당 5회를 넘게 시도하면RATE_LIMITED입니다. - 예약이 걸리지 않은 시간에는
table_password를 무시하고 공개 테이블로 들어갑니다.
예약 · 취소는 운영 중인 테이블에 바로 반영됩니다.
GET /operator/v1/private-tables
예약할 수 있는 테이블(자기 전용 · 운영 중인 live_holdem)과 예약 목록을 돌려줍니다. 예약 목록에는 끝 시각이 지난 지 24시간이 안 된 예약(아직 끝나지 않은 것 · 취소한 것 포함)이 시작 시각 최신순으로 최대 200건 담깁니다.
응답 예시
{
"tables": [
{
"table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
"name": "Live Hold'em VIP",
"names": { "en": "Live Hold'em VIP", "ko": "라이브 홀덤 VIP" },
"currency": "PHP",
"limits": { "sb": 5000, "bb": 10000, "ante": 0, "min_buy_in": 500000, "max_buy_in": 2000000 }
}
],
"reservations": [
{
"private_id": "prv_0199f4a0b1c27d3e8f4a5b6c7d8e9f0a",
"table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
"table_name": "Live Hold'em VIP",
"table_names": { "en": "Live Hold'em VIP", "ko": "라이브 홀덤 VIP" },
"currency": "PHP",
"limits": { "sb": 5000, "bb": 10000, "ante": 0, "min_buy_in": 500000, "max_buy_in": 2000000 },
"start": "2026-10-20T12:00:00Z",
"end": "2026-10-20T14:00:00Z",
"minutes": 120,
"password": "vip2026",
"status": "reserved",
"created_at": "2026-10-19T03:21:40.12Z"
}
],
"standby_minutes": 5,
"min_minutes": 30,
"max_minutes": 1440
}응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
tables[] | array | 예약할 수 있는 테이블: table_id · name · names(없으면 생략) · currency · limits(블라인드 · 앤티 · 바이인 범위, 최소 단위) |
reservations[] | array | 예약 목록 |
reservations[].private_id | string | 예약 ID(prv_…) |
reservations[].table_id · table_name · table_names · currency · limits | 예약한 테이블 | |
reservations[].start · end | 시각 | 시작 · 끝 시각 |
reservations[].minutes | int | 기간(분) — end − start |
reservations[].password | string | 입장 비밀번호 |
reservations[].status | string | reserved · standby · active · ended · cancelled (조회 시각 기준) |
reservations[].created_at · cancelled_at | 시각 | 만든 · 취소한 시각 (cancelled_at 은 취소한 예약만) |
standby_minutes | int | 대기 시작(시작 몇 분 전) — 5 |
min_minutes · max_minutes | int | 예약 기간 범위 — 30 · 1440 |
status 는 시각으로 계산합니다. 시작 시각이 지나도 공개 게임의 마지막 판이 끝날 때까지는 실제 테이블이 아직 대기 상태일 수 있지만, 목록에는 active 로 보입니다.
TIP
응답에 비밀번호가 그대로 실립니다. 관리자 화면에서만 보여 주세요.
오류
| HTTP | 코드 | 상황 |
|---|---|---|
| 403 | PRIVATE_FORBIDDEN | 알방식 오퍼레이터 |
| 500 | INTERNAL_ERROR | 일시적인 서버 오류 |
POST /operator/v1/private-tables
예약을 만듭니다.
요청 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
table_id | string | 예 | 자기 전용 · 운영 중인 live_holdem 테이블 |
start | string (RFC 3339) | 예 | 시작 시각. 초 이하는 버리고 분 단위로 맞춥니다. 지금부터 30일 뒤까지 |
minutes | int | 예 | 기간(분). 30 ~ 1440, 30 의 배수 |
password | string | 예 | 4 ~ 20자, 공백 · 탭 · 줄바꿈 불가 (앞뒤 공백은 지움) |
start가 이미 지났으면 지금 바로 시작합니다. 이때 끝 시각은 요청한start + minutes그대로이므로 실제 기간은 그만큼 짧아집니다. 끝 시각이 지금부터 1분 이내이면start오류입니다.- 같은 테이블의 다른 예약(취소되지 않은 것)과 시간이 겹치면
409 PRIVATE_OVERLAP입니다.
요청 예시
curl -X POST {API_BASE}/operator/v1/private-tables \
-H 'Content-Type: application/json; charset=utf-8' \
-H 'X-Operator: acme' -H 'X-Api-Key: ak_live_…' \
-H 'X-Timestamp: 1760839200123' -H 'X-Nonce: 3f5a7c9e1b3d5f7a9c1e3b5d' -H 'X-Signature: a4e2…' \
-d '{"table_id":"tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d","start":"2026-10-20T20:00:00+08:00","minutes":120,"password":"vip2026"}'응답 예시
200 OK
{
"private_id": "prv_0199f4a0b1c27d3e8f4a5b6c7d8e9f0a",
"table_id": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
"start": "2026-10-20T20:00:00+08:00",
"end": "2026-10-20T22:00:00+08:00",
"status": "reserved"
}오류
| HTTP | 코드 | 상황 |
|---|---|---|
| 403 | PRIVATE_FORBIDDEN | 알방식 오퍼레이터 |
| 400 | INVALID_REQUEST (message invalid json) | 본문이 JSON 이 아니거나 start 가 RFC 3339 가 아님 |
| 400 | INVALID_REQUEST (details.fields) | 잘못된 필드를 모두 담습니다 — table_id(형식 오류 · 없음 · 닫힘 · 다른 오퍼레이터 · live_holdem 아님), minutes, password, start(빠짐 · 끝이 1분 이내 · 30일 넘게 앞) |
| 409 | PRIVATE_OVERLAP | 같은 테이블의 다른 예약과 겹침 |
| 500 | INTERNAL_ERROR | 저장 실패 |
DELETE /operator/v1/private-tables/{private_id}
끝나지 않은 예약을 취소합니다. 진행 중(active)이면 바로 공개 테이블로 돌아갑니다. 본문은 없습니다(빈 본문 또는 {} 로 서명).
요청 예시
curl -X DELETE {API_BASE}/operator/v1/private-tables/prv_0199f4a0b1c27d3e8f4a5b6c7d8e9f0a \
-H 'X-Operator: acme' -H 'X-Api-Key: ak_live_…' \
-H 'X-Timestamp: 1760839200123' -H 'X-Nonce: 7c9e1b3d5f7a9c1e3b5d7f9a' -H 'X-Signature: 0f6b…'응답 예시
{ "private_id": "prv_0199f4a0b1c27d3e8f4a5b6c7d8e9f0a", "status": "cancelled" }취소도 감사 기록에 남으며 변경 이력에서 되돌릴 수 있습니다(응답 헤더 X-Audit-Id).
오류
| HTTP | 코드 | 상황 |
|---|---|---|
| 403 | PRIVATE_FORBIDDEN | 알방식 오퍼레이터 |
| 404 | NOT_FOUND | 형식이 틀린 ID, 없는 예약, 다른 오퍼레이터의 예약 |
| 409 | PRIVATE_ENDED | 이미 끝났거나 취소된 예약 |
| 500 | INTERNAL_ERROR | 취소 실패 |