Skip to content

API 개요 ​

모든 엔드포인트는 /api/v1 아래에 있다.

스펙 원본은 apps/web/src/lib/openapi.ts에 OpenAPI 3.1로 유지되고, GET /api/v1/openapi가 그 객체를 그대로 JSON으로 돌려준다. 인증이 필요 없다.

bash
curl -s http://localhost:3000/api/v1/openapi > openapi.json

apps/web/tests/openapi.test.ts가 app/api/v1/ 밑의 모든 라우트가 스펙에 있고 메서드까지 일치하는지 검사한다. 이 검사는 Markdown 예시나 모든 응답 필드의 정확성까지 보장하지 않으므로, 연동할 때는 배포한 서버의 스펙도 확인한다.

엔드포인트 목록 ​

메서드경로scope설명
GET/openapi—이 스펙 자체
GET/health—DB 연결 포함 상태 확인
POST/setup—최초 관리자 계정 생성 (사용자 0명일 때만)
POST/auth/register—계정 만들기 (누구나, 역할은 viewer 고정)
POST/auth/login—세션 쿠키 발급
PATCH/account세션내 표시 이름 변경
DELETE/account세션내 계정 탈퇴
POST/account/sso-refresh세션내 SSO 이름·이메일·그룹 다시 가져오기
POST/auth/logout세션세션 폐기
GET/keys세션API 키 목록
POST/keys세션API 키 발급
DELETE/keys/{id}세션API 키 폐기
GET/sso세션(admin)SSO 설정 조회 (시크릿 제외)
PUT/sso세션(admin)SSO 설정 저장
POST/sso/discover세션(admin)issuer의 발견 문서로 엔드포인트 채우기
GET/sso/proxy-check세션(admin)현재 요청에 실제 도착한 프록시 헤더 진단
GET/admin/users세션(admin)사용자·에이전트 계정 목록
POST/admin/users세션(admin)API 전용 에이전트 계정과 키 생성
GET/admin/ai-config세션(admin)마스킹된 AI 연결 설정 조회
PATCH/admin/ai-config세션(admin)AI 연결 설정 저장
POST/admin/ai-config/models세션(admin)공급자가 제공하는 모델 목록 조회
POST/admin/ai-config/test세션(admin)선택 모델로 실제 생성 요청 시험
GET/admin/ai-observability세션(admin)AI 호출 집계·실패와 RAG·검토 큐 상태
GET/admin/rag-config세션(admin)RAG·Embedding·Reranker 설정과 색인 통계
PATCH/admin/rag-config세션(admin)RAG 연결·청크 설정 저장
POST/admin/rag-config/models세션(admin)/v1/models에서 Embedding·Reranker 모델 선택지 조회
POST/admin/rag-config/test세션(admin)Embedding·Reranker 연결 시험
POST/admin/rag-config/reindex세션(admin)전체 용어·회의록·위키 재색인 대기열 생성
POST/rag/searchreadpgvector 용어집 검색
POST/rag/meetings/searchread기존 회의 자료 pgvector 검색
POST/rag/wiki/searchread공개 위키 pgvector 검색
GET/lexiconread검증용 용어 표기 스냅샷 (ETag 지원)
POST/validatevalidate문서 하나의 용어 사용 검증
POST/validate/batchvalidate여러 문서의 용어 사용 일괄 검증
GET/candidatesread문서 검증에서 발견한 미등록 후보 목록
POST/candidates/{id}/dismisswrite미등록 후보 무시
POST/candidates/{id}/promotewrite미등록 후보를 용어로 등록
GET/meetingsread기존 회의 자료 목록
POST/meetingswrite기존 연동 호환용 회의 자료 저장
GET/meetings/{id}read기존 회의 자료 원문 조회
PATCH/meetings/{id}write기존 회의 자료 수정·보관
GET/wikiread위키 문서 목록·검색
POST/wikiwrite위키 문서 생성·RAG 색인 예약
GET/wiki/{slug}read위키 문서 조회
PATCH/wiki/{slug}write위키 문서 수정·RAG 색인 예약
GET/admin/exports/terms세션(admin)서버 전체 용어집 읽기 전용 스냅샷 다운로드
GET/admin/sync세션(admin)동기화 식별자·최근 내보내기·출처 서버별 마지막 적용 결과
DELETE/admin/sync?source={id}세션(admin)출처 서버와의 동기화 연결 해제(데이터는 유지)
GET/admin/sync/export세션(admin)전체·변경분 동기화 번들(gzip) 다운로드
POST/admin/sync/import세션(admin)동기화 번들 미리보기(기본)·반영
GET/admin/menu-settings세션(admin)사이드바 메뉴 표시 설정 조회
PATCH/admin/menu-settings세션(admin)워크스페이스 전체의 부가 메뉴 표시 여부 저장
GET/admin/term-quality세션(admin)콘텐츠 완성도 조회
POST/admin/term-quality세션(admin)최소 길이 변경 영향 미리보기
PATCH/admin/term-quality세션(admin)최소 길이 저장
GET/contributions/review-queuereadAI 작업 상태와 목록
POST/contributions/review-queuewriteAI 검토 요청 또는 대기 작업 재개
GET/contributions/suggestionsread현재 리비전의 AI 제안 조회
PATCH/contributions/suggestionswriteAI 관계 제안 승인·거절
DELETE/contributions/suggestionswriteAI 필드 제안 거절
GET/contributions/term-definitionsread한줄 정의 정리 대상과 캐시된 제안
POST/contributions/term-definitionswriteLLM 한줄 정의 생성
PATCH/contributions/term-definitionswrite한줄 정의 한 건 승인
POST/contributions/classificationswrite도메인·업무 분류 AI 추천 생성
POST/contributions/suggestion-dispositionswriteAI 제안 숨김·보류·개인 저장
DELETE/contributions/suggestion-dispositionswrite내 작업에서 AI 제안 제거
GET/contributions/duplicatesread중복 후보 쌍·검토 상태
POST/contributions/duplicateswriteAI 동일 개념 판정
PATCH/contributions/duplicateswrite병합·분리·보류 결정
POST/chatread용어집에 근거한 AI 질문
GET/termsread용어 목록·검색
POST/termswrite용어 등록
GET/terms/{idOrSlug}read용어 상세
PATCH/terms/{idOrSlug}write용어 수정 (낙관적 잠금)
DELETE/terms/{idOrSlug}admin용어 삭제
GET/terms/{idOrSlug}/revisionsread수정 이력
POST/terms/{idOrSlug}/revisions/{number}/revertwrite그 리비전으로 되돌리기 (새 리비전이 쌓인다)
POST/terms/lookupread배치 표기 조회 (AI-Lint 통합 지점)
GET/terms/suggestread검색창 자동완성 후보 (최대 8개)
GET/relationsread의미 관계 목록·근거·재검토 상태
GET/relations/termsread관계 편집용 용어 검색·정의·리비전
POST/relations로그인 사용자의미 관계 제안
PATCH/relations/{id}로그인 사용자관계 수정·승인·거절
POST/importwrite엑셀 임포트 (dry-run 기본)
POST/attachmentswrite본문 이미지 업로드·WebP 변환
GET/attachments/{sha256}read내용 해시로 첨부 이미지 조회

