Files API
파일을 다루는 API입니다. 파일과 폴더에 공통으로 적용되는 리소스 모델, 목록 조회, 버전 이력, 잠금은 Common conventions에서 설명합니다. 이 페이지에서는 파일에만 해당하는 기능을 설명합니다.
Base URL과 scope
/api/external/v1/files
읽기 기능에는 api:read가 필요합니다. 업로드·삭제·이름 변경·이동·복제에는 api:write도 함께 필요합니다.
Intellect용 파일 다운로드
이 endpoint는 Intellect에서 파일을 미리 보거나 열 때 문서 내용을 불러오는 데 사용합니다. 따라서 다운로드(DOWNLOAD) 권한이 아니라 보기(VIEW) 권한을 검사합니다. 일반적인 파일 다운로드는 브라우저에서 다운로드와 같이 다운로드 토큰을 발급받아 브라우저에 전달하세요.
GET /api/external/v1/files/{resourceSeq}/download
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 불러올 파일 |
ss | integer | No | 공유 사용자 seq |
curl -X GET "https://drive.example.com/api/external/v1/files/{resourceSeq}/download?ss=21" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY"
성공하면 JSON 공통 구조 대신 파일을 반환합니다.
HTTP 200 OK
Content-Type: {contentType}
Content-Disposition: attachment; filename={fileName}
Content-Length: {byte}
브라우저에서 다운로드
서버가 아니라 사용자의 브라우저에서 파일을 내려받게 하려면, 먼저 유효 시간이 짧은 다운로드 토큰을 발급받은 뒤 반환된 경로를 브라우저에 전달합니다. 토큰에 다운로드 권한이 포함되어 있으므로 두 번째 요청에는 API Key가 필요하지 않습니다.
GET /api/external/v1/files/{resourceSeq}/download-token
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 내려받을 파일 |
ss | integer | No | 공유 사용자 seq |
{
"result": true,
"code": 200,
"message": "OK",
"data": {
"linkUrl": "/files/download?dt={token}"
}
}
linkUrl은 상대 경로입니다. 브라우저는 사용자가 접속한 도메인을 기준으로 이 경로를 요청합니다. 따라서 두 번째
요청은 /api/external/v1 호출이 아니며 Authorization 헤더도 보내지 않습니다.
GET https://drive.example.com/files/download?dt={dt}
위와 같은 Content-Type, Content-Disposition, Content-Length 헤더와 함께 파일 스트림을 반환합니다.
/api/external/v1/files/download를 직접 호출하려면 API Key가 필요하므로 브라우저에서 다운로드할 때는 사용할 수
없습니다.
여러 리소스를 하나의 ZIP 파일로 내려받는 방법은 Common conventions의 여러 리소스 다운로드를 참고하세요.
파일 미리보기
GET /api/external/v1/files/{resourceSeq}/view
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 미리 볼 파일 |
ss | integer | No | 공유 사용자 seq |
변환된 미리보기 이미지가 아니라 원본 파일을 스트림으로 반환합니다.
HTTP 200 OK
Content-Type: {contentType}
Content-Disposition: attachment; filename={fileName}
Content-Length: {byte}
파일 업로드
api:write 필요POST /api/external/v1/files
파일은 multipart/form-data 형식으로 보냅니다.
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
file | file | Yes | 업로드할 파일 |
pfs | long | No | 부모 폴더 seq. st가 duplicate일 때만 사용하며, 생략하면 최상위 폴더에 업로드. 공유받은 사용자가 업로드할 때 필수 |
ss | integer | No | 공유 사용자 seq. 본인 드라이브에 업로드하면 null |
st | enum | No | 저장 방식. 대소문자 구분 없음 - duplicate(기본값)는 번호를 붙인 새 파일로 추가, version은 rs의 새 버전으로 추가, overwrite는 rs를 덮어씀 |
rs | long | No | 대상 리소스 seq. st가 version 또는 overwrite일 때 필수이며, 없으면 RESOURCE_014로 실패 |
curl -X POST "https://drive.example.com/api/external/v1/files" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: multipart/form-data" \
-F "file=@report.docx" \
-F "pfs=1"
{
"result": true,
"code": 201,
"message": "Created",
"data": {
"resourceSeq": 283,
"resourceName": "report.docx"
}
}
version과 overwrite는 rs로 지정한 파일을 기준으로 저장하므로 pfs를 사용하지 않습니다. 계정의 저장 용량을
초과하면 QUOTA_003으로 실패합니다.
파일 이름 변경
api:write 필요PATCH /api/external/v1/files/{resourceSeq}/rename
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 이름을 바꿀 파일 |
rn | string | Yes | 새 이름 |
ncp | enum | No | 이름 중복 처리 방식. 대소문자 구분 없음 - NONE(기본값)은 중복된 이름을 RESOURCE_006으로 거부, AUTO는 이름에 번호를 붙임 |
pfs | long | No | 부모 폴더 seq. ncp=NONE이고 파일이 최상위 폴더에 있지 않으면 필수. 이 폴더 안에서 이름 중복을 검사하며, 생략하면 최상위 폴더를 기준으로 검사. ncp가 AUTO면 사용하지 않음 |
ss | integer | No | 공유 사용자 seq |
curl -X PATCH "https://drive.example.com/api/external/v1/files/{resourceSeq}/rename" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ss": 21, "rn": "quarterly-report", "ncp": "AUTO"}'
응답의 data.name은 실제로 적용된 이름이며 확장자를 포함하지 않습니다. 예를 들어 rn이 test11.docx면 name은
test11입니다. AUTO로 번호가 붙은 경우에는 rn과 다를 수 있습니다.
파일 이동
api:write 필요POST /api/external/v1/files/{resourceSeq}/move
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 이동할 파일 |
ts | integer | No | 대상 사용자 seq. 호출한 계정이 리소스를 공유한 사용자가 아니면 필수 |
pfs | long | No | 이동할 폴더 seq. 호출한 계정이 리소스를 공유한 사용자가 아니면 필수 |
ss | integer | No | 공유 사용자 seq |
curl -X POST "https://drive.example.com/api/external/v1/files/{resourceSeq}/move" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ts": 1, "pfs": 367}'
파일 복제
api:write 필요POST /api/external/v1/files/{resourceSeq}/copy
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 복제할 파일 |
ts | integer | No | 복제 대상 사용자 seq. 호출한 계정이 리소스를 공유한 사용자면 null |
pfs | long | No | 복제할 폴더 seq. 호출한 계정이 리소스를 공유한 사용자가 아니면 필수 |
ss | integer | No | 공유 사용자 seq. 호출한 계정이 리소스를 공유한 사용자면 null |
선택 헤더인 Accept-Language에 따라 복제본 이름에 붙는 문구의 언어가 정해집니다.
| 언어 | 복제본 이름 |
|---|---|
ko | {name}의 사본.{ext} |
en | Copy of {name}.{ext} |
es | Copia de {name}.{ext} |
성공하면 201 Created와 복제본의 resourceSeq를 반환합니다. 계정의 저장 용량을 초과하면 QUOTA_003으로 실패합니다.
파일 삭제
api:write 필요PATCH /api/external/v1/files/{resourceSeq}/delete
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 삭제할 파일 |
본인 소유 파일만 삭제할 수 있으므로 ss 파라미터가 없습니다. 공유받은 파일은 RESOURCE_005로, 잠긴 파일은
RESOURCE_LOCK_ASPECT_002로 실패합니다.
삭제한 파일은 바로 제거되지 않고 휴지통으로 이동합니다. 휴지통 목록 조회·복원·영구 삭제는 Users를 참고하세요.
새 Office 문서 생성
api:write 필요파일을 업로드하지 않고 기본 제공 템플릿으로 빈 Word·Spreadsheet·Presentation·노트 문서를 만듭니다.
POST /api/external/v1/documents
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
tt | enum | Yes | 템플릿 유형 - word, excel, ppt, note |
pfs | long | No | 부모 폴더 seq. 본인 드라이브에서 생략하면 최상위 폴더에 생성. 공유 폴더에 만들 때(ss가 본인이 아닐 때) 필수이며, 생략하면 PERMISSION_002로 실패 |
ss | integer | No | 공유 사용자 seq. 본인 드라이브에 만들면 null |
Accept-Language 헤더에 따라 사용할 템플릿과 생성되는 파일 이름이 정해집니다. 한국어(ko)·영어(en)·스페인어(es)
템플릿을 제공하며, 그 외 언어를 지정하면 템플릿이 없어 FILE_002로 실패합니다.
| 언어 | 파일 이름 |
|---|---|
ko | 새 문서.docx, 새 프레젠테이션.pptx, 새 스프레드시트.xlsx, 새 노트.tfi |
en | New Document.docx와 다른 유형의 영어 이름 |
es | Nuevo documento.docx와 다른 유형의 스페인어 이름 |
같은 위치에 같은 이름의 파일이 있으면 새 문서 (1).docx처럼 번호를 붙인 이름으로 생성합니다.
curl -X POST "https://drive.example.com/api/external/v1/documents" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ss": 21, "pfs": 5, "tt": "word"}'
{
"result": true,
"code": 201,
"message": "Created",
"data": {
"resourceSeq": 4699,
"userSeq": 1
}
}
data.userSeq는 문서가 생성된 드라이브의 소유자 seq입니다. 공유 폴더에 만들면 요청한 계정이 아니라 폴더를 공유한
사용자의 seq입니다.
대상 폴더의 업로드(UPLOAD) 권한을 검사합니다. 실패하면 공통 실패 구조로 응답합니다.
| Status | errorCode | 원인 |
|---|---|---|
| 400 | REQUEST_001 | 요청 값 검증 실패 |
| 403 | PERMISSION_001 | 대상 폴더가 호출한 계정에 공유되지 않음 |
| 403 | PERMISSION_002 | 업로드 권한 부족, 또는 공유 폴더에 pfs 누락 |
| 404 | RESOURCE_005 | 대상 폴더가 존재하지 않음 |
| 404 | FILE_002 | 요청한 언어의 템플릿이 없음 |
| 400 | QUOTA_003 | 저장 용량 부족 |
{
"result": false,
"code": 404,
"errorCode": "FILE_002",
"message": "{message}"
}
편집기 세션 endpoint
web-office endpoint는 브라우저에서 문서를 편집하는 세션에 사용합니다. 편집기는 이 endpoint로 문서 메타데이터를
조회하고, 파일을 가져오고, 편집하는 동안 문서를 잠그고, 변경 내용을 저장하고, 잠금을 해제합니다. Thinkfree 편집기를
직접 호스팅할 때 사용합니다. SDK로 편집기를 제품에 포함하려면 Editor SDK를
참고하세요.
GET /api/external/v1/web-office/{loginUserSeq}/info
GET /api/external/v1/web-office/{loginUserSeq}/get
POST /api/external/v1/web-office/{loginUserSeq}/lock
PUT /api/external/v1/web-office/{loginUserSeq}/put
POST /api/external/v1/web-office/{loginUserSeq}/unlock
loginUserSeq는 API Key에서 가져오는 값이 아니라 호출하는 쪽에서 직접 지정하는 값입니다. 서버는 지정한 사용자가
API Key와 같은 tenant에 속하는지만 확인하며, API Key를 발급받은 계정과 같은지는 확인하지 않습니다. 따라서 API Key를
가진 쪽은 이 endpoint로 해당 tenant의 모든 사용자 권한으로 요청할 수 있습니다. 이 endpoint를 호출할 수 있는 키는
tenant 전체 권한을 가진 키로 관리하세요. 브라우저가 보낸 loginUserSeq를 그대로 전달하지 말고, 어떤 사용자로
요청할 수 있는지 서버에서 판단해야 합니다.
편집기 세션에 사용하는 다섯 endpoint는 모두 scope 검사에서 제외됩니다. api:read만 부여된 키로도 저장 상태를
변경하는 lock, put, unlock을 호출할 수 있습니다.
공통 파라미터
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
loginUserSeq | long | Yes | path 파라미터 - 편집 세션을 사용할 사용자 |
docId | string | Yes | 문서 식별자. 리소스 소유자 seq와 리소스 seq를 하이픈으로 이은 값({ownerUserSeq}-{resourceSeq}, 예: 21-512) |
app | enum | Yes | 편집기 화면. 예: WORD_EDITOR, CELL_VIEWER, SHOW_WATCHER. info, get, put에 필수 |
user_id | string | Yes | 로그인 계정 이름. info, get, put에 필수 |
lang | string | No | 세션 언어. 예: ko_KR. 권한 오류 메시지와 익명 사용자 표시 이름의 언어(ko, en, es)를 결정 |
app 값은 애플리케이션과 모드를 조합한 15가지입니다. 애플리케이션은 WORD, CELL, SHOW, HWP, PDF이고, 모드는 EDITOR, VIEWER, WATCHER입니다.
*_EDITOR는 편집(EDIT) 권한을, *_VIEWER와 *_WATCHER는 보기(VIEW) 권한을 검사합니다. 이 검사는 info, get,
put에 적용되며, 문서 소유자가 요청하면 검사하지 않습니다. 공개 링크로 접속한 익명 사용자는 PUBLIC_LINK로 공유된
문서에만 접근할 수 있습니다.
문서 메타데이터 조회
GET /api/external/v1/web-office/{loginUserSeq}/info
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
type | enum | No | 요청 유형. 대소문자 구분 없음 - open(문서 열기), download(원본 다운로드), pdf_download(PDF로 변환해 다운로드), print(인쇄). download와 pdf_download는 감사 로그에 다운로드로 기록됨 |
JSON이 아니라 루트 요소가 <property>인 XML 문서를 반환합니다. 요청할 때 권한을 검사하며, 권한이 없으면 HTTP 403을
반환합니다. read, write, locked 필드는 실제 권한이나 잠금 상태와 관계없이 고정된 값입니다.
| 필드 | 설명 |
|---|---|
type | 항상 file |
name | 파일 이름. CDATA로 감싸서 반환 |
modified | 마지막 수정 일시. epoch 밀리초 |
read, write | 항상 true |
locked | 항상 false |
size | 파일 크기(byte) |
fullName | 사용자 표시 이름 |
userCursorName | 요청한 user_id 값. 익명 사용자는 lang 언어로 된 익명 동물 이름 |
profileImage | 사용자 프로필 이미지 |
cursorColor | 커서 색상. 요청할 때마다 무작위로 지정 |
revision | modified와 같은 값 |
currentVersionNumber | 현재 버전 번호 |
curl -X GET "https://drive.example.com/api/external/v1/web-office/{loginUserSeq}/info?app=WORD_EDITOR&user_id={user_id}&docId=21-512&lang=ko_KR&type=open" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY"
<property>
<type>file</type>
<name><![CDATA[report.docx]]></name>
<modified>1758240000000</modified>
<read>true</read>
<write>true</write>
<locked>false</locked>
<size>24576</size>
<fullName>{fullName}</fullName>
<userCursorName>{user_id}</userCursorName>
<profileImage>{profileImage}</profileImage>
<cursorColor>{cursorColor}</cursorColor>
<revision>1758240000000</revision>
<currentVersionNumber>3</currentVersionNumber>
</property>
리소스가 없으면 HTTP 200과 함께 일반 텍스트 NotExist를 반환합니다. 따라서 상태 코드와 응답 본문을 함께
확인하세요.
문서 가져오기
GET /api/external/v1/web-office/{loginUserSeq}/get
파일을 application/octet-stream으로 스트리밍합니다. *_VIEWER 요청은 감사 로그에 미리보기로, 그 외 app 값의
요청은 문서 열기로 기록됩니다.
curl -X GET "https://drive.example.com/api/external/v1/web-office/{loginUserSeq}/get?app=WORD_EDITOR&user_id={user_id}&docId=21-512" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-o report.docx
문서 저장
PUT /api/external/v1/web-office/{loginUserSeq}/put
문서 내용을 application/octet-stream으로 보냅니다. 성공하면 docId를 일반 텍스트로 반환합니다.
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
app, user_id, docId | - | Yes | 공통 파라미터 참고 |
size | long | Yes | 업로드할 문서의 바이트 크기 |
type | enum | No | 저장 사유. 대소문자 구분 없음. save, autoPut, close, 그 밖의 값이거나 생략하면 새 버전으로 저장. saveAs와 autoSave는 저장하지 않고 docId만 반환 |
openTimestamp | long | No | 전달할 수 있지만 서버에서 사용하지 않음 |
다른 web-office endpoint와 달리 필수 파라미터가 없거나 형식이 잘못되면 400 REQUEST_001을 JSON으로 반환합니다.
저장 용량을 초과하면 QUOTA_003이 아니라 500 Internal Server Error를 반환합니다.
curl -X PUT "https://drive.example.com/api/external/v1/web-office/{loginUserSeq}/put?app=WORD_EDITOR&user_id={user_id}&docId=21-512&size=24576&type=save" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary "@report.docx"
문서 잠금과 잠금 해제
POST /api/external/v1/web-office/{loginUserSeq}/lock
POST /api/external/v1/web-office/{loginUserSeq}/unlock
두 endpoint 모두 docId만 사용하며 app, user_id, lang은 필요하지 않습니다. 성공하면 본문 없이 200 OK를
반환합니다. docId에 해당하는 리소스가 없으면 HTTP 400과 일반 텍스트 메시지를 반환합니다.
curl -X POST "https://drive.example.com/api/external/v1/web-office/{loginUserSeq}/lock?docId=21-512" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY"
편집기 세션 오류
이 endpoint의 일부 실패 응답에는 errorCode나 본문이 없어 Errors의 코드로 원인을 구분할 수 없습니다.
상태 코드와 응답 본문을 함께 확인하세요.
| 경우 | 응답 |
|---|---|
필수 파라미터 누락 또는 app 값 오류 - info, get, lock, unlock | HTTP 500, 본문 없음 |
필수 파라미터 누락 또는 형식 오류 - put | 400 REQUEST_001, JSON |
loginUserSeq에 해당하는 사용자 없음 | 404 USER_005, JSON |
| API Key와 다른 tenant의 사용자 | 403 AccessDenied, 일반 텍스트 |
docId 형식 오류 | 500 Internal Server Error, errorCode 없는 JSON |
| 문서 접근 권한 없음 | 403, lang 언어로 된 권한 오류 메시지(일반 텍스트) |
리소스 없음 - info | 200 NotExist, 일반 텍스트 |
리소스 없음, 파일 읽기·저장 실패, 용량 초과 - get, put | 500 Internal Server Error, errorCode 없는 JSON |
리소스 없음 - lock, unlock | 400, 일반 텍스트 "리소스 잠금에 실패했습니다." / "리소스 잠금 해제에 실패했습니다." |
오류
files와 documents endpoint는 실패하면 공통 실패 구조로 응답합니다.
{
"result": false,
"code": 400,
"errorCode": "QUOTA_003",
"message": "{message}"
}
| Status | errorCode | 원인 |
|---|---|---|
| 400 | RESOURCE_001 | 삭제 실패 |
| 404 | RESOURCE_005 | 리소스를 찾을 수 없음 |
| 409 | RESOURCE_006 | 이름 중복 |
| 400 | RESOURCE_014 | rs 누락 |
| 423 | RESOURCE_LOCK_ASPECT_002 | 리소스가 잠겨 있음 |
| 400 | QUOTA_003 | 저장 용량 부족 |
| 500 | RESPONSE_001 | 서버 오류 |
전체 오류 코드는 Errors를, web-office endpoint의 오류는 편집기 세션 오류를
참고하세요.