본문으로 건너뛰기

Audit logs API

정보

Document Management SDK의 Audit Logs는 파일·사용자·관리 활동을 Document Governance SDK 연동 구조를 통해 수집·저장하고 조회할 수 있도록 구현한 사례입니다. Storage와 Editor의 활동이 하나의 증적 기록으로 연결되는 구조는 Governance Integration에서 확인할 수 있습니다.

tenant의 감사 기록을 읽는 두 개의 읽기 전용 endpoint입니다. 페이지 단위 조회와, 기간 전체를 내려받는 CSV 내보내기입니다.

Base URL과 인가

/api/external/v1/admins/audit-logs

이 endpoint들은 ADMIN 역할을 가진 계정으로 발급된 API Key가 필요합니다. 인가는 역할만으로 결정되며 키의 scope는 검사하지 않습니다. 두 endpoint 모두 읽기 전용이므로 api:read만 가진 키도 api:write를 가진 키와 동일하게 동작합니다.

조회 대상 tenant는 호출한 키를 기준으로 서버가 고정합니다. 다른 tenant를 지정하는 요청 파라미터는 없습니다. tenant는 요청 host로 판별하므로 키를 발급받은 도메인으로 호출해야 하며, 다른 도메인으로 호출하면 API_KEY_004로 실패합니다.

거버넌스가 꺼져 있으면 endpoint 자체가 없음

governance.audit.enabled=false로 동작하는 환경은 이 endpoint들을 아예 등록하지 않으며 모든 호출이 404가 됩니다. 여기서의 404는 경로가 틀렸다는 뜻이 아니라 기능이 꺼져 있다는 뜻입니다.

데이터 출처

감사 이벤트는 Drive 데이터베이스에 저장되지 않습니다. 거버넌스 서버에 있고, Drive가 거버넌스 조회 API를 프록시합니다. 거버넌스 인증은 서버 사이드에서 처리되므로 호출자에게는 Drive API Key 외에 필요한 것이 없습니다.

이 구조 때문에 알아 둘 점이 하나 있습니다. 거버넌스 어휘를 벗어난 필터 값은 400이 아니라 500으로 돌아옵니다. 거버넌스는 그 값을 400으로 거절하지만 Drive가 이를 RESPONSE_001로 감쌉니다. 모든 필터는 아래에 나열된 값 안에서 보냅니다.

필터 값

eventCategory

포함 범위
LOGIN로그인, 로그아웃, 계정 잠금 상태
FILE_FOLDER파일과 폴더 행위
SHARE공유
USER_MANAGEMENT사용자와 관리자 계정 관리
SETTING환경 설정 변경
eventCategory는 하나만 보낼 것

두 개 이상을 보내면 오류가 아니라 200에 0건이 돌아오며, 이는 "그런 사건이 없음"과 구분되지 않습니다. 2026-09-14 실측: eventCategory=LOGIN&eventCategory=SHAREtotalCount 0을 반환했습니다. 여러 카테고리를 한 번에 보려면 각 카테고리를 eventTypes로 펼쳐서 보냅니다.

channel

포함 범위
WEB웹 화면
API외부 API
MCPMCP
SYSTEM사용자 요청 없이 시스템에서 발생

outcomeStatus

포함 범위
SUCCESS동작 성공
FAIL동작 실패

eventType

41개 값이며, 각각 하나의 카테고리에 속합니다.

카테고리종류
LOGINLOGIN, LOGOUT, ACCOUNT_LOCKED_STATUS_CHANGE
FILE_FOLDERFILE_CREATE, FILE_UPLOAD, FILE_DOWNLOAD, FILE_PREVIEW, FILE_OPEN, FILE_EDIT, FILE_DELETE, FILE_PERMANENT_DELETE, FILE_RESTORE, FILE_RENAME, FILE_MOVE, FILE_COPY, FOLDER_CREATE, FOLDER_DOWNLOAD, FOLDER_DELETE, FOLDER_PERMANENT_DELETE, FOLDER_RESTORE, FOLDER_RENAME
SHARESHARE_CREATE, SHARE_PERMISSION_CHANGE, SHARE_REMOVE
USER_MANAGEMENTUSER_CREATE, USER_DELETE, USER_PERMANENT_DELETE, USER_RESTORE, USER_INFO_UPDATE, USER_TWOFACTOR_RESET, USER_PASSWORD_CHANGE, USER_STATUS_CHANGE, ADMIN_CREATE, ADMIN_DELETE, ADMIN_PERMANENT_DELETE, ADMIN_RESTORE, ADMIN_INFO_UPDATE, ADMIN_PASSWORD_CHANGE, ADMIN_STATUS_CHANGE
SETTINGSETTING_UPDATE, SETTING_ALLOWED_IP_CHANGE

