{"openapi":"3.1.0","info":{"title":"RndManage API","version":"1.0.0","description":"사내 R&D 결재 문서(공문/품의서/증빙) 작성·집계 API. 웹 세션 쿠키 또는 `Authorization: Bearer <Google 토큰>`으로 인증. 토큰은 `gcloud auth print-identity-token` 또는 Google OAuth(1시간 유효)로 발급. 이메일이 ALLOWED_DOMAINS/ALLOWED_EMAILS 화이트리스트에 있어야 하며, 토큰의 audience가 이 앱의 OAuth 클라이언트(또는 gcloud CLI, ALLOWED_TOKEN_AUDIENCES 등록 클라이언트)여야 한다. 영구 삭제·대량 덮어쓰기 작업(백업 복원, 휴지통 비우기/영구삭제, 고아 파일 삭제, 마스터데이터 import)은 Bearer로 403."},"servers":[{"url":"https://0.0.0.0:8080"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Google ID 토큰 또는 email 스코프 포함 액세스 토큰 (1h)"}},"schemas":{"DocumentSummary":{"type":"object","properties":{"id":{"type":"string"},"docType":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]},"status":{"type":"string","enum":["draft","review","approved","archived"]},"title":{"type":"string"},"docNumber":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"},"authorEmployeeNo":{"type":"string"},"authorName":{"type":"string"},"pinned":{"type":"boolean"}}},"Document":{"type":"object","description":"문서 전체 본문. 필수: id(nanoid), docType, docSubtype, title. 전체 필드 구조는 GET /api/documents/{docType}/{id} 응답을 참조.","required":["id","docType","docSubtype","title"],"properties":{"id":{"type":"string"},"docType":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]},"docSubtype":{"type":"string"},"status":{"type":"string"},"docNumber":{"type":"string"},"title":{"type":"string"},"recipient":{"type":"string"},"authorEmployeeNo":{"type":"string"},"approverEmployeeNo":{"type":"string"},"department":{"type":"string"},"projectNo":{"type":"string"},"bodyIntro":{"type":"string"},"bodySections":{"type":"array","items":{"type":"object"}},"extraFields":{"type":"object"},"tableRows":{"type":"array","items":{"type":"array","items":{"type":"string"}}},"attachments":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}}}}},"security":[{"bearerAuth":[]}],"paths":{"/api/health":{"get":{"summary":"서비스/저장소 상태 확인","responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"user":{"type":"string"},"storage":{"type":"object"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/documents":{"get":{"summary":"문서 목록(요약) 조회","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":1000}},{"name":"docType","in":"query","schema":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"documents":{"type":"array","items":{"$ref":"#/components/schemas/DocumentSummary"}}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}},"post":{"summary":"문서 저장 (신규/수정 upsert)","description":"id가 같으면 수정, 없으면 생성. baseUpdatedAt을 보내면 충돌 시 409. docNumber 충돌 시 자동으로 새 번호 발급(numberChanged: true).","requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Document"},{"type":"object","properties":{"baseUpdatedAt":{"type":"string"},"force":{"type":"boolean"},"forceDocNumber":{"type":"boolean"}}}]}}}},"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"id":{"type":"string"},"docNumber":{"type":"string"},"numberChanged":{"type":"boolean"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"409":{"description":"동시 편집 충돌 (currentUpdatedAt 포함)"},"500":{"description":"서버 오류"}}}},"/api/documents/{docType}/{id}":{"get":{"summary":"문서 본문 조회","parameters":[{"name":"docType","in":"path","required":true,"schema":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"document":{"$ref":"#/components/schemas/Document"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"404":{"description":"없음"},"500":{"description":"서버 오류"}}},"delete":{"summary":"문서 삭제 (휴지통 이동 — 복구 가능)","parameters":[{"name":"docType","in":"path","required":true,"schema":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"404":{"description":"없음"},"500":{"description":"서버 오류"}}}},"/api/documents/{docType}/{id}/pdf":{"get":{"summary":"PDF 생성 + 다운로드 (첨부 자동 병합)","parameters":[{"name":"docType","in":"path","required":true,"schema":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"PDF 바이너리 (application/pdf)"},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/documents/clone":{"post":{"summary":"문서 복제 (계획→결과 전환 포함)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["docType","id"],"properties":{"docType":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]},"id":{"type":"string"},"targetDocType":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}}}}}},"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"id":{"type":"string"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/master-data":{"get":{"summary":"마스터 데이터 조회 (사원/과제/거래처/설정)","responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"employees":{"type":"array","items":{"type":"object"}},"projects":{"type":"array","items":{"type":"object"}},"vendors":{"type":"array","items":{"type":"object"}},"settings":{"type":"object"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}},"put":{"summary":"마스터 데이터 일괄 저장","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/numbering/peek":{"get":{"summary":"다음 문서번호 미리보기 (발급 확정 아님)","parameters":[{"name":"docType","in":"query","required":true,"schema":{"type":"string","enum":["official_letter","plan_approval","result_resolution","draft","draft_approval","approval","report"]}},{"name":"employeeNo","in":"query","required":true,"schema":{"type":"string"}},{"name":"docDate","in":"query","schema":{"type":"string"}},{"name":"projectNo","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"docNumber":{"type":"string"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/budgets/status":{"get":{"summary":"과제별 비목 예산 집행 현황","responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"statuses":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/trips":{"get":{"summary":"출장 목록","responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"trips":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}},"post":{"summary":"출장 저장 (upsert)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"성공","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"}}}}}},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}},"/api/backup":{"get":{"summary":"전체 백업 JSON 다운로드","responses":{"200":{"description":"백업 JSON 파일"},"401":{"description":"미인증 (세션/토큰 없음 또는 화이트리스트 밖)"},"403":{"description":"API 토큰으로 불가한 작업 (웹 UI 전용)"},"500":{"description":"서버 오류"}}}}}}