Skip to content
Structly Docs
한국어

API reference

Auth

On this page

This page is generated from the public contract. Descriptions are shown in the original Korean.

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

회원가입#

POST /api/auth/signup

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

Authentication: Not required

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.
X-Structly-Clientheader"stly"Nostly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다.

Request body

application/json · Required: Yes

Type: Signup

NameTypeRequiredDescription
emailstringYes정규화 후 3~254자, @ 하나, 공백·제어 문자 불가
passwordstringYes문자 수 기준. 조합 규칙 없음
display_namestringYes앞뒤 공백 제거 후 1~100자, 제어 문자 불가
keep_signed_inbooleanNo

Responses

StatusDescription
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 response body

Type: Me

NameTypeRequiredDescription
userUserYes
organizationsOrganization[]Yesactive 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | nullYesverified active 소속인 현재 Organization. 없거나 인증 대기면 null

로그인#

POST /api/auth/login

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

Authentication: Not required

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.
X-Structly-Clientheader"stly"Nostly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다.

Request body

application/json · Required: Yes

Type: Login

NameTypeRequiredDescription
emailstringYes
passwordstringYes
keep_signed_inbooleanNo

Responses

StatusDescription
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 response body

Type: Me

NameTypeRequiredDescription
userUserYes
organizationsOrganization[]Yesactive 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | nullYesverified active 소속인 현재 Organization. 없거나 인증 대기면 null

로그아웃#

POST /api/auth/logout

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

Authentication: Session cookie

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

Responses

StatusDescription
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 토큰 불가).

Authentication: Session cookie

Responses

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

200 response body

Type: Me

NameTypeRequiredDescription
userUserYes
organizationsOrganization[]Yesactive 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | nullYesverified active 소속인 현재 Organization. 없거나 인증 대기면 null

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

POST /api/me/activity

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

Authentication: Session cookie

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes

Responses

StatusDescription
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 토큰 불가).

Authentication: Session cookie

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

Request body

application/json · Required: Yes

Type: OrganizationSelect

NameTypeRequiredDescription
organization_idstringYesID.

Responses

StatusDescription
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에서 제공하지 않습니다.

Authentication: Session cookie

Parameters

NameInTypeRequiredDescription
OriginheaderstringYes서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다.

Request body

application/json · Required: Yes

Type: PasswordChange

NameTypeRequiredDescription
current_passwordstringYes저장된 비밀번호와 일치해야 합니다
new_passwordstringYes8~128자. 문자 종류 조합 규칙 없음. 현재 비밀번호와 같아도 허용

Responses

StatusDescription
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에 넣지 않습니다.

Authentication: Not required

Parameters

NameInTypeRequiredDescription
OriginheaderstringYesAPI Origin. Cookie·Authorization은 보내지 않습니다.

Request body

application/json · Required: Yes

Type: CLILoginCreate

No top-level fields to show.

Responses

StatusDescription
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 response body

Type: CLILoginStart

NameTypeRequiredDescription
device_codestringYes
user_codestringYes
verification_uristring(uri)Yes
expires_in600Yes
interval5Yes

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 세션의 선택은 복사·변경하지 않습니다.

Authentication: Not required

Parameters

NameInTypeRequiredDescription
OriginheaderstringYesAPI Origin. Cookie·Authorization은 보내지 않습니다.

Request body

application/json · Required: Yes

Type: CLILoginPoll

NameTypeRequiredDescription
device_codestringYes

Responses

StatusDescription
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 response body

Type: Me

NameTypeRequiredDescription
userUserYes
organizationsOrganization[]Yesactive 소속. lower(name)·생성 시각·ID 순
current_organization_idstring | nullYesverified active 소속인 현재 Organization. 없거나 인증 대기면 null

Web User의 CLI 승인·거부#

POST /api/auth/cli-login/decision

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

Authentication: Session cookie

Parameters

NameInTypeRequiredDescription
OriginheaderstringYesHTTPS는 설정된 Web Origin, 로컬은 Vite proxy의 same-origin.

Request body

application/json · Required: Yes

Type: CLILoginDecision

NameTypeRequiredDescription
user_codestringYes
decisionanyYesValues: approve, deny

Responses

StatusDescription
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