고객

쇼핑몰 회원가입

상점 설정 그대로 가입 화면을 그리고 같은 기준으로 검증해요.

v1 API 상세: 회원

구매자가 쇼핑몰에 직접 가입​​하는 흐름이에요. 상점의 가입 정책(약관·수집 항목·중복·탈퇴 후 재가입 제한)을 모두 거쳐요.

고객 등록과 다른 API예요

고객 등록(POST /v1/users/join)은 가맹점이 기존 회원을 이관​​하는 서버 동기화 API예요. 가입 정책을 거치지 않고 external_uid·그룹·가입일을 서버가 정해요. 아래 POST /v1/users/signup은 신규 구매자 가입​​이고, 브라우저 입력을 BFF가 그대로 넘기는 경로라 식별자·권한 값을 받지 않아요.

1가입 정책 조회

가입 화면을 그리기 전에 어떤 약관을 받아야 하고 어떤 항목이 필수인지 서버에서 받아요. 약관 ID를 화면에 하드코딩하면 상점이 약관을 바꿨을 때 가입이 통째로 막혀요.

GEThttps://api.bootapi.com/v1/users/signup-policyBasic Auth

필요 권한: user:user_signup_policy · 고객 JWT는 필요 없어요.

{
  "signup_enabled": true,
  "membership_type": "id",
  "supported_member_types": ["individual"],
  "fields": {
    "name":    { "required": true },
    "email":   { "required": true },
    "phone":   { "required": false },
    "address": { "required": true }
  },
  "terms": [
    {
      "term_id": "67e4b4425ec892162491d0ec",
      "required": true,
      "title": "이용약관",
      "desc": "서비스 이용에 대한 약관이에요",
      "content": "<p>제1조 ...</p>",
      "use_url": false,
      "url": null,
      "sort": 0,
      "updated_at": "2026-08-01T10:00:00+09:00"
    }
  ],
  "policy_version": "3f2a1c8e9b4d7a06"
}json
  • membership_type — id면 아이디로, email이면 이메일로 가입받는 상점이에요.
  • fields — 상점 정보 응답의 수집 설정에서 파생한 값이라 두 응답이 갈라지지 않아요.
  • terms — 상점이 만든 약관과 Bootpay 고정 약관을 합쳐 sort 순으로 줘요. 고정 약관은 모든 상점에 공통​​이에요.
  • use_url이 true면 content가 비어 있고 url로 약관을 열어야 해요. 이 경우 content만 그리면 빈 약관이 나와요.
  • updated_at — 약관에는 별도 버전 번호가 없어서 변경 시각을 버전 대신 써요.

signup_enabled가 false인 상점(가입 비활성)은 이 API가 MALL_INACTIVE로 거절해요.

policy_version으로 약관 변경 감지

응답의 policy_version은 약관 목록과 수집 설정의 지문이에요. 가입 요청에 그대로 실어 보내면, 화면을 띄운 뒤 상점이 약관을 바꿨을 때 409로 막아요. 동의받지 않은 약관에 조용히 동의 처리되는 것(silent agreement)을 막는 장치예요.

{
  "error_code": "SIGNUP_POLICY_VERSION_CHANGED",
  "payload": { "policy_version": "a71b0c3d5e8f2419" }
}json

이때는 정책을 다시 조회해 바뀐 약관을 보여주고 다시 동의받아요. policy_version을 보내지 않으면 검사하지 않아요(선택 항목).

표시 순서(sort)만 바꾼 경우에는 버전이 바뀌지 않아요 — 동의 대상이 같기 때문이에요.

2가입 요청

POSThttps://api.bootapi.com/v1/users/signupBasic Auth

필요 권한: user:user_create · 고객 JWT는 필요 없어요.

파라미터 타입 필수 설명
name String 필수 회원 이름 (50자 이하)
password String 필수 비밀번호 (8자 이상, 72바이트 이하)
login_id String 선택 membership_type이 id면 필수 (영문/숫자 5~30자)
email String 선택 fields.email.required면 필수
phone String 선택 fields.phone.required면 필수
address Object 선택 fields.address.required면 필수. 아래 참조
term_ids Array 선택 동의한 약관 ID. 필수 약관은 모두 포함해야 해요
policy_version String 선택 정책 조회 응답의 값

address 객체는 세 키만 받아요.

