REST API
HTTP로 파일 업로드, 컬렉션 생성, 공유 관리가 가능합니다. 모든 응답은 JSON이며, 익명 업로드에는 API 키가 필요하지 않습니다.
소개
storage.to API는 CLI, 데스크톱 앱, 웹 업로더은 물론, 여러분이 만들고 싶은 어떤 서드파티 클라이언트에도 동력을 제공합니다.
업로드 흐름은 3단계입니다:
- 초기화 — 파일을 업로드하고 싶다고 알려주세요. Cloudflare R2를 가리키는 프리사인드 URL을 하나 이상 반환합니다.
- R2에 업로드 —
PUT바이트를 프리사인 URL(들)에 직접 전송하세요. 바이트는 저희 서버를 거치지 않습니다. - 확인 — 업로드가 완료되었다고 알려주세요.
File레코드를 생성하고 공유 가능한 URL을 드립니다.
기본 URL
https://storage.to/api
아래 엔드포인트는 모두 이 기본 경로를 기준으로 합니다. 예: POST /upload/init는 POST https://storage.to/api/upload/init을 의미합니다.
인증
대부분의 엔드포인트는 인증이 필요하지 않습니다. 익명 업로드는 핵심 기능입니다.
인증은 선택 사항이며 다음 기능을 해제합니다:
- 내 계정에 연결된 업로드( /dashboard 에서 확인 가능 )
- 프리미엄 기능(영구 파일, 더 큰 저장공간)
- 방문자 토큰 일치가 필요하지 않은 소유권 기반 변경(삭제, 비밀번호 설정, 만료 변경)
Laravel Sanctum 베어러 토큰을 사용합니다. 데스크톱 OAuth 핸드오프 또는 웹 로그인으로 토큰을 발급받은 뒤 다음 형식으로 전송하세요:
Authorization: Bearer <token>
방문자 토큰
익명 클라이언트는 계정 없이도 자신의 업로드에 대한 소유권을 증명할 방법이 필요합니다. 우리는 방문자 토큰 를 사용합니다. 방문자 토큰 는 클라이언트가 한 번 생성해 재사용하는 랜덤 문자열입니다. 모든 요청과 함께 보내세요:
X-Visitor-Token: <random-string>
웹에서는 토큰이 visitor_token 쿠키에 자동으로 저장됩니다. CLI는 이를 ~/.config/storageto/token에 저장합니다( CLI 문서 참조 ).
변경(mutation) 엔드포인트(삭제, 비밀번호 설정, 만료 변경)의 경우, 둘 중 하나는 방문자 토큰이 일치하거나 또는 요청이 파일을 생성한 것과 동일한 IP에서 온 경우에 소유권이 확인됩니다. 둘 다 사라질 수 있습니다(쿠키 삭제, 네트워크 변경). 앞으로는 소유자 토큰가 선호되는 증거입니다.
소유자 토큰
리소스를 생성하는 모든 엔드포인트(/upload/init multipart, /upload/confirm, /upload/reserve, /collection)는 응답에 owner_token를 반환합니다. 이 토큰은 IP나 방문자 토큰과 무관하게, 해당 특정 리소스에 연결된 서명된 소유권 증거입니다.
토큰을 리소스 ID와 함께 저장하고, 어떤 변경(mutation) 요청에도 다음처럼 보내세요:
Authorization: Owner <token>
또는 이미 인증된 세션에서 Authorization: Bearer를 사용 중이라면, 다음처럼 보내세요:
X-Owner-Token: <token>
서버는 기존의 방문자 토큰 + IP 폴백과 함께 소유자 토큰을 유효한 소유권 증거로 받아들입니다. 토큰을 보유한 클라이언트는 네트워크를 바꾸거나 쿠키를 지워도 계속 정상 동작하고, 토큰이 없는 클라이언트는 예전과 똑같이 그대로 동작합니다.
토큰은 리소스가 존재하는 동안만 유지되며, 안전하게 저장할 수 있고, 독립적으로 만료되지 않습니다. 토큰을 잃어버리면 해당 리소스(파일/컬렉션/업로드)의 제어 권한도 잃게 됩니다 — 로컬 비밀번호처럼 취급하세요.
에러
에러는 항상 동일한 형태로 제공됩니다:
{
"success": false,
"error": "Human-readable message"
}
자주 쓰는 HTTP 상태 코드:
| 코드 | 의미 |
|---|---|
200 | 성공. |
201 | 생성됨. |
400 | 잘못된 요청(예: 컬렉션 크기 제한 초과). |
401 | 비밀번호가 필요하거나 비밀번호가 올바르지 않습니다. |
403 | 권한 없음(해당 리소스의 소유자가 아닙니다). |
404 | 리소스를 찾을 수 없거나 만료되었습니다. |
422 | 검증에 실패했거나 플랜/쿼터 제한이 있습니다. |
429 | 요청 제한(rate limit) 또는 업로드 쿼터 초과입니다. |
500 | 서버 오류입니다. 상태를 확인하세요. |
요청 제한
모든 요청 제한은 IP 기준입니다. 429 응답에는 표준 Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining 헤더가 포함됩니다.
| 범위 | 한도 |
|---|---|
| 업로드 시작(init) / 확인(confirm) / 중단(abort) | 60 / 분 |
| 멀티파트 완료 | 500 / 분 |
| 멀티파트 파트 URL | 120 / 분 |
| 배치 시작(init) / 확인(confirm) | 500 / 분 |
| 상태 폴링(파일 & 컬렉션) | 120 / 분 |
| 설정(비밀번호, 만료, 최대 다운로드 횟수) | 30 / 분 |
| 비밀번호 검증 | 10 / 분 |
| 컬렉션 생성 | 30 / 분 |
| 관리(준비 완료, 삭제) | 60 / 분 |
| 썸네일 업로드 | 120 / 분 |
| ShareX 업로드 | 20 / 일 |
| 앱 분석/에러 | 분당 120회 및 60회 |
업로드 쿼터: 익명 클라이언트에는 동시에 두 가지 제한이 걸려 있습니다 — 방문자 토큰당 24시간 100GB 과 IP당 24시간 500GB (IP 제한은 토큰 없는 트래픽과 공유 네트워크를 잡습니다). 둘 중 하나라도 초과하면 자세한 내용이 포함된 429를 받게 됩니다. 이는 업로드 할당량 제한일 뿐입니다 — 다운로드는 무제한이며 제한 없이 제공됩니다(R2 서명 URL에서 직접 제공).
업로드
5GB를 넘는 파일을 포함한 모든 파일의 3단계 업로드 흐름(자동으로 멀티파트 처리). 빠르게 스크린샷처럼 업로드만 필요하다면 대신 ShareX를 참고하세요.
/upload/init
60/min
업로드를 시작하세요. 50MB를 초과하는 파일은 멀티파트 업로드 응답(type: "multipart" 필드)이 제공되고, 그 외에는 단일 프리사인 PUT이 제공됩니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
filename | string · required | 원본 파일명. 최대 255자. |
content_type | string · required | MIME 유형. |
size | integer · required | 바이트 단위 파일 크기. 최소 1. |
/upload/parts
Owner only
120/min
진행 중인 멀티파트 업로드에 대해 추가 파트 URL을 요청합니다. /init이 가지고 있는 파트 수보다 URL을 적게 반환했을 때(또는 만료됐을 때) 사용합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
upload_id | string · required | /init에서 받은 upload_id. |
part_numbers | array<int> · required | URL을 가져올 파트 번호입니다. |
/upload/complete-multipart
Owner only
500/min
모든 파트를 업로드한 뒤 R2에서 멀티파트 업로드를 완료합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
upload_id | string · required | /init에서 받은 upload_id. |
parts | array · required | 각 항목: R2 응답의 { partNumber, etag }. |
/upload/abort
Owner only
60/min
멀티파트 업로드를 취소하고 R2에 남은 부분 데이터를 정리합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
upload_id | string · required | 중단할 업로드입니다. |
/upload/confirm
60/min
업로드가 완료되었는지 확인합니다. 이때 File 레코드를 생성하고 공유 가능한 URL을 반환합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
filename | string · required | 원본 파일명. |
size | integer · required | 바이트 단위 파일 크기. |
content_type | string · required | MIME 유형. |
r2_key | string · required | /init에서 받은 r2_key. |
collection_id | string · optional | 컬렉션에 첨부하기. |
crc32 | integer · optional | 무결성 검증을 위한 CRC32 체크섬. |
file_id | string(9) · optional | 이전에 예약됨된 파일 ID를 이행합니다. |
/file/reserve
60/min
바이트가 준비되기 이전 전에 파일 ID와 공유 가능한 URL을 예약합니다. 먼저 링크를 전달해야 하고, 이후에 업로드를 이행해야 할 때 유용합니다. 소유권은 방문자 토큰 + IP에 연결됩니다. 나중에 /upload/init + /upload/confirm으로 업로드를 마무리하고, 확인 시 file_id를 전달하세요.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
filename | string · optional | 자리표시자 파일명. 기본값은 "Pending". |
content_type | string · optional | 자리표시자 MIME 유형. |
/upload/init-batch
500/min
웹 업로더에 최적화된 /upload/init의 배치 버전입니다. 한 번의 왕복으로 최대 250개 파일을 시작합니다.
웹 업로더에서 내부적으로 사용합니다. 대부분의 클라이언트는 단일 파일 /upload/init을 사용하는 것을 권장합니다.
/upload/confirm-batch
500/min
/upload/confirm의 배치 버전입니다. 한 번의 왕복으로 여러 파일을 확인합니다.
컬렉션
컬렉션은 단일 공유 URL(/c/{id}) 아래에 여러 파일을 묶습니다. 최대 10,000개 파일, 총 25GB까지 가능합니다.
/collection
30/min
새 컬렉션을 생성합니다. 이후 /upload/confirm에서 collection_id를 전달해 파일을 첨부하세요.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
expected_file_count | integer · optional | 예상된 모든 파일이 확인되면 컬렉션을 자동으로 '준비됨' 처리하기 위한 힌트입니다. |
/collection/{id}/status
120/min
컬렉션의 상태를 확인합니다. 또한 예상된 모든 파일이 확인되면 컬렉션을 자동으로 '준비됨' 처리합니다.
/collection/{id}/ready
Owner only
60/min
컬렉션을 다운로드 준비 상태로 표시합니다. 보통 필요하지 않습니다. expected_file_count에 도달하면 컬렉션이 자동으로 준비됩니다.
/collection/{id}
Owner only
60/min
컬렉션과 그 안의 모든 파일을 삭제합니다.
/collection/{id}/password
Owner only
30/min
컬렉션에 비밀번호를 설정합니다. 4–100자 필요합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
password | string · required | 4–100자. |
/collection/{id}/password
Owner only
30/min
컬렉션에서 비밀번호를 제거합니다.
/collection/{id}/verify-password
10/min
비밀번호를 확인합니다. 성공하면 200, 비밀번호가 틀리면 401를 반환합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
password | string · required |
/collection/{id}/expiry
Owner only
30/min
컬렉션의 만료 시간을 변경합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
days | integer · optional | 지금부터 1–7일. 영구(프리미엄 전용)라면 생략하거나 null로 설정하세요. |
/collection/{id}/max-downloads
Owner only
30/min
다운로드 한도 설정(다운로드 N회 후 삭제). 한도에 도달하면 컬렉션이 자동으로 삭제됩니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
max_downloads | integer · optional | 1–1000. 현재 다운로드 횟수를 초과해야 합니다. 한도 제거는 null. |
파일
파일 단위 설정(비밀번호, 만료, 최대 다운로드)은 컬렉션 엔드포인트를 그대로 따릅니다. 소유자만 가능합니다.
/file/{id}/status
120/min
파일이 업로드를 아직 대기 중인지 확인합니다.
/file/{id}
Owner only
60/min
파일을 즉시 삭제합니다.
/file/{id}/thumbnail
Owner only
120/min
동영상 또는 이미지 파일의 썸네일 이미지를 업로드합니다(다운로드 페이지에서 사용). 최대 2MB.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
thumbnail | image · required | 멀티파트 업로드. 최대 2MB. |
/file/{id}/password
Owner only
30/min
파일에 비밀번호를 설정합니다. 4–100자 필요합니다.
/file/{id}/password
Owner only
30/min
파일의 비밀번호를 제거합니다.
/file/{id}/verify-password
10/min
파일의 비밀번호를 확인합니다.
/file/{id}/expiry
Owner only
30/min
파일의 만료 시간을 변경합니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
days | integer · optional | 지금부터 1–7일. 영구(프리미엄 전용)라면 생략하거나 null로 설정하세요. |
/file/{id}/max-downloads
Owner only
30/min
파일의 총 다운로드 횟수를 제한합니다. 한도에 도달하면 자동으로 삭제됩니다.
ShareX 업로드
원샷 업로드 엔드포인트 — 멀티파트 파일을 보내면 공유 가능한 URL을 바로 받습니다. init/confirm 절차가 없습니다. 스크린샷 도구에 딱 맞아요. 전체 설정 가이드는 /ko/docs/sharex에서 확인하세요.
데스크톱 인증
인증된 클라이언트(예: 데스크톱 앱)로서 Sanctum 토큰을 보유한 경우.
/user
Bearer token
인증된 사용자를 반환합니다.
/auth/logout
Bearer token
현재 액세스 토큰을 폐기합니다.
기타
/health
헬스 체크입니다. 데이터베이스, R2 스토리지, Redis 캐시를 핑합니다. 모두 정상(200)인 경우 200를 반환하고, 아니면 503을 반환합니다.
/activity
홈페이지 글로브용 실시간 활동 스트림. Cloudflare 엣지에 캐시됩니다.
/bandwidth/status
60/min
요청자의 현재 업로드 할당량 사용량 — CLI와 데스크톱 앱에서 남은 용량을 표시하는 데 사용됩니다. 인증된 사용자는 응답 형태가 다릅니다. URL 이름과 달리, 이것은 업로드 바이트만 추적하며 다운로드는 집계되지 않습니다.
/app-analytics
120/min
CLI 또는 데스크톱 앱에서 사용 이벤트를 전송하세요.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
app | string · required | desktop, cli 또는 web. |
version | string · optional | 클라이언트 버전입니다. |
event | string · required | 이벤트 이름(예: upload_complete)입니다. |
context | object · optional | 추가 메타데이터입니다. |
/app-errors
60/min
CLI 또는 데스크톱 앱에서 오류 리포트를 전송하세요. 서버에서 중복 제거됩니다 — 같은 오류는 시간당 최대 10개까지입니다.
요청 본문
| 필드 | 유형 | 설명 |
|---|---|---|
app | string · required | desktop, cli 또는 web. |
type | string · required | 오류 클래스/유형입니다. |
message | string · required | 오류 메시지입니다. |
stack | string · optional | 스택 트레이스입니다. |
version, os, os_version, arch, context | various · optional | 진단 메타데이터입니다. |