Skip to content

Upload Resource

Uploads an asset (image, video, document, …) to your project’s storage. The endpoint supports two upload modes: simple upload for files up to 400 MB, and chunked upload for larger files or unreliable networks.

Endpoint

shell
curl -X POST https://api.contentisland.net/api/1.0/resource/upload \
--header 'Authorization: Bearer YOUR_WRITE_TOKEN' \
--form 'file=@/path/to/your-asset.png'

The request must be multipart/form-data. The field name and the optional X-Chunk-Upload header determine which mode is used.

Simple upload (≤ 400 MB)

Use this mode for any file up to 400 MB. The whole file travels in a single request.

FieldRequiredDescription
fileyesThe binary contents of the asset (multipart field).

Example

shell
curl -X POST https://api.contentisland.net/api/1.0/resource/upload \
--header 'Authorization: Bearer YOUR_WRITE_TOKEN' \
--form 'file=@/path/to/cover-image.png'

Response

201 Created:

interface UploadedResource {
name: string; // the final file name in storage (prefixed and sanitized)
url: string; // public URL of the uploaded asset
}
{
"name": "ab12cd34-cover-image.png",
"url": "https://storage.contentisland.net/your-project/ab12cd34-cover-image.png"
}

Chunked upload (large files or resumable uploads)

For files larger than 400 MB, or whenever you need a resumable upload, split the file into smaller chunks (each one still must be ≤ 400 MB) and send one request per chunk to the same endpoint, setting the header X-Chunk-Upload: true.

FieldRequiredDescription
chunkyesBinary contents of this chunk (multipart field — not file).
chunkOptionsyesJSON string with the metadata of the chunk. See the ChunkOptions interface below.

Required header: X-Chunk-Upload: true.

interface ChunkOptions {
chunkIndex: number; // 0-based index of this chunk
chunkSize: number; // size of this chunk, in bytes
totalChunks: number; // total number of chunks for the whole file
uploadId?: string; // returned by the first chunk; resend it for every subsequent chunk
multiPartUpload?: {
// returned by the first chunk; resend it for every subsequent chunk
Parts: { ETag: string; PartNumber: number }[];
};
filePrefix?: string; // returned by the first chunk; resend it for every subsequent chunk
}

The flow

  1. First chunk (chunkIndex: 0): omit uploadId, multiPartUpload and filePrefix. The server initializes the multipart upload and returns those three fields.
  2. Intermediate chunks: copy uploadId, multiPartUpload and filePrefix from the previous response into the next chunkOptions. The server keeps appending parts and returns the updated values.
  3. Last chunk (chunkIndex + 1 === totalChunks): the server finalizes the upload automatically and the response is the final { name, url } object — there is no separate finalize endpoint to call.

Example — first chunk

shell
curl -X POST https://api.contentisland.net/api/1.0/resource/upload \
--header 'Authorization: Bearer YOUR_WRITE_TOKEN' \
--header 'X-Chunk-Upload: true' \
--form 'chunkOptions={"chunkIndex":0,"chunkSize":5242880,"totalChunks":4}' \
--form 'chunk=@/path/to/part-0.bin'

Response (chunk in progress):

{
"uploadId": "abcd1234EXAMPLEUPLOADID",
"multiPartUpload": { "Parts": [{ "ETag": "\"e1d2c3...\"", "PartNumber": 1 }] },
"filePrefix": "ab12cd34"
}

Example — subsequent chunk

Reuse the values returned by the previous response:

shell
curl -X POST https://api.contentisland.net/api/1.0/resource/upload \
--header 'Authorization: Bearer YOUR_WRITE_TOKEN' \
--header 'X-Chunk-Upload: true' \
--form 'chunkOptions={"chunkIndex":1,"chunkSize":5242880,"totalChunks":4,"uploadId":"abcd1234EXAMPLEUPLOADID","multiPartUpload":{"Parts":[{"ETag":"\"e1d2c3...\"","PartNumber":1}]},"filePrefix":"ab12cd34"}' \
--form 'chunk=@/path/to/part-1.bin'

Final chunk response

When you send the last chunk (chunkIndex + 1 === totalChunks), the server completes the multipart upload and replies with the same { name, url } shape as the simple upload.

Status Codes

CodeDescription
201The chunk (or the whole file) was processed successfully. Body shape depends on whether this is the final chunk ({ name, url }) or not (chunk-progress object).
400Invalid request. Most commonly: the project’s organization does not have storage configured, or the multipart payload is malformed.
401Unauthorized. The token is missing, malformed or expired.
403Forbidden. The token does not have write permissions — use a Write Token.
500Internal server error. An error occurred while processing the request.