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":"…","scopes":["space:partner","device:door"]}}
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 재호출은 기간 변경 + 해지 해제됩니다(멱등 — 같은 요청을 몇 번 보내도 결과가 한 번 보낸 것과 같습니다). 새 externalRef에서 doorIds를 생략하거나 null로 보내면 현재 매장의 출입문 범위를 사용합니다. 같은 externalRef를 재발급할 때 생략하거나 null로 보내면 저장된 문 범위를 유지합니다. 비어 있지 않은 배열을 보낼 때만 범위를 바꾸며, 빈 배열은 400으로 거절됩니다. 모든 문으로 넓히려면 현재 문 ID 전체를 명시해야 합니다. 시간창은 한 건당 최대 720시간이며, 장기 자격은 재등록 또는 회원권을 사용합니다.
POST/space/v1/partner/entry-permits/revoke
{"externalRef":"member-1001","reason":"환불"} 또는 {"permitId":"…"} # reason 선택(≤200자)
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}
기기 기기 제어 범위
매장 기기는 한 경로로 다룹니다. 목록으로 기기와 연결 상태를 보고, 명령으로 조작합니다. 기기 제어 범위의 키로는 문만 보입니다.
GET/device/v1/devices · GET/device/v1/devices/{id}
행마다 id · name · health.state(online · offline · unknown — unknown은 아직 한 번도 연결된 적 없음) · capabilities(받는 명령 묶음)가 옵니다. 단건은 문의 지금 상태(standing)를 더합니다.
POST/device/v1/devices/{id}/commands
curl -X POST https://api.superplace.so/device/v1/devices/$DOOR/commands \
-H "Authorization: Bearer $TOKEN" -H "Idempotency-Key: $(uuidgen)" \
-d '{"capability":"door","command":"hold","args":{"minutes":60}}' # minutes 0 = 잠글 때까지
문 명령은 door.open(잠깐 열기) · door.hold(열어두기) · door.close(잠그기)이고 args.reason은 기록용입니다. 기기가 실제로 실행했다고 답한 뒤에 응답합니다 — 성공은 200과 outcome: reported, 실패는 details.reason으로 offline(연결 끊김, 보내지 않음, 409) · refused(기기가 거절, 502) · noResponse(기기가 답하지 않음 — 실행됐는지 모름, 504)입니다.
Idempotency-Key 헤더 필수 — 요청마다 고유한 문자열(UUID 권장). 타임아웃 뒤 같은 값으로 다시 보내면 문이 두 번 열리지 않고 처음 결과를 돌려받습니다. 모든 호출이 출입 기록에 남습니다.
영업시간
PATCH/core/v1/places/{placeId} · GET/core/v1/public/places/{placeId}/schedule
PATCH {"hours":{"week":{"mon":[["09:00","22:00"]], …, "sun":[]}}} # 빈 배열 = 휴무
GET …/schedule?days=7 # 휴무·공휴일까지 계산된 "그날 실제로 여는 구간" (인증 불필요)
API 키로는 영업시간만 수정할 수 있습니다(다른 매장 정보는 403). 저장하면 영업시간 기준으로 도는 매장 자동화가 즉시 이 값을 따릅니다.
기존 시스템의 명부를 옮겨올 때는 일괄 반입(/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-28 | 기기는 한 경로로: GET /device/v1/devices · GET /device/v1/devices/{id} · POST /device/v1/devices/{id}/commands. 명령은 기기가 실행했다고 답한 뒤에 응답합니다(실패는 details.reason: offline · refused · noResponse). 기존 문·보드 경로(/device/v1/doors·/device/v1/boards)는 그대로 동작하지만 새 기능은 더하지 않고 이 문서에서 뺐습니다. 기존 응답의 실패에는 reason·detail이 더해졌습니다. |
| 2026-09-08 | 문 통합 출입 설정 GET/PUT /space/v1/doors/{deviceId}/access-config, 지목 대상 목록 GET /space/v1/access/people · /groups 공개(기기 제어 범위). 통합 설정이 있는 문에서 기존 시간대 정책 API는 409. people 지목 대상은 허가·회원권 없이 전화만으로 입장. |
| 2026-09-06 | 출입 허가에 doorIds(허용 문 지정) 추가, 문별 허가 최대 길이는 지정한 문 중 가장 짧은 값. |
| 2026-09-04 | 영업시간 PATCH /core/v1/places/{placeId}(hours만) · 공개 일정 GET /core/v1/public/places/{placeId}/schedule. |
| 2026-09-03 | v2: 허가 목록·단건, 출입 기록, 출입 설정(entryPhone), 문 제어·시간대 정책·끊김 정책(기기 제어 범위 신설), spk_test_/spk_live_ 키 구분, developers.superplace.so 개설. 허가 url 도메인 go.superplace.so 통일(기존 링크 유효). |
| 2026-08-31 | 첫 공개: 허가 등록·해지, 회원권, 예약, 활동 이벤트. |
문의는 키를 전달받은 채널로 회신해 주세요.