브라우저가 오가는 SSO 창구 두 개(/auth/sso/start, /auth/sso/callback)는 /api/v1 바깥에 있다. 화면 이동으로만 답하는 자리라 JSON 에러 봉투를 쓸 수 없기 때문이다 — 실패는 /login?sso=<코드>로 돌아온다. SSO 연결에 코드표가 있다.

인증 ​

인증은 두 갈래다.

주체방식
사람(웹 UI)glossary_session 쿠키 또는 신뢰하도록 구성한 oauth2-proxy 헤더
도구(AI-Lint, CI)Authorization: Bearer glk_<prefix>_<secret>

Authorization 헤더가 있으면 API 키 경로를, 없으면 세션 경로를 탄다. 스킴 토큰(Bearer)은 RFC 7235대로 대소문자를 구분하지 않지만 토큰 본문은 구분한다.

API 키는 해시만 저장한다. 평문 토큰은 발급 응답에서만 볼 수 있고 이후로는 복구할 수 없다. 자세한 것은 인증에 있다.

scope ​

키마다 read / write / validate 중 하나 이상을 갖는다. 요구 scope가 없으면 403 forbidden이다. 세션 사용자는 scope 대신 role(admin | editor | viewer)로 갈린다. viewer는 read/validate 요청만 할 수 있고, editor와 admin은 write scope도 사용할 수 있다. 용어 삭제와 /admin/*의 홈·AI·사용자 설정처럼 명시된 관리 작업은 admin 전용이다.

에러 규약 ​

전 엔드포인트가 같은 봉투를 쓴다. 예외 없음.

json
{
  "error": {
    "code": "revision_conflict",
    "message": "다른 사람이 이미 수정했습니다.",
    "details": { "currentRevision": 7 }
  }
}

details는 있을 때만 실린다. code는 기계가 분기할 수 있는 안정된 문자열이다.

codeHTTP언제
validation_failed400입력이 스키마에 맞지 않음. details에 필드별 사유
unauthorized401세션도 유효한 키도 없음
forbidden403인증은 됐으나 scope/role이 모자람
not_found404대상 없음. 형식이 잘못된 id도 여기로 온다
term_not_found404용어 대상이 없음
revision_conflict409낙관적 잠금 충돌. details.currentRevision
email_taken409가입하려는 이메일이 이미 있음(대소문자 무시)
payload_too_large413업로드 본문 상한 초과
rate_limited429챗봇의 사용자·API Key별 분당 요청 제한 초과
method_not_allowed405Allow 헤더에 실제 허용 메서드가 실려 온다
internal_error500처리되지 않은 예외. 스택은 응답에 노출하지 않는다
ai_provider_error502선택 모델·인증·할당량 또는 AI 공급자 연결 문제
ai_not_enabled503관리자가 용어 챗봇 연결을 활성화하지 않음
rag_provider_error502Embedding/Reranker 공급자 연결·인증·응답 문제
rag_not_ready503RAG가 꺼져 있거나 색인/비밀값 설정이 준비되지 않음

4xx와 5xx의 경계

재시도해도 절대 성공하지 않는 입력은 5xx가 아니라 4xx다. ?page=1e999이나 형식이 잘못된 UUID는 그대로 Postgres로 흘러가면 500이 되지만, 기계 클라이언트에게 "나중에 다시 시도하라"는 신호를 주면 안 되므로 라우트가 미리 걸러 400/404로 답한다.

405와 Allow 헤더 ​

라우트는 자신이 처리하지 않는 메서드를 명시적으로 405 스텁으로 export한다. Next의 기본 405는 0바이트 본문에 content-type도 없어 위 규약을 깬다. OPTIONS도 함께 만들어져서 Allow 헤더가 실제 허용 메서드와 항상 일치한다 (GET을 허용하는 라우트는 HEAD도 같이 광고한다).

$ curl -i -X PUT http://localhost:3000/api/v1/terms
HTTP/1.1 405 Method Not Allowed
allow: GET, HEAD, POST
{"error":{"code":"method_not_allowed","message":"지원하지 않는 메서드입니다."}}

상태를 바꾸는 GET은 만들지 않는다 ​

CSRF 방어는 상태 변경 요청의 Origin 또는 Referer를 허용 출처와 비교하고 SameSite=Lax 쿠키를 함께 사용한다. 따라서 상태 변경은 반드시 POST/PATCH/DELETE다. 로그아웃이 GET이 아니라 POST인 이유가 이것이다. apps/web/tests/screen-guards.test.ts가 이 규칙을 강제한다.

HTTPS ​

기본 Compose 구성은 평문 HTTP다. 세션 쿠키는 HTTPS 요청에서 Secure가 자동으로 붙는다. 판정은 apps/web/src/lib/auth/session.ts의 isSecureRequest가 담당한다. 운영에서 프록시 헤더를 신뢰하려면 GLOSSARY_TRUST_PROXY_HEADERS=true를 설정하고, 리버스 프록시는 X-Forwarded-Proto를 실제 외부 프로토콜로 덮어써야 한다. 구성 전제는 운영 안내서를 참고한다.

사내망 온프레미스 배포를 전제로 만든 Apache-2.0 프로젝트입니다.