본문으로 건너뛰기
Structly 문서
English

API 레퍼런스

Auth

이 페이지의 내용

이 페이지는 공개 계약에서 생성하며 설명은 원문(한국어) 그대로 표시합니다.

회원가입·로그인·로그아웃, 현재 User와 현재 Organization 선택, 비밀번호 변경, stly 브라우저 승인 로그인. 인증이 필요한 경로는 User 세션 쿠키만 받으며 Agent 토큰은 쓰지 않습니다.

회원가입#

POST /api/auth/signup

User·비밀번호 credential·세션을 함께 만들고 세션 쿠키를 설정합니다. 이메일 소유 확인은 하지 않습니다.

인증: 필요 없음

Parameter

이름위치타입필수설명
Originheaderstring예서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.
X-Structly-Clientheader"stly"아니요stly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다.

요청 본문

application/json · 필수: 예

타입: Signup

이름타입필수설명
emailstring예정규화 후 3~254자, @ 하나, 공백·제어 문자 불가
passwordstring예문자 수 기준. 조합 규칙 없음
display_namestring예앞뒤 공백 제거 후 1~100자, 제어 문자 불가
keep_signed_inboolean아니요

응답

상태설명
201성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
405METHOD_NOT_ALLOWED. Allow 포함
409EMAIL_CONFLICT(정규화 이메일 중복)
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
500INTERNAL_ERROR

201 응답 본문

타입: Me

이름타입필수설명
userUser예
organizationsOrganization[]예active 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | null예verified active 소속인 현재 Organization. 없거나 인증 대기면 null

로그인#

POST /api/auth/login

이메일 미존재와 비밀번호 불일치를 같은 401로 응답합니다. verified active 소속이 정확히 하나면 현재 Organization으로 지정합니다.

인증: 필요 없음

Parameter

이름위치타입필수설명
Originheaderstring예서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.
X-Structly-Clientheader"stly"아니요stly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다.

요청 본문

application/json · 필수: 예

타입: Login

이름타입필수설명
emailstring예
passwordstring예
keep_signed_inboolean아니요

응답

상태설명
200성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
405METHOD_NOT_ALLOWED. Allow 포함
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
500INTERNAL_ERROR

200 응답 본문

타입: Me

이름타입필수설명
userUser예
organizationsOrganization[]예active 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | null예verified active 소속인 현재 Organization. 없거나 인증 대기면 null

로그아웃#

POST /api/auth/logout

세션 행을 삭제하고 쿠키를 지웁니다. 세션이 없어도 204입니다. 본문은 비워야 합니다.

인증: 세션 쿠키

Parameter

이름위치타입필수설명
Originheaderstring예서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

응답

상태설명
204성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
405METHOD_NOT_ALLOWED. Allow 포함
500INTERNAL_ERROR

현재 User·소속 Organization·현재 Organization 조회#

GET /api/me

본문과 query를 거부합니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가).

인증: 세션 쿠키

응답

상태설명
200성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
405METHOD_NOT_ALLOWED. Allow 포함
500INTERNAL_ERROR

200 응답 본문

타입: Me

이름타입필수설명
userUser예
organizationsOrganization[]예active 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | null예verified active 소속인 현재 Organization. 없거나 인증 대기면 null

Web 사용자 활동으로 세션 갱신#

POST /api/me/activity

빈 본문과 query만 허용합니다. fixed는 변경하지 않고 web_keep·web_browser는 서버 5분 스로틀에 따라 갱신합니다.

인증: 세션 쿠키

Parameter

이름위치타입필수설명
Originheaderstring예

응답

상태설명
204성공. web_keep가 실제 갱신된 경우에만 Max-Age 30일 쿠키를 다시 설정합니다.
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
405METHOD_NOT_ALLOWED. Allow 포함
500INTERNAL_ERROR

현재 Organization 선택#

PUT /api/me/current-organization

active 소속이 있는 Organization만 선택합니다. 이후 Catalog 요청의 경계가 됩니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가).

인증: 세션 쿠키

Parameter

이름위치타입필수설명
Originheaderstring예서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

요청 본문

application/json · 필수: 예

타입: OrganizationSelect

이름타입필수설명
organization_idstring예ID.

응답

상태설명
204성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
404ORGANIZATION_NOT_FOUND(active 소속이 아닌 Organization)
405METHOD_NOT_ALLOWED. Allow 포함
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
500INTERNAL_ERROR

