공통 규약
모든 Document Management API 요청은 같은 base URL, 인증 헤더, scope 검사 방식과 응답 구조를 사용합니다. 이 페이지를 먼저 읽은 뒤 각 endpoint 페이지에서 필요한 기능을 확인하세요.
Base URL
이 reference에서 설명하는 모든 endpoint는 다음 경로 아래에 있습니다.
https://drive.example.com/api/external/v1
drive.example.com은 예시 주소입니다. 운영 중인 Thinkfree Drive에서 해당 tenant에 할당된 서브도메인으로 바꿔
사용하세요. 각 endpoint 페이지에는 이 경로를 기준으로 한 상대 경로를 표기합니다.
인증
모든 요청은 Authorization 헤더에 API Key를 bearer token으로 담아 인증합니다.
Authorization: Bearer replace-with-your-USER-API-KEY
API Key는 관리자가 Thinkfree Drive 관리 화면의 API Key 메뉴에서 발급합니다. API로 키를 발급·조회·폐기하는 방법은 Authentication을 참고하세요.
API Key는 서버의 secret 저장소에 보관하세요. 브라우저 JavaScript, 모바일 앱, URL, 소스 코드 저장소, 로그에는 포함하지 않습니다. 키가 노출되었을 가능성이 있으면 즉시 폐기한 뒤 새 키를 발급받아 사용하세요.
API Key는 발급된 tenant에서만 사용할 수 있습니다. 키가 속한 tenant와 요청한 host의 tenant가 다르면 요청이
REQUEST_006으로 실패합니다.
Scope
각 API Key에는 아래 두 scope 중 하나 또는 둘 다가 부여됩니다. 서버는 endpoint를 실행하기 전에 scope를 검사합니다.
| Scope | 허용 범위 |
|---|---|
api:read | 읽기 동작 - 목록, 조회, 검색, 다운로드 |
api:write | 쓰기 동작 - 업로드, 이름 변경, 이동, 복제, 삭제, 복원, 설정 변경 |
쓰기 endpoint를 호출하려면 api:read와 함께 api:write가 필요합니다. api:write가 필요한 기능은 각 endpoint
페이지에 표시되어 있습니다. /resources 아래에서는 버전 복원, 버전 삭제, 버전 전체 삭제에만 api:write가
필요합니다. 잠금과 잠금 해제를 포함한 이 페이지의 나머지 리소스 기능은 api:read만으로 호출할 수 있습니다.
API Key에는 MCP 접근을 위한 mcp:read, mcp:write도 함께 부여되며, 발급할 수 있는 scope 조합은 두 가지입니다.
자세한 내용은 Authentication을 참고하세요.
admins, super-admin 아래의 endpoint와 users, notifications, config, web-office, pinned-folders,
API Key 관리 endpoint는 공통 인증 외에 scope를 따로 검사하지 않습니다. 따라서 api:read만 부여된 키로도 이
endpoint의 쓰기 기능을 호출할 수 있습니다. 이 endpoint에 대한 접근은 scope가 아니라 키를 누구에게 발급하는지로
통제합니다.
응답 구조
성공
대부분의 endpoint는 아래 공통 구조로 응답합니다. endpoint별 응답 데이터는 data에 담기며, 반환할 값이 없으면
data가 생략됩니다.
| Field | Type | Required | 의미 |
|---|---|---|---|
result | boolean | Yes | 성공이면 true |
code | integer | Yes | 결과의 HTTP 상태 코드, 예: 200, 201 |
message | string | Yes | 짧은 상태 문자열, 예: OK, Created |
data | object or array | No | endpoint별 응답 데이터. 반환할 값이 없으면 생략 |
{
"result": true,
"code": 201,
"message": "Created",
"data": {
"resourceSeq": 283,
"resourceName": "report.docx"
}
}
{
"result": true,
"code": 200,
"message": "OK"
}
실패
| Field | Type | 의미 |
|---|---|---|
result | boolean | false |
code | integer | HTTP 상태 코드 |
errorCode | string | RESOURCE_005와 같은 고정된 오류 코드 |
message | string | 사용자에게 표시할 수 있는 실패 메시지 |
{
"result": false,
"code": 404,
"errorCode": "RESOURCE_005",
"message": "데이터를 찾을 수 없습니다."
}
오류 처리는 message가 아니라 errorCode를 기준으로 구현하세요. message 문구는 언어에 따라 다르며 변경될 수
있습니다. 전체 오류 코드는 Errors를 참고하세요.
공통 구조를 쓰지 않는 endpoint
이 페이지 마지막에 설명하는 빌드 정보 endpoint는 result, data 없이 응답 객체만 반환합니다. 실패 응답은 공통
실패 구조를 따릅니다. 공통 구조를 사용하지 않는 endpoint는 빌드 정보 endpoint뿐입니다.
날짜
sd, ed처럼 날짜를 받는 요청 파라미터는 YYYY-MM-DD 형식을 사용합니다. resourceRegisterDate,
resourceUpdateDate처럼 응답에 포함되는 시각은 YYYY-MM-DD HH:mm:ss.SSS 형식입니다.
축약 파라미터 이름
이 API의 query·body 파라미터는 축약된 이름을 사용합니다. 같은 이름은 모든 endpoint에서 같은 의미입니다.
| 이름 | Type | 의미 |
|---|---|---|
ss | integer | 공유 사용자 seq. 호출한 계정이 공유 리소스의 소유자가 아니면 필수. 본인 소유 리소스면 null |
ts | integer | 이동·복제 대상 사용자 seq |
rs | long | 리소스 seq. 요청 body에서 리소스를 지정할 때 사용 |
pfs | long | 부모 폴더 seq |
rn | string | 리소스 이름 |
rt | enum | 리소스 유형 - FILE 또는 FOLDER |
sk | string | 파일·폴더 이름에 대한 검색 키워드 |
sb | enum | 정렬 기준 - name, size, update, open |
so | enum | 정렬 순서 - asc, desc |
pi | integer | 페이지 번호, 최소 1 |
ps | integer | 페이지 크기, 최소 1 |
ci | long | cursor id - 이전 페이지 마지막 항목의 resourceSeq |
cv | object | cursor value - 이전 페이지 마지막 항목의 정렬 기준 값 |
ct | enum | cursor type - 이전 페이지 마지막 항목의 resourceType |
dt | string | download-token endpoint가 발급한 다운로드 토큰 |
페이지네이션
이 API는 두 가지 페이지네이션 방식을 사용합니다.
cursor 페이지네이션은 리소스 목록 조회에 사용합니다. ps로 페이지 크기를 지정하고, 첫 요청에서는 cursor 파라미터를
생략합니다. 다음 페이지부터는 이전 응답의 cursor 값을 ci, cv, ct로 보냅니다. sb와 so는 반드시 함께
보내야 하며, 둘 다 생략하면 name 오름차순으로 정렬합니다.
{
"result": true,
"code": 200,
"message": "OK",
"data": [],
"pageSize": 10,
"nextCursor": 40094,
"nextCursorValue": "Sample folder",
"nextCursorType": "FOLDER",
"hasNext": true
}
번호 페이지네이션은 버전 이력과 대부분의 관리자 목록 조회에 사용합니다. pi와 ps를 보내면 응답에 totalCount,
pageIndex, pageSize가 포함됩니다.
리소스 모델
파일과 폴더는 모두 리소스이며, resourceSeq로 식별하고 resourceType으로 구분합니다. 파일과 폴더는 같은 구조를
사용하지만 목록 조회와 단건 조회의 응답 필드는 일부 다릅니다. 두 응답에 공통으로 포함되는 필드는 다음과 같습니다.
| Field | Type | 의미 |
|---|---|---|
resourceSeq | long | 파일 또는 폴더의 고정 식별자 |
resourceType | enum | FILE 또는 FOLDER |
parentFolderSeq | long | 상위 폴더. 드라이브 최상위면 null |
resourceName | string | 파일 또는 폴더 이름 |
ownerId | string | 소유자 계정 id |
sizeByte | long | 바이트 크기. 폴더면 null |
canView | boolean | 호출한 계정이 이 리소스를 열 수 있는지 여부 |
canEdit | boolean | 호출한 계정이 이 리소스를 수정할 수 있는지 여부 |
canDownload | boolean | 호출한 계정이 이 리소스를 다운로드할 수 있는지 여부 |
canDelete | boolean | 호출한 계정이 이 리소스를 삭제할 수 있는지 여부 |
canShare | boolean | 호출한 계정이 이 리소스를 공유할 수 있는지 여부 |
resourceRegisterDate | string | 생성 시각 |
resourceUpdateDate | string | 마지막 수정 시각 |
한쪽 응답에만 포함되는 필드는 다음과 같습니다.
| Field | Type | 반환 위치 | 의미 |
|---|---|---|---|
isShared | boolean | 목록 | 공유 여부 |
isLocked | boolean | 단건 조회 | 편집 잠금 여부 |
parentFolderName | string | 단건 조회 | 상위 폴더 이름 |
리소스 동작
아래 기능은 파일과 폴더에 공통으로 사용할 수 있습니다.
리소스 목록
GET /api/external/v1/resources
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
st | enum | Yes | 검색 범위 - 내 드라이브는 MY, 볼 수 있는 전체는 ALL |
ps | integer | Yes | 페이지 크기, 최소 1 |
ss | integer | No | 공유 사용자 seq. null이거나 키 소유자 본인의 seq면 본인 기준으로, 다른 값이면 해당 공유자 기준으로 조회. st가 ALL이면 적용되지 않음 |
sk | string | No | 이름 검색 키워드. st가 ALL일 때만 적용 |
pfs | long | No | 부모 폴더 seq. 공유받은 사용자가 호출할 때 필수 |
rt | enum | No | FILE 또는 FOLDER |
oi | string | No | 소유자 id, 최대 254자 |
sd | date | No | 수정일 범위 시작, YYYY-MM-DD. ed를 함께 보내지 않으면 무시 |
ed | date | No | 수정일 범위 종료, YYYY-MM-DD. sd를 함께 보내지 않으면 무시 |
ft | enum | No | 파일 유형 - document, spreadsheet, presentation, pdf, image, note |
sb | enum | No | 정렬 기준. so를 함께 보내지 않으면 무시 |
so | enum | No | 정렬 순서. sb를 함께 보내지 않으면 무시 |
ci | long | No | 이전 페이지의 cursor id |
cv | object | No | 이전 페이지의 cursor value |
ct | enum | No | 이전 페이지의 cursor type |
sb와 so를 보내지 않으면 리소스 이름 오름차순으로 정렬합니다.
curl -X GET "https://drive.example.com/api/external/v1/resources?st=MY&ps=10" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY"
리소스 단건 조회
GET /api/external/v1/resources/{resourceSeq}
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 조회할 리소스 |
ss | integer | No | 공유 사용자 seq |
d | boolean | No | true면 삭제된 리소스를, false면 삭제되지 않은 리소스를 조회. 생략하면 삭제되지 않은 리소스를 조회 |
이름 중복 확인
GET /api/external/v1/resources/exists
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
rn | string | Yes | 확인할 리소스 이름 |
rt | enum | Yes | FILE 또는 FOLDER |
pfs | long | No | 부모 폴더 seq |
ss | integer | No | 공유 사용자 seq |
같은 이름의 리소스가 이미 있으면 해당 리소스의 resourceSeq를 반환합니다.
폴더 트리 조회
GET /api/external/v1/resources/tree
호출한 계정이 볼 수 있는 모든 폴더를 resourceSeq, resourceName, parentFolderSeq, resourceType을 가진
1차원 배열로 반환합니다. 트리는 parentFolderSeq를 기준으로 구성하며, 이 값이 null이면 최상위 폴더입니다.
공유 링크 조회
GET /api/external/v1/resources/{resourceSeq}/link
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 링크를 만들 리소스 |
ss | integer | No | 공유 사용자 seq. 호출한 계정이 리소스를 공유한 사용자면 null, 그렇지 않으면 필수 |
data.linkUrl에 https://drive.example.com/s/{token} 형식의 공유 URL을 반환합니다. 이 URL을 브라우저에서 열면
Thinkfree Drive 웹 앱이 실행되고, 웹 앱이 /api/v1/shares/link/{token}으로 토큰을 확인합니다.
여러 리소스를 한 번에 내려받기
리소스를 두 개 이상 내려받으려면 API를 두 번 호출합니다. 먼저 다운로드 토큰을 발급받습니다.
POST /api/external/v1/resources/download-token
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
rl | array | Yes | 내려받을 리소스 목록. 각 항목은 ss와 rs를 가진 객체 |
curl -X POST "https://drive.example.com/api/external/v1/resources/download-token" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/json" \
-d '{"rl": [{"ss": 41, "rs": 25068}, {"ss": 41, "rs": 25013}]}'
그다음 브라우저에서 반환된 경로를 열면 ZIP 파일이 스트리밍 방식으로 다운로드됩니다.
GET /api/external/v1/resources/download?dt={dt}
리소스 잠금과 잠금 해제
PATCH /api/external/v1/resources/{resourceSeq}/lock
PATCH /api/external/v1/resources/{resourceSeq}/unlock
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 잠그거나 잠금 해제할 리소스 |
ss | integer | No | body 파라미터 - 공유 사용자 seq. 호출한 계정이 리소스 소유자면 null |
두 endpoint 모두 ko-kr, en-us와 같은 Accept-Language 헤더를 선택적으로 받으며, 이 값에 따라 message의
언어가 정해집니다. 잠금에 실패하면 RESOURCE_015를, 잠금 해제에 실패하면 RESOURCE_016을 반환합니다.
curl -X PATCH "https://drive.example.com/api/external/v1/resources/25068/lock" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Accept-Language: en-us" \
-H "Content-Type: application/json" \
-d '{"ss": null}'
{
"result": false,
"code": 400,
"errorCode": "RESOURCE_015",
"message": "리소스 잠금에 실패했습니다."
}
버전 이력
파일은 버전 이력을 보관합니다. 현재 버전은 versionType이 CURRENT이고 resourceVersionSeq가 null이며,
이전 버전의 versionType은 HISTORY입니다.
버전 목록
GET /api/external/v1/resources/{resourceSeq}/versions
| 파라미터 | Type | 필수 | 설명 |
|---|---|---|---|
resourceSeq | long | Yes | path 파라미터 - 이력을 조회할 파일 |
pi | integer | Yes | 페이지 번호, 최소 1 |
ps | integer | Yes | 페이지 크기, 최소 1 |
ss | integer | No | 공유 사용자 seq. 공유받지 않은 파일이면 null, 공유받은 파일이면 필수 |
각 항목에는 versionNumber, sizeByte, versionType, versionRegisterDate와 함께 해당 버전을 만든 계정(userSeq,
userName, tenantSeq, tenantName)과 파일 소유자(ownerSeq, ownerName, ownerStatus, ownerTenantSeq,
ownerTenantName) 정보가 포함됩니다. CURRENT 항목의 resourceVersionSeq는 null입니다.
버전 다운로드
GET /api/external/v1/resources/{resourceSeq}/versions/{resourceVersionSeq}/download-token
GET /api/external/v1/resources/{resourceSeq}/versions/download?dt={dt}
해당 버전의 다운로드 토큰을 발급받은 뒤 브라우저에서 반환된 경로를 열면 파일이 다운로드됩니다. 토큰 요청의 ss는
버전 목록 조회와 같은 규칙을 따릅니다.
버전 복원
api:write 필요POST /api/external/v1/resources/{resourceSeq}/versions/{resourceVersionSeq}/restore
요청 body에 ss를 담은 JSON을 보내야 합니다. 공유받지 않은 파일이면 null을, 공유받은 파일이면 공유 사용자 seq를
보냅니다. body를 생략하면 400으로 실패합니다.
curl -X POST "https://drive.example.com/api/external/v1/resources/25068/versions/7/restore" \
-H "Authorization: Bearer replace-with-your-USER-API-KEY" \
-H "Content-Type: application/json" \
-d '{"ss": null}'
지정한 버전을 현재 버전으로 복원하고 201 Created를 반환합니다. 복원에 실패하면 RESOURCE_VERSION_006(500)을
반환합니다.
버전 삭제
api:write 필요DELETE /api/external/v1/resources/{resourceSeq}/versions/{resourceVersionSeq}
DELETE /api/external/v1/resources/{resourceSeq}/versions
첫 번째 endpoint는 지정한 버전 하나를, 두 번째 endpoint는 버전 이력 전체를 삭제합니다. 두 endpoint 모두 현재 버전은 삭제하지 않습니다.
리소스와 버전 오류
위 endpoint는 공통 실패 구조로 응답합니다. 전체 오류 코드는 Errors를 참고하세요.
| 코드 | 상태 | 발생 조건 |
|---|---|---|
REQUEST_001 | 400 | 요청 값 검증 실패 |
REQUEST_006 | 403 | 다른 tenant의 키로 요청 |
AUTH_009 | 403 | 키가 유효하지 않거나 필요한 scope가 없음 |
RESOURCE_005 | 404 | 리소스를 찾을 수 없음 |
RESOURCE_015 | 400 | 잠금 실패 |
RESOURCE_016 | 400 | 잠금 해제 실패 |
RESOURCE_VERSION_002 | 400 | 버전 삭제 실패 |
RESOURCE_VERSION_003 | 404 | 버전을 찾을 수 없음 |
RESOURCE_VERSION_006 | 500 | 버전 복원 실패 |
RESPONSE_001 | 500 | 예기치 않은 서버 오류 |
빌드 정보
아래 두 endpoint는 실행 중인 Thinkfree Drive의 빌드 정보를 반환합니다. 공통 구조 없이 응답 객체만 반환하며,
api:read와 api:write 중 하나만 있어도 호출할 수 있습니다.
GET /api/external/v1/build
GET /api/external/v1/build/summary
{
"applicationName": "Thinkfree-Drive",
"buildFileName": "Thinkfree-Drive-1.5.0_202609140944",
"version": "1.5.0",
"profile": "prod",
"buildTime": "2026-09-14 09:44"
}
| Field | Type | 의미 |
|---|---|---|
applicationName | string | 항상 Thinkfree-Drive |
buildFileName | string | 애플리케이션 이름·버전·빌드 시각으로 구성된 빌드 파일 이름 |
version | string | 애플리케이션 버전 |
profile | string | 실행 프로파일 - local, dev, stage, prod |
buildTime | string | 빌드 시각, yyyy-MM-dd HH:mm |
GET /api/external/v1/build/summary는 버전과 빌드 시각을 이어 붙인 표시용 문자열 하나를 buildInfo에 담아
반환합니다.