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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | 서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다. |
X-Structly-Client | header | "stly" | No | stly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다. |
Request body
application/json · Required: Yes
Type: Signup
| Name | Type | Required | Description |
|---|---|---|---|
email | string | Yes | 정규화 후 3~254자, @ 하나, 공백·제어 문자 불가 |
password | string | Yes | 문자 수 기준. 조합 규칙 없음 |
display_name | string | Yes | 앞뒤 공백 제거 후 1~100자, 제어 문자 불가 |
keep_signed_in | boolean | No |
Responses
| Status | Description |
|---|---|
201 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
409 | EMAIL_CONFLICT(정규화 이메일 중복) |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
500 | INTERNAL_ERROR |
201 response body
Type: Me
| Name | Type | Required | Description |
|---|---|---|---|
user | User | Yes | |
organizations | Organization[] | Yes | active 소속. lower(name)·생성 시각·ID 순 |
current_organization_id | string | null | Yes | verified active 소속인 현재 Organization. 없거나 인증 대기면 null |
로그인#
POST /api/auth/login
이메일 미존재와 비밀번호 불일치를 같은 401로 응답합니다. verified active 소속이 정확히 하나면 현재 Organization으로 지정합니다.
Authentication: Not required
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | 서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다. |
X-Structly-Client | header | "stly" | No | stly가 cli 정책을 선택할 때 stly. keep_signed_in과 함께 보낼 수 없습니다. |
Request body
application/json · Required: Yes
Type: Login
| Name | Type | Required | Description |
|---|---|---|---|
email | string | Yes | |
password | string | Yes | |
keep_signed_in | boolean | No |
Responses
| Status | Description |
|---|---|
200 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
500 | INTERNAL_ERROR |
200 response body
Type: Me
| Name | Type | Required | Description |
|---|---|---|---|
user | User | Yes | |
organizations | Organization[] | Yes | active 소속. lower(name)·생성 시각·ID 순 |
current_organization_id | string | null | Yes | verified active 소속인 현재 Organization. 없거나 인증 대기면 null |
로그아웃#
POST /api/auth/logout
세션 행을 삭제하고 쿠키를 지웁니다. 세션이 없어도 204입니다. 본문은 비워야 합니다.
Authentication: Session cookie
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | 서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다. |
Responses
| Status | Description |
|---|---|
204 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
500 | INTERNAL_ERROR |
현재 User·소속 Organization·현재 Organization 조회#
GET /api/me
본문과 query를 거부합니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가).
Authentication: Session cookie
Responses
| Status | Description |
|---|---|
200 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
500 | INTERNAL_ERROR |
200 response body
Type: Me
| Name | Type | Required | Description |
|---|---|---|---|
user | User | Yes | |
organizations | Organization[] | Yes | active 소속. lower(name)·생성 시각·ID 순 |
current_organization_id | string | null | Yes | verified active 소속인 현재 Organization. 없거나 인증 대기면 null |
Web 사용자 활동으로 세션 갱신#
POST /api/me/activity
빈 본문과 query만 허용합니다. fixed는 변경하지 않고 web_keep·web_browser는 서버 5분 스로틀에 따라 갱신합니다.
Authentication: Session cookie
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes |
Responses
| Status | Description |
|---|---|
204 | 성공. web_keep가 실제 갱신된 경우에만 Max-Age 30일 쿠키를 다시 설정합니다. |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
500 | INTERNAL_ERROR |
현재 Organization 선택#
PUT /api/me/current-organization
active 소속이 있는 Organization만 선택합니다. 이후 Catalog 요청의 경계가 됩니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가).
Authentication: Session cookie
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | 서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다. |
Request body
application/json · Required: Yes
Type: OrganizationSelect
| Name | Type | Required | Description |
|---|---|---|---|
organization_id | string | Yes | ID. |
Responses
| Status | Description |
|---|---|
204 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
404 | ORGANIZATION_NOT_FOUND(active 소속이 아닌 Organization) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
500 | INTERNAL_ERROR |
본인 비밀번호 변경#
PUT /api/me/password
현재 비밀번호를 확인한 뒤 새 비밀번호로 바꿉니다. 요청한 세션과 이 User의 다른 Web·CLI 세션, Agent 토큰은 그대로 유지합니다. 세션 쿠키 structly_session이 필요합니다(Bearer 토큰 불가). Web UI 전용이며 stly에서 제공하지 않습니다.
Authentication: Session cookie
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | 서버 origin(예: http://127.0.0.1:5173)과 같아야 합니다. |
Request body
application/json · Required: Yes
Type: PasswordChange
| Name | Type | Required | Description |
|---|---|---|---|
current_password | string | Yes | 저장된 비밀번호와 일치해야 합니다 |
new_password | string | Yes | 8~128자. 문자 종류 조합 규칙 없음. 현재 비밀번호와 같아도 허용 |
Responses
| Status | Description |
|---|---|
204 | 성공. 세션 쿠키를 다시 발급하지 않습니다. |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
500 | INTERNAL_ERROR |
CLI 승인 요청 생성#
POST /api/auth/cli-login
생성·poll은 API Origin과 credential 없는 CLI, 결정은 Web Origin과 User 세션 전용입니다. 모든 응답은 no-store이며 코드를 URL에 넣지 않습니다.
Authentication: Not required
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | API Origin. Cookie·Authorization은 보내지 않습니다. |
Request body
application/json · Required: Yes
Type: CLILoginCreate
No top-level fields to show.
Responses
| Status | Description |
|---|---|
201 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
404 | CLI_LOGIN_NOT_FOUND |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
409 | CLI_LOGIN_CONFLICT |
410 | CLI_LOGIN_EXPIRED |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
429 | CLI_LOGIN_RATE_LIMITED |
500 | INTERNAL_ERROR |
201 response body
Type: CLILoginStart
| Name | Type | Required | Description |
|---|---|---|---|
device_code | string | Yes | |
user_code | string | Yes | |
verification_uri | string(uri) | Yes | |
expires_in | 600 | Yes | |
interval | 5 | Yes |
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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | API Origin. Cookie·Authorization은 보내지 않습니다. |
Request body
application/json · Required: Yes
Type: CLILoginPoll
| Name | Type | Required | Description |
|---|---|---|---|
device_code | string | Yes |
Responses
| Status | Description |
|---|---|
200 | 성공 |
202 | 승인 대기 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
404 | CLI_LOGIN_NOT_FOUND |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
409 | CLI_LOGIN_CONFLICT |
410 | CLI_LOGIN_EXPIRED |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
429 | CLI_LOGIN_RATE_LIMITED |
500 | INTERNAL_ERROR |
200 response body
Type: Me
| Name | Type | Required | Description |
|---|---|---|---|
user | User | Yes | |
organizations | Organization[] | Yes | active 소속. lower(name)·생성 시각·ID 순 |
current_organization_id | string | null | Yes | verified 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
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Origin | header | string | Yes | HTTPS는 설정된 Web Origin, 로컬은 Vite proxy의 same-origin. |
Request body
application/json · Required: Yes
Type: CLILoginDecision
| Name | Type | Required | Description |
|---|---|---|---|
user_code | string | Yes | |
decision | any | Yes | Values: approve, deny |
Responses
| Status | Description |
|---|---|
204 | 성공 |
400 | INVALID_REQUEST(query·미정의 필드·JSON 형식·본문 있는 GET/logout) |
401 | UNAUTHENTICATED(세션 없음·만료) 또는 로그인 실패 INVALID_CREDENTIALS. WWW-Authenticate 포함 |
403 | FORBIDDEN_ORIGIN(Origin이 서버 origin과 다름·누락) |
404 | CLI_LOGIN_NOT_FOUND |
405 | METHOD_NOT_ALLOWED. Allow 포함 |
409 | CLI_LOGIN_CONFLICT |
410 | CLI_LOGIN_EXPIRED |
413 | PAYLOAD_TOO_LARGE(본문 16 KiB 초과) |
415 | UNSUPPORTED_MEDIA_TYPE |
422 | VALIDATION_FAILED. data에 필드 오류 |
429 | CLI_LOGIN_RATE_LIMITED |
500 | INTERNAL_ERROR |