로그인 성공과 실패는 둘 다 LOGIN으로 기록되며, 구분은 outcomeStatus입니다. 로그아웃만 LOGOUT으로 따로 남습니다. 따라서 LOGIN으로 필터하면 성공과 실패가 함께 나옵니다.

날짜

요청 날짜는 yyyy-MM-dd입니다. 기간은 from 당일 00:00부터 to 다음 날 00:00 직전까지이므로 종료일이 결과에 포함됩니다. 응답의 값은 Asia/Seoul 기준 yyyy-MM-dd HH:mm:ss.SSS입니다.

감사 이벤트 목록 조회

GET /api/external/v1/admins/audit-logs

호출한 키의 tenant를 페이지 번호 방식으로 조회합니다. 정렬은 occurredAt 내림차순으로 고정이며 정렬 파라미터는 없습니다.

파라미터타입필수설명
piintegerYes페이지 번호, 1부터
psintegerYes페이지 크기, 1에서 200. 더 큰 값은 거버넌스 상한인 200으로 잘립니다
actorEmailstringNo행위자 이메일, 정확일치. 부분 검색은 지원하지 않습니다
fromstringNo시작일, 당일 포함
tostringNo종료일, 당일 포함
eventCategorystringNo카테고리 값 하나
eventTypesstring[]No이벤트 종류, 값마다 한 번씩 반복
channelstringNoWEB, API, MCP, SYSTEM 중 하나
outcomeStatusstringNoSUCCESS 또는 FAIL

eventTypes는 쉼표로 잇지 않고 반복해서 보냅니다: eventTypes=FILE_RENAME&eventTypes=FILE_MOVE. 개수 제한은 없으며, 실질 상한은 요청 URL 길이로 기본 웹 서버에서 8 KB입니다.

List audit events
curl -X GET "https://drive.example.com/api/external/v1/admins/audit-logs?pi=1&ps=20&from=2026-09-01&to=2026-09-14&eventCategory=FILE_FOLDER&eventTypes=FILE_RENAME&eventTypes=FILE_MOVE" \
-H "Authorization: Bearer replace-with-your-api-key" \
-H "Content-Type: application/json"
Success
{
"result": true,
"code": 200,
"data": [
{
"eventId": "019b2f58-7f3a-7c21-8e90-4c1f2f2e7840",
"occurredAt": "2026-09-14 14:11:03.510",
"eventType": "FILE_RENAME",
"eventCategory": "FILE_FOLDER",
"actorType": "HUMAN",
"actorName": "First user",
"actorEmail": "user1@example.com",
"objectType": "FILE",
"objectName": "Proposal.pptx",
"objectEmail": null,
"objectPath": "MY/Sales/2026",
"outcomeStatus": "SUCCESS",
"outcomeCode": null,
"channel": "WEB",
"clientIp": "198.51.100.20",
"tenantSeq": "3",
"tenantName": "Example tenant",
"change": {
"before": "Proposal_draft.pptx",
"after": "Proposal.pptx"
},
"targets": null
}
],
"totalCount": 1234,
"pageIndex": 1,
"pageSize": 20
}

목록 응답에는 message가 없습니다. 페이징 값은 totalCount, pageIndex, pageSize로 내려옵니다.

필드타입설명
eventIdstring거버넌스가 발급한 이벤트 식별자
occurredAtstring발생 시각
eventTypestring이벤트 종류. eventTypes가 매칭하는 값
eventCategorystring해당 종류가 속한 상위 분류
actorTypestring행위자 유형. HUMAN
actorNamestring행위자 표시 이름
actorEmailstring행위자 이메일. Drive 계정 id와 같은 값
objectTypestring대상 유형: FILE, FOLDER, USER, SETTING
objectNamestring대상 이름 - 파일이나 폴더 이름, 계정 이름 등
objectEmailstring대상 계정 이메일. 대상이 계정인 경우에만 있고 아니면 null
objectPathstring부모 폴더 기준 대상 경로. 맨 앞 세그먼트는 위치 코드로 MY는 내 드라이브, SHARE는 공유 문서함
outcomeStatusstringSUCCESS 또는 FAIL
outcomeCodestring실패 사유 코드. 실패 건에만 있고 아니면 null
channelstring요청이 들어온 경로
clientIpstring요청 클라이언트 IP
tenantSeqstringtenant 식별자. 거버넌스 scope id
tenantNamestringtenant 이름. 거버넌스 scope 이름
changeobject변경 전후를 담은 {before, after, summary}. 변경성 이벤트에만
targetsobject[]공유 대상자 등 대상 목록. 해당하는 이벤트에만
Failure
{
"result": false,
"code": 400,
"errorCode": "REQUEST_001",
"message": "[{msg=must not be null, field=pi}]"
}