본인 비밀번호 변경#

PUT /api/me/password

현재 비밀번호를 확인한 뒤 새 비밀번호로 바꿉니다. 요청한 세션과 이 User의 다른 Web·CLI 세션, Agent 토큰은 그대로 유지합니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가). Web UI 전용이며 stly에서 제공하지 않습니다.

인증: 세션 쿠키

Parameter

이름위치타입필수설명
Originheaderstring예서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

요청 본문

application/json · 필수: 예

타입: PasswordChange

이름타입필수설명
current_passwordstring예저장된 비밀번호와 일치해야 합니다
new_passwordstring예8~128자. 문자 종류 조합 규칙 없음. 현재 비밀번호와 같아도 허용

응답

상태설명
204성공. 세션 쿠키를 다시 발급하지 않습니다.
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
405METHOD_NOT_ALLOWED. Allow 포함
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
500INTERNAL_ERROR

CLI 승인 요청 생성#

POST /api/auth/cli-login

생성·poll은 API Origin과 credential 없는 CLI, 결정은 Web Origin과 User 세션 전용입니다. 모든 응답은 no-store이며 코드를 URL에 넣지 않습니다.

인증: 필요 없음

Parameter

이름위치타입필수설명
Originheaderstring예API Origin. Cookie·Authorization은 보내지 않습니다.

요청 본문

application/json · 필수: 예

타입: CLILoginCreate

표시할 최상위 필드가 없습니다.

응답

상태설명
201성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
404CLI_LOGIN_NOT_FOUND
405METHOD_NOT_ALLOWED. Allow 포함
409CLI_LOGIN_CONFLICT
410CLI_LOGIN_EXPIRED
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
429CLI_LOGIN_RATE_LIMITED
500INTERNAL_ERROR

201 응답 본문

타입: CLILoginStart

이름타입필수설명
device_codestring예
user_codestring예
verification_uristring(uri)예
expires_in600예
interval5예

CLI 승인 대기·일회용 세션 발급#

POST /api/auth/cli-login/poll

생성·poll은 API Origin과 credential 없는 CLI, 결정은 Web Origin과 User 세션 전용입니다. 모든 응답은 no-store이며 코드를 URL에 넣지 않습니다. 소비 시 active·verified 후보가 정확히 하나이면 새 CLI 세션에 자동 선택하고, 0개 또는 여러 개이면 current_organization_id는 null입니다. Web 세션의 선택은 복사·변경하지 않습니다.

인증: 필요 없음

Parameter

이름위치타입필수설명
Originheaderstring예API Origin. Cookie·Authorization은 보내지 않습니다.

요청 본문

application/json · 필수: 예

타입: CLILoginPoll

이름타입필수설명
device_codestring예

응답

상태설명
200성공
202승인 대기
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
404CLI_LOGIN_NOT_FOUND
405METHOD_NOT_ALLOWED. Allow 포함
409CLI_LOGIN_CONFLICT
410CLI_LOGIN_EXPIRED
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
429CLI_LOGIN_RATE_LIMITED
500INTERNAL_ERROR

200 응답 본문

타입: Me

이름타입필수설명
userUser예
organizationsOrganization[]예active 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | null예verified active 소속인 현재 Organization. 없거나 인증 대기면 null

Web User의 CLI 승인·거부#

POST /api/auth/cli-login/decision

생성·poll은 API Origin과 credential 없는 CLI, 결정은 Web Origin과 User 세션 전용입니다. 모든 응답은 no-store이며 코드를 URL에 넣지 않습니다.

인증: 세션 쿠키

Parameter

이름위치타입필수설명
Originheaderstring예HTTPS는 설정된 Web Origin, 로컬은 Vite proxy의 same-origin.

요청 본문

application/json · 필수: 예

타입: CLILoginDecision

이름타입필수설명
user_codestring예
decisionany예값: approve, deny

응답

상태설명
204성공
400INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout)
401UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함
403FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락)
404CLI_LOGIN_NOT_FOUND
405METHOD_NOT_ALLOWED. Allow 포함
409CLI_LOGIN_CONFLICT
410CLI_LOGIN_EXPIRED
413PAYLOAD_TOO_LARGE(본문 16 KiB 초과)
415UNSUPPORTED_MEDIA_TYPE
422VALIDATION_FAILED. data에 필드 오류
429CLI_LOGIN_RATE_LIMITED
500INTERNAL_ERROR