api.file.kiwi v2
Public API for file.kiwi — create WebFolders, register initial files, and upload E2E encrypted chunks programmatically.
Base URL: https://api.file.kiwi
This document describes the v2 API. For the v1 API, see v1 API documentation.
Overview
v2 supports two folder creation flows through the same endpoint:
Create a folder with files
- Use this when the client already knows the file list.
POST /v2/folderscreates the folder, registers files, and returns upload URLs in one response.
Create an empty folder first
- Use this when the file list is not known yet.
POST /v2/folderscreates a shareable empty folder.- No upload URLs are returned.
- The uploader opens the returned
folderUrlin a browser and uploads directly throughfile.kiwi. - If no file is uploaded within 24 hours, the ownerless empty folder is deleted.
Uploaded file contents are encrypted before reaching storage. The URL fragment (#secretKey) is the decryption key and is not sent by browsers during normal page requests.
Flow Comparison
| Topic | Create a folder with files | Create an empty folder first |
|---|---|---|
| Use when | The API client already knows the file list. | The uploader will choose files later in the browser. |
| API request | POST /v2/folders with files[] |
POST /v2/folders without files[] |
| Secret key generation | The API client generates the secret key and sends only encryption.ske. |
api.file.kiwi generates the secret key for the returned folderUrl when encryption.keyStrategy is server_generated. |
| File registration | api.file.kiwi registers the initial files during folder creation. |
file.kiwi registers files when the browser user uploads. |
| Upload URLs | Returned by api.file.kiwi in the folder creation response. |
Not returned by api.file.kiwi. |
| Upload actor | The API client uploads encrypted chunks programmatically. | The browser user uploads through file.kiwi. |
| Ownership | Managed by the API workflow. | Assigned by file.kiwi when the browser upload flow starts. |
| Empty-folder cleanup | Not applicable. | Deleted if no file is uploaded within 24 hours. |
| Upload status API | Available through GET /v2/folders/{folderId}/files/{fileId}/upload-status. |
Not part of the empty-folder API flow. |
Resources
| Resource | Description |
|---|---|
folder |
A shareable WebFolder at https://file.kiwi/{folderId} |
file |
A file entry registered inside a folder |
uploadUrls |
Presigned R2 chunk upload URL components |
uploadAuth |
Token used to verify upload completion and extend expiration during long uploads |
Empty Folders
For empty folders, api.file.kiwi only creates the folder and share URL.
- The API does not register files into an existing empty folder.
- The API does not return upload URLs for an empty folder.
- The web app at
file.kiwihandles browser authentication, owner assignment, file registration, and upload. - Opening the folder URL should not claim ownership by itself.
- If no browser user uploads a file within 24 hours, the ownerless empty folder is deleted.
Choosing an Empty Folder Mode
Use an empty folder when the person who will upload files should do it in the browser. The API client only creates the link and returns it to the user.
| Situation | Recommended mode |
Why |
|---|---|---|
| A user wants to send large files to a friend, client, or coworker. | send |
The first uploader becomes the folder owner and recipients can download the uploaded files. |
| Multiple people need to exchange large files with each other. | share |
Browser users can upload and download through the same shared folder. |
In all empty-folder cases, return folderUrl to the user. The user opens the link, uploads at least one file within 24 hours through file.kiwi, and shares the same link with the intended recipients.
request mode is supported by the API, but it is not recommended for ownerless empty-folder creation because the first browser uploader becomes the owner. Use it only when that ownership behavior is intentional.
Endpoints
POST /v2/folders
Create a WebFolder. The request may include files or may create an empty folder.
Empty Folder Request
POST https://api.file.kiwi/v2/folders
Content-Type: application/json
{
"title": "Large file transfer",
"mode": "send",
"encryption": {
"keyStrategy": "server_generated"
}
}
Folder With Files Request
{
"title": "Project assets",
"mode": "send",
"encryption": {
"ske": "<encrypted-secret-key>"
},
"files": [
{ "filename": "<encrypted-filename>", "filesize": 1048576 },
{ "filename": "<encrypted-filename>", "filesize": 5242880, "mimetype": "image/jpeg" }
]
}
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | No | WebFolder title (max 200 characters) |
mode |
string | No | send, share, or request. Defaults to send. |
encryption.keyStrategy |
string | No | server_generated for server-generated share URLs. |
encryption.ske |
string | Conditional | Encrypted secret key. Required when the client generates the decryption key. |
files |
array | No | Initial files to register. Omit or pass an empty array to create an empty folder. |
files[].filename |
string | Yes, when files is used |
Encrypted filename (base64) |
files[].filesize |
number | Yes, when files is used |
File size in bytes |
files[].mimetype |
string | No | MIME type |
Response 200 OK
Empty folder:
{
"folderId": "a1b2c3d4",
"folderUrl": "https://file.kiwi/a1b2c3d4#secretKey",
"folderUrlBase": "https://file.kiwi/a1b2c3d4",
"mode": "send",
"uploadRequiredWithinHours": 24,
"files": []
}
Folder with files:
{
"folderId": "a1b2c3d4",
"folderUrl": "https://file.kiwi/a1b2c3d4",
"mode": "send",
"uploadAuth": "a1b2c3d4e5f6g7h8",
"files": [
{
"filename": "<encrypted-filename>",
"fileId": "e5f6g7h8",
"chunkSize": 10485760,
"chunks": 1,
"freeDownloadHours": 24,
"uploadUrls": {
"head": "https://filekiwi.xxx.r2.cloudflarestorage.com/",
"tail": "X-Amz-Algorithm=AWS4-HMAC-SHA256&...",
"path": "stbox/0525/e5f6g7h8",
"signatures": ["<signature_for_chunk_00001>"],
"headers": {
"x-amz-meta-folder_id": "a1b2c3d4",
"x-amz-meta-chunks": "1"
}
}
}
]
}
| Response Field | Description |
|---|---|
folderId |
Unique WebFolder identifier |
folderUrl |
Shareable URL. Includes #secretKey only when the server generated the key. |
folderUrlBase |
Folder URL without the decryption fragment |
mode |
Folder mode: send, share, or request |
uploadRequiredWithinHours |
Returned for empty folders. If no file is uploaded within this many hours, the ownerless empty folder is deleted. |
uploadAuth |
Token for upload verification. Returned when files are registered. |
files[] |
Registered file entries and upload URL data |
GET /v2/folders/{folderId}/files/{fileId}/upload-status
Verify which chunks have been uploaded for a file.
When uploadAuth is provided and matches the token returned from POST /v2/folders, the server can extend expiration if the file has less than 2 hours remaining. This prevents files from expiring during long uploads.
Request
GET https://api.file.kiwi/v2/folders/a1b2c3d4/files/e5f6g7h8/upload-status?uploadAuth=a1b2c3d4e5f6g7h8
| Parameter | Type | Required | Description |
|---|---|---|---|
folderId |
string | Yes | WebFolder ID |
fileId |
string | Yes | File ID |
uploadAuth |
string | No | Upload token from folder creation |
Response 200 OK
Upload complete:
{
"complete": true,
"missing": []
}
Upload incomplete:
{
"complete": false,
"missing": [2, 5]
}
API Upload Flow
Create Folder With Files
1. Generate encryption keys client-side.
2. POST /v2/folders with encryption.ske and files[].
3. Share https://file.kiwi/{folderId}#{secretKey}.
4. Upload encrypted chunks with the returned uploadUrls.
5. GET /v2/folders/{folderId}/files/{fileId}/upload-status.
Create Empty Folder For Browser Upload
1. POST /v2/folders with no files[].
2. Share the returned folderUrl.
3. The uploader opens the folder URL in a browser and uploads at least one file within 24 hours.
4. file.kiwi handles browser authentication, owner assignment, file registration, and upload.
api.file.kiwi does not provide a follow-up file-registration endpoint for this flow.
Chunk Upload
For each file, upload each chunk via presigned PUT URL:
PUT {head}{path}/{chunkNumber}?{tail}&X-Amz-Signature={signatures[i]}
Headers: (all headers from uploadUrls.headers)
Body: <encrypted chunk data>
chunkNumberis zero-padded to 5 digits (for example,00001,00002).- All headers from
uploadUrls.headersmust be included in the PUT request. - Presigned URLs expire after 36 hours.
- Recommended upload order: first chunk, last chunk, then remaining chunks sequentially. This enables video preview on the receiver side for formats such as MP4.
Limits
The limits below apply to the direct API upload flow, where files are registered by passing files[] to POST /v2/folders and upload URLs are returned by api.file.kiwi.
For empty-folder browser uploads, file.kiwi handles file registration and upload, so the web app's upload policy applies instead.
To increase direct API upload limits with an API key, contact mini@file.kiwi or chat.
| Limit | Value |
|---|---|
| Files per WebFolder | 10 |
| Max file size | 999 GiB |
| Max title length | 200 characters |
| Presigned URL validity | 36 hours |
| Concurrent chunk uploads | 1 (upload one chunk at a time) |
| Rate limit | Undisclosed |
| Download count (Korea) | 3 (details) |
Free Download Hours by File Size
| File Size | Free Download Hours |
|---|---|
| < 10 GB | 24 hours |
| 10 GB-20 GB | 12 hours |
| >= 20 GB | 6 hours |
These hours differ from the web version.
E2E Encryption
All files are encrypted before upload using RFC 8188 — Encrypted Content-Encoding for HTTP (AES-128-GCM). The server stores ciphertext.
Client-Generated Keys
For strict client-side key ownership:
- Generate a
secretKeyclient-side. - Encrypt the
secretKeyintoske. - Send only
sketo the API. - Append
#secretKeytofolderUrlBasebefore sharing.
Server-Generated Share URLs
For empty-folder workflows, clients may request encryption.keyStrategy = "server_generated". In that case, the response includes a shareable folderUrl with #secretKey.
The server must not persist the plaintext secretKey. For highly sensitive files, prefer client-generated keys.