{
  "address": {
    "zipcode": "06164",
    "address": "서울특별시 강남구 테헤란로 123",
    "address_detail": "101동 101호"
  }
}json

user_group_id·role 같은 다른 키가 섞이면 권한 주입이 되므로 조용히 버리지 않고 거절해요. 최상위 user_id·login_pw·group·membership_type·status 같은 식별자·권한 값도 같은 방식으로 거절해요.

주소 수집 상점

use_membership_collect_address가 켜진 상점에서는 address 없이 가입할 수 없어요. 2026-09-21 이전에는 이 필드를 보낼 방법이 없어 해당 상점의 v1 가입이 항상 실패했어요.

응답

가입 결과는 상점의 가입 방식에 따라 세 가지예요.

{ "status": "finish", "user_id": "67e4...", "requires_login": true }json
status 뜻 함께 오는 값
finish 가입 완료 user_id
standby 이메일 인증 대기 user_standby_id, verification_context
pending_approval 관리자 승인 대기 user_id

어떤 경우에도 고객 JWT를 발급하지 않아요. requires_login: true를 받으면 로그인을 따로 호출해요.

3이메일 인증 (standby)

이메일로 가입받는 상점은 인증 메일을 보내고 대기 상태로 만들어요. 가입 응답의 verification_context는 그 대기 건의 소유 증명​​이니 BFF가 보관해요.

상태 조회

GEThttps://api.bootapi.com/v1/users/authenticate/:user_standby_idBasic Auth
{
  "status": 0,
  "auth_email": false,
  "email": "u***@example.com",
  "user_standby_id": "67e4...",
  "verification_state": "pending",
  "requires_login": true,
  "client_key": "..."
}json

verification_state는 pending · verified · expired 중 하나예요. 기존 status·auth_email·pending_approval 필드는 그대로 유지돼요.

조회는 인증한 상점의 대기 건만 볼 수 있어요. 다른 상점의 ID를 넣으면 USER_STAND_BY_NOT_FOUND예요. verification_context를 함께 보내면 소유까지 확인하고, 보내지 않으면 상점 범위 확인까지만 해요.

인증 완료

POSThttps://api.bootapi.com/v1/users/authenticateBasic Auth

메일 링크로 받은 token_key를 보내요. 잘못된 Base64는 500이 아니라 API_PARAM_INVALID로 응답해요.

인증이 끝나면 대기 문서의 약관 동의(약관 ID·정책 버전·동의 시각)가 회원 계정으로 그대로 이식돼요.

인증 메일 재발송

POSThttps://api.bootapi.com/v1/users/authenticate/:user_standby_id/resendBasic Auth

필요 권한: user:user_signup_resend

verification_context가 필수​​예요. 없거나 틀리면 SIGNUP_CONTEXT_INVALID예요.

{ "accepted": true, "resend_after": "2026-09-21T10:01:00+09:00" }json

재발송은 60초 쿨다운​​이 있고, 인증 유효시간은 발송 후 30분​​이에요. 이미 인증을 마쳤거나 만료된 대기 건은 USER_EMAIL_AUTHENTICATE_EXPIRED로 거절해요.

오류

error_code 상황
MALL_INACTIVE 가입 비활성 상점
API_PARAM_INVALID 허용하지 않는 키, address가 객체가 아님
TERM_NOT_FOUND 목록에 없는 약관 ID
REQUIRED_PARAMETER_IS_MISSING (131) 필수 약관 미동의, 필수 수집 항목 누락
SIGNUP_POLICY_VERSION_CHANGED (10800) 조회 이후 약관·수집 설정 변경
USER_ADDRESS_BLANK (421) 주소 수집 상점인데 주소 누락
USER_ID_EXIST (404) / USER_EMAIL_EXIST (405) 중복 가입
MEMBER_LEFT_RECENTLY 탈퇴 후 재가입 제한 기간
SIGNUP_CONTEXT_INVALID (10801) 재발송의 verification_context 누락·불일치
USER_STAND_BY_NOT_FOUND (411) 없는 대기 건, 다른 상점의 대기 건
USER_EMAIL_RECENTLY_SENT (413) 재발송 쿨다운

선택 약관은 동의하지 않아도 가입할 수 있어요. 필수 약관만 term_ids에 모두 들어가면 돼요.