superplace 출입 API
매장 출입 제어를 위한 superplace 공개 API입니다.
빠른 시작
# 1) 키를 토큰으로 교환
curl -X POST https://api.superplace.so/core/v1/auth/apikey/token \
-H 'Content-Type: application/json' -d '{"key":"spk_live_…"}'
# 2) 출입 허가 등록 — 이 순간부터 전화·QR로 입장됩니다
curl -X POST https://api.superplace.so/space/v1/partner/entry-permits \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"externalRef":"member-1001","phone":"01012345678","name":"김회원",
"startsAt":"2026-09-03T00:00:00Z","endsAt":"2026-09-05T00:00:00Z"}'
두 호출이면 회원이 입장합니다.
기본
- 기본 주소:
https://api.superplace.so— 경로 앞머리가 서비스입니다:/core(인증·활동) ·/space(허가·회원권·예약) ·/device(문·보드) - 온보딩 때 두 세트를 받습니다: 테스트 매장
placeId+spk_test_키, 실매장placeId+spk_live_키
인증
POST/core/v1/auth/apikey/token — 키를 15분 토큰으로 교환하고, 모든 요청에 Authorization: Bearer {accessToken}을 전달합니다. 교환은 IP당 분당 30회.
→ {"success":true,"data":{"accessToken":"…","expiresIn":900,"placeId":"…"}}
placeId가 곧 매장 ID입니다 — 활동 기록 조회 등 경로에 매장 ID가 필요한 API에 이 값을 그대로 씁니다. 키가 매장에 묶여 있어 따로 물어볼 필요가 없습니다.
키에는 쓸 수 있는 범위가 담겨 있습니다. 발급 시 요청하신 범위대로 만들어 드리며, 범위 밖 호출은 403으로 거절됩니다.
| 범위 | 할 수 있는 것 |
|---|---|
| 손님과 출입 | 출입 허가 등록·조회·회수 · 출입 기록 · 출입 설정 · 회원권 · 예약 |
| 기기 제어 | 문 열기·잠그기·열어두기 (물리 개방) · 문 상태 · 시간대 정책 · 끊김 정책 |
테스트 매장
spk_test_ 키는 테스트 매장 전용입니다. 모의 응답이 아니라 실매장과 같은 서버·같은 로직으로 동작하며(허가·상태 전이·이력 전부 실기록), 실제 문과 연결되지 않습니다. 키가 매장에 묶여 있어 테스트 호출이 실매장 문을 여는 일은 없습니다.
- 테스트 매장에는 문이 등록되어 있어 문 열기·잠그기·열어두기·정책까지 전부 성공 응답으로 연습할 수 있습니다. 실행 결과는 출입 기록에도 그대로 남습니다.
- 전화 입장은 실매장에 050 출입 전화번호가 배정된 뒤 동작합니다 — 배정 여부는 출입 설정의
entryPhone으로 확인됩니다. - 실운영 전환은
spk_live_키로 바꾸기만 하면 됩니다 — 코드는 그대로입니다.
응답과 오류
성공: {"success":true,"data":…} 목록: {"success":true,"data":[…],"total":n}
실패: {"error":"코드","message":"설명","statusCode":숫자}
401 토큰 만료(재교환) · 403 스코프 없음 · 404 대상 없음 · 409 규칙 위반(message에 이유) · 429 요청 한도 · 502/503 매장 기기 오프라인(재시도)
입장 수단
허가를 등록하면 두 방법이 모두 동작합니다.
| 수단 | 동작 |
|---|---|
| 전화 | 등록된 번호로 매장 출입 전화번호(050)에 전화 → 발신번호 확인 → 개문. 번호는 출입 설정의 entryPhone. 안내물에는 tel:0507… QR로 인쇄하면 찍는 즉시 전화가 걸립니다. |
| 입장 링크 (QR) | 허가 응답의 url을 앱·문자·인쇄물에 QR로. 손님이 열면 문 버튼이 나타납니다. 링크가 곧 자격이므로 공개 채널에 올리지 마세요 — 회수하면 즉시 무효. |
출입 허가
POST/space/v1/partner/entry-permits
{"externalRef":"member-1001","phone":"01012345678","name":"김회원",
"startsAt":"2026-09-03T00:00:00Z","endsAt":"2026-09-05T00:00:00Z"}
→ {"success":true,"data":{"permitId":"…","entryToken":"…",
"url":"https://go.superplace.so/entry?t=…"}}
같은 externalRef 재호출은 기간 변경 + 회수 해제됩니다(멱등 — 같은 요청을 몇 번 보내도 결과가 한 번 보낸 것과 같습니다). 시간창은 한 건당 최대 720시간 — 장기 자격은 재등록 또는 회원권.
POST/space/v1/partner/entry-permits/revoke
{"externalRef":"member-1001"} 또는 {"permitId":"…"}
GET/space/v1/partner/entry-permits
쿼리: externalRef · limit(≤500) · offset. 파트너가 등록한 허가만 반환합니다.
→ data: [{"permitId":"…","externalRef":"member-1001","name":"김회원","phoneTail":"5678",
"state":"active", // active | pending | expired | revoked
"startsAt":"…","endsAt":"…","useCount":3,"firstUsedAt":"…","url":"…"}]
GET/space/v1/partner/entry-permits/{permitId}
문 기기 제어 범위
매장 기기 중 지금 API로 다루는 것은 출입문(doors)과 그 문을 여닫는 제어 보드(boards)입니다. 기기 종류는 계속 늘어납니다.
GET/device/v1/doors
doorState: locked · unlocked(열림 유지) · open(문짝 열림) · warning. online: 보드 통신 여부.
POST/device/v1/doors/{id}/open · /close · /hold
curl -X POST https://api.superplace.so/device/v1/doors/$DOOR/hold \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)" \
-d '{"minutes":60}' # minutes 생략 = 잠글 때까지 열어두기
Idempotency-Key 헤더 필수 — 요청마다 고유한 문자열(UUID 권장). 타임아웃 후 재전송할 때 같은 값을 다시 보내면 문이 두 번 열리지 않고 원래 결과를 돌려받습니다. open=잠깐 열림, hold=열어두기, close=잠그기. 모든 호출이 출입 기록에 남습니다.
문 시간대 정책 기기 제어 범위
GET · POST · DELETE/device/v1/doors/{id}/policies
POST {"window":{"ref":"business_hours"},"mode":"free"} # 영업시간 자유 개방
POST {"window":{"ref":"after_hours"},"mode":"auth"} # 그 외 인증 개문
mode: free | auth | closed window.ref: always | business_hours | after_hours | custom
free 시간대에는 자격 없이 열려 있습니다. 변경 후 문 상태 조회로 확인하세요.
인터넷 끊김 정책 기기 제어 범위
GET · PUT/device/v1/boards/{boardId}/netloss
PUT {"graceSec":45,"channels":{"1":"close"}}
# 값: open | close | hold | off — 끊김 graceSec초 뒤 보드가 스스로 실행
보드 온라인 여부: GET/device/v1/boards
출입 기록
GET/space/v1/partner/entry-logs
쿼리: sinceDays(≤30) · limit(≤500). 전화번호는 뒤 4자리만 반환되며, 조회는 열람 기록에 남습니다.
→ data: [{"doorId":"…","doorName":"현관","result":"opened","reason":"phone",
"actor":"guest:*5678","actorLabel":"김회원(*5678)","requestedAt":"…"}]
이벤트 단위 상세(entry.opened·entry.denied·entry.permit.used, 기간·결과 필터):
GET/core/v1/places/{placeId}/events — 문법은 API 레퍼런스.
출입 설정
GET/space/v1/partner/gate-config
→ {"phoneEnabled":true,"entryPermitMaxHours":720,"entryPhone":"0507…"}
entryPhone = 이 매장의 출입 전화번호. 미배정이면 필드가 없습니다.
회원권·예약
30일 초과 장기 자격은 회원권(기간 내 상시 입장), 시간 단위 이용은 예약. 둘 다 손님과 출입 범위의 키로 쓸 수 있습니다. 필드와 예시는 API 레퍼런스.
기존 시스템의 명부를 옮겨올 때는 일괄 반입(/space/v1/customers/import · /space/v1/memberships/import)을 쓰세요 — {"source":"어느 시스템", "items":[…]} 형식이고, 행마다 독립 처리라 같은 파일을 다시 올려도 중복이 생기지 않습니다.
오프라인 동작
- 허가 등록·회수는 최대 5분 안에 매장 장비로 동기화됩니다.
- 매장 인터넷이 끊긴 동안: 이미 동기화된 허가만 동작. 끊긴 뒤의 등록·회수는 복구 전까지 미반영.
- 끊김 36시간 초과 시 현장 판정 중단. 문은 끊김 정책대로 동작.
- 전화 판정은 서버에서 하므로 매장 회선과 무관하지만, 개문 명령 전달에는 매장 회선이 필요합니다.
판정 규칙
- 허가·회원권·예약은 병렬 — 하나라도 유효하면 열립니다. 회원권이 살아 있으면 허가를 회수해도 열립니다. 시간 제한 운영은 허가만 쓰세요.
- 허가에 이름이 있고 입력 경로에도 이름이 있으면 일치해야 합니다(전화 인증은 이름 생략).
mode:free시간대는 자격 판정 없이 개방 — 허가와 별개의 축입니다.
전체 명세 (OpenAPI)
- API 레퍼런스 — 전체 API를 브라우저에서 바로 실행해볼 수 있습니다(Try it out). Authorize 버튼에 교환한 액세스 토큰을 넣으면 이후 호출에 자동으로 붙습니다.
- 원문 스펙:
developers.superplace.so/openapi.yaml— OpenAPI 3.0. 클라이언트 코드 생성기에 그대로 쓸 수 있습니다.
변경 이력
| 날짜 | 내용 |
|---|---|
| 2026-09-03 | v2: 허가 목록·단건, 출입 기록, 출입 설정(entryPhone), 문 제어·시간대 정책·끊김 정책(기기 제어 범위 신설), spk_test_/spk_live_ 키 구분, developers.superplace.so 개설. 허가 url 도메인 go.superplace.so 통일(기존 링크 유효). |
| 2026-08-31 | 첫 공개: 허가 등록·회수, 회원권, 예약, 활동 이벤트. |
문의는 키를 전달받은 채널로 회신해 주세요.