API Reference · 룰렛·티켓

룰렛 추첨

사용자의 티켓 한 장으로 서버에서 당첨 칸을 결정하고 연결된 지급 경로를 처리합니다. 포인트 지급을 당첨 팝업의 '보상 받기' 시점으로 미룰 수도 있습니다.

POST/api/v1/contents/{content_id}/roulettes/{group_id}/spin

요청

  • Authorization: Bearer sess_* — 콘텐츠 세션 토큰.
  • content_id (path) — 토큰의 콘텐츠와 일치해야 합니다.
  • group_id (path) — 룰렛 그룹 UUID.
  • session_id (body, 필수) — 토큰의 세션 ID와 일치해야 합니다.
  • ticket_type_id (body, 필수) — 허용된 티켓 유형 UUID. 개별 티켓은 서버가 만료 임박 순으로 고릅니다.
  • idempotency_key (body 또는 Idempotency-Key 헤더, 필수) — 요청마다 고유한 문자열, 최대 128자. 둘 다 보내면 body가 우선합니다.
  • claim (body, 선택) — 포인트 지급 시점. "auto"는 추첨 응답 전에 지급합니다. "deferred"는 추첨·티켓 차감·결과 반환까지만 하고, 지급은 당첨 보상 받기 호출 때 합니다. 생략하면 "auto"(기존 즉시 지급)이며, 다른 값은 400입니다.
shell
curl -X POST \
  -H "Authorization: Bearer <session_token>" \
  -H "Content-Type: application/json" \
  -d '{"session_id":"<session_uuid>","ticket_type_id":"<ticket_type_uuid>","idempotency_key":"<unique_spin_key>","claim":"deferred"}' \
  "https://added-dev.blomics.net/api/v1/contents/<content_id>/roulettes/<group_id>/spin"

성공 응답

200 — reward.slot_id가 서버가 뽑은 칸입니다. remaining_tickets는 사용한 티켓 유형의 남은 수량입니다. duplicate: true는 같은 키로 다시 조회한 결과로, 티켓을 다시 소비하거나 재추첨하지 않았다는 뜻입니다. 아래는 즉시 지급(claim 생략 또는 "auto")의 예입니다.

json
{
  "draw_id": "<draw_uuid>",
  "roulette_group_id": "<group_uuid>",
  "roulette_id": "<roulette_uuid>",
  "roulette_version": 1,
  "ticket_id": "<consumed_ticket_uuid>",
  "reward": { "slot_id": "<slot_uuid>", "label": "100P", "display_order": 0,
    "reward_type": "point", "point": 100 },
  "event_log_id": "<event_log_uuid>",
  "postback_id": "<postback_uuid>",
  "delivery": "delivered",
  "delivery_code": null,
  "remaining_tickets": 2,
  "duplicate": false
}

postback_id와 event_log_id는 상황에 따라 null일 수 있습니다. delivery·delivery_code는 포스트백이 있을 때만 포함되며 delivery는 delivered·pending·failed 중 하나입니다. 내부 적립에는 balance_after가, 지급 안내가 필요한 경우 user_message가 포함될 수 있습니다. 당첨 칸 결과와 지급 완료 여부를 구분해서 표시하세요.

지연 지급 응답 (claim: "deferred")

포인트 당첨이면 claim_status: "unclaimed"가 붙고 아직 지급하지 않았으므로 postback_id는 null, delivery·delivery_code·balance_after는 없습니다. 티켓은 이미 차감됐고 당첨 기록(event_log_id)과 예산·한도 집계는 추첨 시점에 끝납니다. 당첨 팝업에서 사용자가 '보상 받기'를 누르면 draw_id로 당첨 보상 받기를 호출하세요.

json
{
  "draw_id": "<draw_uuid>",
  "roulette_group_id": "<group_uuid>",
  "roulette_id": "<roulette_uuid>",
  "roulette_version": 1,
  "ticket_id": "<consumed_ticket_uuid>",
  "reward": { "slot_id": "<slot_uuid>", "label": "100P", "display_order": 0,
    "reward_type": "point", "point": 100 },
  "event_log_id": "<event_log_uuid>",
  "postback_id": null,
  "remaining_tickets": 2,
  "duplicate": false,
  "claim_status": "unclaimed"
}
  • claim_status는 지연 지급으로 뽑은 포인트 당첨에만 있습니다. "unclaimed"는 '보상 받기' 전, "claimed"는 지급 처리가 끝났다는 뜻입니다. 즉시 지급 추첨에는 이 필드가 없습니다.
  • 꽝(0포인트)은 받을 것이 없으므로 claim: "deferred"여도 늘 즉시 완료되며 claim_status가 없습니다. 꽝에는 보상 받기를 호출하지 않아도 됩니다.
  • 지급 방식은 처음 추첨할 때 정해집니다. 같은 키로 재요청하면서 claim 값을 바꿔도 바뀌지 않으며, 미수령 당첨은 추첨 재요청으로 지급되지 않습니다(지급은 보상 받기에서만).
  • 사용자가 팝업을 닫거나 이탈해 보상 받기를 못 했으면 미수령으로 남습니다. 다음 진입 때 미수령 당첨 조회로 다시 안내하세요.
재시도와 화면 연출
네트워크 단절·시간 초과·서버 오류 후에는 새 키를 발급하지 말고 같은 idempotency_key로 재시도하세요. 이미 저장된 추첨이면 같은 칸을 돌려주고 미완료 지급을 이어갑니다(지연 지급 당첨은 claim_status: "unclaimed" 그대로 돌려줍니다). 해결 전 키를 보존하고 추첨 버튼을 중복 실행하지 마세요. 응답의 확률표 버전이 화면과 다르면 상세를 다시 조회한 뒤 결과를 표시하세요.

오류 처리

  • 400 INVALID_PARAM — 필수 값 누락·형식 오류, 허용되지 않은 claim 값.
  • 401 UNAUTHORIZED / SESSION_EXPIRED — 세션 인증 실패·만료.
  • 404 NOT_FOUND — 경로의 콘텐츠 또는 본문 세션 ID가 세션 토큰과 불일치합니다.
  • 409 ALREADY_EXISTS — 같은 멱등 키를 다른 룰렛 또는 티켓 유형에 재사용했습니다.
  • 499 NOT_FOUND — 룰렛·지급 경로·해당 유형의 이용 가능한 티켓이 없습니다.
  • 499 ROULETTE_UNAVAILABLE / ROULETTE_COMPLETED / TICKET_NOT_ACCEPTED — 운영 상태 또는 허용 티켓 조건 불일치.
  • 499 BUDGET_EXHAUSTED / CAMPAIGN_PAUSED / CAMPAIGN_EXPIRED / DAILY_LIMIT_EXCEEDED / USER_LIMIT_EXCEEDED / USER_BLOCKED — 지급 조건 거부. 지연 지급에서도 이 판정은 추첨 시점에 합니다.

당첨 전 거부에는 티켓을 소비하지 않거나 반환합니다. 응답을 받지 못한 경우에는 추첨 원장이 남았을 수 있으므로 반드시 같은 키로 결과를 확인하세요. 오류 본문은 공통 { code, message, data } 형식입니다.