File Management
The file management APIs accept raw media files and return the file_id required by downstream processing APIs. For most image, audio, and video workflows, this is the first API you call.
Upload File
Basic Information
| Item | Value |
|---|---|
| Request Method | POST |
| Request Path | /base/file/upload |
| Content-Type | multipart/form-data |
| Authentication | Raw API key in the Authorization header |
Request Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
Authorization | string | Yes | Pass the raw API key, for example YOUR_API_KEY |
Form Data
| Parameter | Type | Required | Description |
|---|---|---|---|
file | file | Yes | Audio, image, video, or text file to upload |
ℹ️ Note: The current backend limits a single upload to 20 GB and validates file extension and file size.
Supported Upload Extensions
The upload endpoint currently documents the following media extensions. If the extension does not match the backend validation rules, the API can return 6001.
| Category | Supported extensions | Notes |
|---|---|---|
| Image | .jpg, .jpeg, .png, .webp, .bmp | Used by image processing APIs |
| Audio | .mp3, .wav, .m4a, .aac, .flac, .ogg | Used by audio processing APIs |
| Video | .mp4, .mov, .avi, .mkv, .flv, .webm | Used by video processing APIs |
| Other text-like materials | Not explicitly enumerated in the current public docs | Verify against the downstream task API before production use |
💡 Tip: Upload success does not guarantee every downstream task will accept the file. Task APIs still validate compatibility and may return
6014.
Request Example
curl -X POST https://api.ai-mcn.tv:10000/base/file/upload \
-H "Authorization: YOUR_API_KEY" \
-F "file=@/path/to/video.mp4"
Success Example
{
"code": 200,
"msg": "File uploaded successfully~",
"data": {
"file_id": "537489015178246",
"original_name": "video.mp4",
"size": 10485760,
"blake3_id": "a1b2c3d4...",
"base_ext": ".mp4",
"download_url": "/download/a1/537489015178246.mp4",
"created_at": "2026-04-05T08:00:00Z",
"expire_at": "2026-06-04T00:00:00Z",
"is_expired": false
}
}
Important Fields
file_id: the identifier used in task creationdownload_url: download location of the original fileexpire_at: file expiration timeblake3_id: content fingerprint
💡 Tip: Uploading the exact same file can hit backend deduplication and reuse an existing record instead of storing a duplicate file.
Error Codes
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
6001 | 400 | Unsupported file type | Upload a file with a supported extension |
6002 | 413 | File exceeds 20 GB | Compress the file or upload a smaller one |
6011 | 400 | Empty file | Make sure the uploaded file contains actual content |
6502 | 401 | Authentication failed | Pass the raw API key in the Authorization header |
💡 Tip: Single-shot upload works best for small files. For multi-GB files, use Chunked Upload (Resumable) below — after a network interruption you only re-upload the missing chunks instead of the whole file.
Chunked Upload (Resumable)
Chunked upload splits a large file into fixed-size parts that are uploaded one by one. If any part fails, only that part is retried; after an interruption you can query the list of missing parts and resume. Use it for multi-GB files; keep using the single-shot POST /base/file/upload for small files.
The response of the final complete call is identical in shape to the single-shot upload response — deduplication, expiration renewal, and the 60-day retention all behave the same, so downstream APIs never need to know which upload path produced the file.
Endpoint Overview
| Endpoint | Method | Path | Description |
|---|---|---|---|
| Create session | POST | /base/file/upload/chunk/init | Declare filename and total size; returns the session and chunk contract; supports instant upload |
| Upload part | PUT | /base/file/upload/chunk/{upload_id}/{index} | Upload the raw bytes of part index; idempotent and safely retryable |
| Query status | GET | /base/file/upload/chunk/{upload_id} | Returns the list of missing parts — the basis for resuming |
| Complete upload | POST | /base/file/upload/chunk/{upload_id}/complete | Validates all parts and finalizes the file; response mirrors single-shot upload |
| Abort session | DELETE | /base/file/upload/chunk/{upload_id} | Actively discard the upload; idempotent |
All endpoints use the same authentication as single-shot upload: pass the raw API key in the Authorization header.
Resumable Upload Flow
- Call
initwithfilenameandsizeto obtainupload_id,part_size, andtotal_parts. - Split the file by
part_sizeand upload each part — out of order and in parallel are both fine, and re-uploading the same part is safe. - If the network drops, call the status endpoint after reconnecting to get the
missingpart list, then re-upload only the missing parts. - After all parts are uploaded, call
completeto obtain thefile_id.
⚠️ Warning:
part_sizeis decided by the server (currently 32 MiB). Clients must split the file using the value returned byinit— never hard-code it. Every part must be exactlypart_sizebytes, except the last part, which is the remainder.
Create Session (init)
Basic Information
| Item | Value |
|---|---|
| Request Method | POST |
| Request Path | /base/file/upload/chunk/init |
| Content-Type | application/json |
| Authentication | Raw API key in the Authorization header |
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
filename | string | Yes | — | Original filename with extension, used for type validation and record keeping |
size | number | Yes | — | Total file size in bytes, up to 20 GB |
blake3_id | string | No | — | Content fingerprint (same convention as single-shot deduplication); may trigger instant upload |
Request Example
curl -X POST https://api.ai-mcn.tv:10000/base/file/upload/chunk/init \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "video.mp4",
"size": 4370031878
}'
Success Example
{
"code": 200,
"msg": "success",
"data": {
"upload_id": "537489015178300",
"part_size": 33554432,
"total_parts": 131,
"expires_at": "2026-07-05 12:00:00"
}
}
upload_id: unique identifier for this upload session, used by the other four endpointspart_size: bytes per part (server-decided; split your file accordingly)total_parts: total part count, i.e.ceil(size / part_size)expires_at: session expiration time; every part upload or status query extends it
ℹ️ Note: Sessions are kept for 72 hours by default and are automatically extended by upload activity. Sessions that never complete are cleaned up; you would then need a fresh
init.
Instant Upload
When init carries a blake3_id and a non-expired file with identical content already exists in the system, the API returns that file's full information directly (same shape as the single-shot upload response, plus instant: true) — zero bytes uploaded, no session is created, and no upload_id is returned:
{
"code": 200,
"msg": "File already exists, expiration time renewed~",
"data": {
"file_id": "537489015178246",
"original_name": "video.mp4",
"size": 4370031878,
"blake3_id": "a1b2c3d4...",
"base_ext": ".mp4",
"download_url": "/download/a1/537489015178246.mp4",
"created_at": "2026-04-05T08:00:00Z",
"expire_at": "2026-09-01T00:00:00Z",
"is_expired": false,
"instant": true
}
}
💡 Tip: Clients should check for
instant: truein the response — if present, use the returnedfile_iddirectly; otherwise continue with the chunked flow. A fingerprint that only matches an expired file does not trigger instant upload; the session is created normally, and aftercompletethe system renews and reuses the original record.
Upload Part (part)
Basic Information
| Item | Value |
|---|---|
| Request Method | PUT |
| Request Path | /base/file/upload/chunk/{upload_id}/{index} |
| Content-Type | application/octet-stream |
| Authentication | Raw API key in the Authorization header |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
upload_id | string | Yes | Session ID returned by init |
index | number | Yes | Part index, starting from 0, less than total_parts |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
blake3 | string | No | Blake3 checksum of this part's content; if provided, the server verifies it and returns 6026 on mismatch, treating the part as not uploaded |
The request body is the raw bytes of the part (not form data). Every part must be exactly part_size bytes, except the last part, which is the remainder.
Request Example
# Split the file by the part_size returned from init (example: 32 MiB)
split -b 33554432 -d -a 4 video.mp4 part_
# Upload part 0 (part_0000 maps to index=0, and so on)
curl -X PUT "https://api.ai-mcn.tv:10000/base/file/upload/chunk/537489015178300/0" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @part_0000
Success Example
{
"code": 200,
"msg": "success",
"data": {
"upload_id": "537489015178300",
"index": 0,
"received": 1,
"total_parts": 131
}
}
💡 Tip: The part endpoint is idempotent — uploading the same part twice due to a timeout retry never corrupts the file. Different parts can be uploaded out of order and in parallel for higher throughput.
Query Status (status)
Basic Information
| Item | Value |
|---|---|
| Request Method | GET |
| Request Path | /base/file/upload/chunk/{upload_id} |
| Authentication | Raw API key in the Authorization header |
Request Example
curl -X GET https://api.ai-mcn.tv:10000/base/file/upload/chunk/537489015178300 \
-H "Authorization: YOUR_API_KEY"
Success Example
{
"code": 200,
"msg": "success",
"data": {
"upload_id": "537489015178300",
"size": 4370031878,
"part_size": 33554432,
"total_parts": 131,
"received": 100,
"missing": [100, 101, 102, 130],
"expires_at": "2026-07-05 12:00:00"
}
}
missing: list of missing part indexes — after reconnecting, re-upload only these parts
Complete Upload (complete)
Basic Information
| Item | Value |
|---|---|
| Request Method | POST |
| Request Path | /base/file/upload/chunk/{upload_id}/complete |
| Authentication | Raw API key in the Authorization header |
Request Example
curl -X POST https://api.ai-mcn.tv:10000/base/file/upload/chunk/537489015178300/complete \
-H "Authorization: YOUR_API_KEY"
Success Example
The response shape is identical to POST /base/file/upload:
{
"code": 200,
"msg": "File uploaded successfully~",
"data": {
"file_id": "537489015178246",
"original_name": "video.mp4",
"size": 4370031878,
"blake3_id": "a1b2c3d4...",
"base_ext": ".mp4",
"download_url": "/download/a1/537489015178246.mp4",
"created_at": "2026-07-02T08:00:00Z",
"expire_at": "2026-08-31T00:00:00Z",
"is_expired": false
}
}
💡 Tip: Just like single-shot upload, if the assembled content matches an existing file, deduplication kicks in and the existing (renewed) record is returned instead of storing a duplicate.
Error Example
When parts are still missing:
{
"code": 6027,
"msg": "Parts still missing, cannot complete: missing indexes (up to 20 listed) [100, 101, 102]",
"data": null
}
Abort Session (abort)
Basic Information
| Item | Value |
|---|---|
| Request Method | DELETE |
| Request Path | /base/file/upload/chunk/{upload_id} |
| Authentication | Raw API key in the Authorization header |
Request Example
curl -X DELETE https://api.ai-mcn.tv:10000/base/file/upload/chunk/537489015178300 \
-H "Authorization: YOUR_API_KEY"
Success Example
{
"code": 200,
"msg": "success",
"data": {
"upload_id": "537489015178300",
"aborted": true
}
}
ℹ️ Note: Abort is idempotent — calling it again, or on an expired session, still returns success.
Chunked Upload Error Codes
| Error Code | HTTP Status | Description | Resolution |
|---|---|---|---|
6024 | 404 | Session not found or expired | Call init again and re-upload from scratch |
6025 | 400 | Invalid part (index out of range / wrong part size) | Check the index range and part byte count against the contract returned by init |
6026 | 400 | Part checksum mismatch | Re-upload the part |
6027 | 400 | Parts still missing at complete | Upload the missing indexes from the response, then call complete again |
6028 | 400 | Assembled file size does not match the declared size | Verify the size declared at init against how the file was actually split |
6001 | 400 | Unsupported file type | Upload a file with a supported extension |
6002 | 413 | Declared size exceeds 20 GB | Compress the file or upload a smaller one |
6011 | 400 | Declared size is 0 | Make sure the file contains actual content |
6502 | 401 | Authentication failed | Pass the raw API key in the Authorization header |
Get File Details
Basic Information
| Item | Value |
|---|---|
| Request Method | GET |
| Request Path | /base/file/{file_id} |
| Authentication | Raw API key in the Authorization header |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes | File ID returned by the upload API |
Request Example
curl -X GET https://api.ai-mcn.tv:10000/base/file/537489015178246 \
-H "Authorization: YOUR_API_KEY"
Success Example
{
"code": 200,
"msg": "success",
"data": {
"file_id": "537489015178246",
"original_name": "video.mp4",
"size": 10485760,
"blake3_id": "a1b2c3d4...",
"base_ext": ".mp4",
"upload_user_id": 1001,
"download_url": "/download/a1/537489015178246.mp4",
"created_at": "2026-04-05T08:00:00Z",
"expire_at": "2026-06-04T00:00:00Z",
"is_expired": false
}
}
Notes
- Uploaded files are retained for 60 days by default
- Processing APIs validate both file existence and file type compatibility before task creation
- Missing or expired files return
6004