감사 이벤트 CSV 내보내기

GET /api/external/v1/admins/audit-logs/export

조건에 맞는 기간 전체를 CSV로 내려받습니다. 목록 조회와 같은 필터를 받되 페이징 파라미터는 받지 않으며, 본문은 JSON 봉투 없는 CSV 원문입니다.

파라미터타입필수설명
fromstringNo시작일, 당일 포함. 비우면 to의 92일 전
tostringNo종료일, 당일 포함. 비우면 현재 시각
actorEmailstringNo행위자 이메일, 정확일치
eventCategorystringNo카테고리 값 하나
eventTypesstring[]No이벤트 종류, 값마다 한 번씩 반복
channelstringNoWEB, API, MCP, SYSTEM 중 하나
outcomeStatusstringNoSUCCESS 또는 FAIL

기간 상한은 92일입니다. 두 날짜를 모두 비우면 최근 92일이 적용되고, 그보다 긴 구간은 400으로 거절됩니다. 달력 기준 한 분기가 89일에서 92일이므로 92일이면 어떤 3개월 구간도 담깁니다. 더 긴 기간이 필요하면 구간을 나눠 여러 번 호출합니다.

pips는 이 endpoint에서 쓰지 않으며 보내도 무시됩니다. 응답은 한 페이지가 아니라 기간 전체입니다.

Export audit events
curl -X GET "https://drive.example.com/api/external/v1/admins/audit-logs/export?from=2026-06-01&to=2026-09-01&eventCategory=SHARE" \
-H "Authorization: Bearer replace-with-your-api-key" \
-o audit-events.csv
응답 헤더
Content-Typetext/csv
Content-Dispositionattachment; filename*=UTF-8''audit-events_20260601-20260901.csv
Content-Length없음 - 본문을 조각으로 나눠 보내므로 전체 크기를 미리 알 수 없습니다

파일 이름은 audit-events_{from}-{to}.csv 형식입니다.

Export body
schemaVersion,eventId,eventType,sourceEventType,occurredAt,origin.system,…,observedIp,ingestKeyId
1.0,019b2f58-7f3a-7c21-8e90-4c1f2f2e7840,FILE_RENAME,FILE_RENAME,2026-07-16T05:11:03.510Z,TFD,…,198.51.100.20,key-acme-01

파일 규격은 거버넌스 원본 그대로입니다. BOM이 붙은 UTF-8, CRLF 줄 끝, RFC 4180 따옴표, 순서가 계약의 일부인 44개 열, 그리고 수식으로 읽힐 수 있는 값 앞의 작은따옴표입니다. 목록 응답보다 열이 많습니다.

Failure
{
"result": false,
"code": 400,
"message": "감사 로그 내보내기 기간은 최대 92일입니다."
}

내보내기 실패는 공통 봉투의 예외입니다. errorCode가 없습니다.

첫 조각 이후의 실패는 알릴 수 없음

응답은 조각으로 나뉘어 전송됩니다. 첫 조각을 보낸 시점에 이미 200이 나갔으므로, 그 뒤의 실패는 응답이 도중에 끊기는 것으로만 나타납니다. 규격을 지키는 HTTP 클라이언트는 마지막 조각이 오지 않는 것을 오류로 처리하며 잘린 파일을 받아들이지 않지만, 받은 내용이 완결되었는지 확인할 책임은 여전히 클라이언트에 있습니다.

긴 기간은 스트리밍으로 파일에 저장합니다. 한 행이 약 1,450바이트이므로 10만 행이면 약 138 MB입니다. 응답 전체를 메모리에 올리는 방식 - 브라우저 Blob, 문자열 변환 등 - 은 기간이 길면 실패할 수 있습니다. curl -o나 스트림 복사로 파일에 바로 흘려 쓰는 방식을 권합니다.

동시 실행은 서버 인스턴스당 10건까지이며 tenant를 구분하지 않고 셉니다. 11건째부터 429가 반환되고 목록 조회는 영향을 받지 않습니다. 429는 재시도해도 안전합니다.

Failure
{
"result": false,
"code": 429,
"message": "다른 내보내기가 진행 중입니다. 잠시 뒤 다시 시도해 주세요."
}

에러

코드상태의미
API_KEY_004401인증 실패 - 헤더 누락, 알 수 없는 값, 비활성이거나 만료된 키, 비활성 계정, 다른 tenant의 도메인
AUTH_009403호출한 키가 ADMIN 역할이 아님
REQUEST_001400검증 실패. message에 걸린 필드가 담깁니다. pips 누락, 또는 1 미만 등
RESPONSE_001500거버넌스 조회 실패. 거버넌스 어휘를 벗어난 필터 값도 포함

API가 반환하는 전체 코드 목록은 Errors를 참고합니다.