Storage API

SDX API Storage Data eXchange v1.0

Advanced object storage technology enabling blazing-fast uploads to public nodes (buckets) distributed globally. Upload files up to 1TB using chunked uploads with resume support.

Updated recently 25 min read API v1.0

Introduction

Chunked Uploads
Upload files in 5MB chunks with automatic reassembly and resume support.
Up to 1TB Files
Handle massive files with our distributed storage architecture.
Folder Management
Create folders, list contents, rename, delete — full filesystem operations.

📦 Storage Data eXchange (SDX) — Shulker's advanced object storage technology. With SDX, you can upload files of up to 1TB using chunked uploads, create folders for organization, and manage your objects through a comprehensive RESTful API.

Authentication

The SDX API uses simple key-based authentication. Every request must include your unique key as a URL query parameter.

Authentication Format
?key=your_sdx_key_here

🔐 Security — Your SDX key is tied to a specific node (e.g., in0). The API verifies that your key matches the node you're accessing. Find your API endpoint URL in your SDX Management Panel.

Endpoint URL

The API endpoint URL varies based on your assigned node. Find your specific endpoint in your SDX Management Panel.

Example (in0 node)
https://node-in0-bucket.shulker.in/

⚠️ Important — Always use your actual endpoint URL from your management panel. The example above is for illustration only.

Initialize Upload

POST

Initialize a chunked file upload. Validates storage space and prepares the system for receiving file chunks.

Endpoint
/?key=YOUR_KEY&action=upload-init&path=/
ParameterTypeDescription
fileNameStringName of the file to upload
fileSizeIntegerTotal file size in bytes (max 1TB)
totalChunksIntegerNumber of chunks (5MB each, last may be smaller)
mimeTypeStringMIME type of the file (optional)
JavaScript Example
async function initializeUpload(file, sdxKey, path = '/') {
    const totalChunks = Math.ceil(file.size / (5 * 1024 * 1024));
    
    const formData = new FormData();
    formData.append('fileName', file.name);
    formData.append('fileSize', file.size);
    formData.append('totalChunks', totalChunks);
    formData.append('mimeType', file.type);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=upload-init&path=${path}`,
        { method: 'POST', body: formData }
    );
    
    return await response.json();
}
Python Example
import requests, math, os

def initialize_upload(file_path, sdx_key, path='/'):
    file_size = os.path.getsize(file_path)
    file_name = os.path.basename(file_path)
    total_chunks = math.ceil(file_size / (5 * 1024 * 1024))
    
    data = {
        'fileName': file_name,
        'fileSize': file_size,
        'totalChunks': total_chunks,
        'mimeType': 'application/octet-stream'
    }
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=upload-init&path={path}',
        data=data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=upload-init&path=/" \
  -F "fileName=example.mp4" \
  -F "fileSize=104857600" \
  -F "totalChunks=20" \
  -F "mimeType=video/mp4"
Success Response
{
    "success": true,
    "upload_id": "sdx_67890abcdef",
    "chunk_size": 5242880,
    "message": "Upload initialized successfully"
}

Upload Chunk

POST

Upload individual file chunks. Each chunk should be 5MB (except the last chunk which may be smaller).

Endpoint
/?key=YOUR_KEY&action=upload-chunk
HeaderDescription
X-Upload-IDUpload ID from init response
X-Chunk-IndexZero-based chunk index
JavaScript Example
async function uploadChunk(file, uploadId, chunkIndex, sdxKey) {
    const CHUNK_SIZE = 5 * 1024 * 1024;
    const start = chunkIndex * CHUNK_SIZE;
    const end = Math.min(start + CHUNK_SIZE, file.size);
    const chunk = file.slice(start, end);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=upload-chunk`,
        {
            method: 'POST',
            headers: {
                'X-Upload-ID': uploadId,
                'X-Chunk-Index': chunkIndex.toString()
            },
            body: chunk
        }
    );
    
    return await response.json();
}
Python Example
def upload_chunk(file_path, upload_id, chunk_index, sdx_key):
    CHUNK_SIZE = 5 * 1024 * 1024
    
    with open(file_path, 'rb') as f:
        f.seek(chunk_index * CHUNK_SIZE)
        chunk_data = f.read(CHUNK_SIZE)
    
    headers = {
        'X-Upload-ID': upload_id,
        'X-Chunk-Index': str(chunk_index)
    }
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=upload-chunk',
        headers=headers,
        data=chunk_data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=upload-chunk" \
  -H "X-Upload-ID: sdx_67890abcdef" \
  -H "X-Chunk-Index: 0" \
  --data-binary "@chunk_0.bin"
Success Response
{
    "success": true,
    "chunk_index": 0,
    "uploaded_chunks": 1,
    "total_chunks": 20,
    "progress_percent": 5.0,
    "bytes_uploaded": 5242880,
    "bytes_remaining": 99614720
}

Complete Upload

POST

Finalize the upload by merging all chunks into the final file. Validates chunk integrity and updates storage usage.

Endpoint
/?key=YOUR_KEY&action=upload-complete
JavaScript Example
async function completeUpload(uploadId, sdxKey) {
    const formData = new FormData();
    formData.append('uploadId', uploadId);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=upload-complete`,
        { method: 'POST', body: formData }
    );
    
    return await response.json();
}
Python Example
def complete_upload(upload_id, sdx_key):
    data = {'uploadId': upload_id}
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=upload-complete',
        data=data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=upload-complete" \
  -F "uploadId=sdx_67890abcdef"
Success Response
{
    "success": true,
    "message": "Upload completed successfully",
    "file_name": "example.mp4",
    "file_size": 104857600,
    "file_size_formatted": "100 MB",
    "path": "example.mp4",
    "full_path": "/your_key/example.mp4",
    "mime_type": "video/mp4",
    "checksum": "d41d8cd98f00b204e9800998ecf8427e",
    "upload_time_seconds": 45.32,
    "merge_time_seconds": 2.15,
    "average_speed_mbps": 2.21,
    "chunks_uploaded": 20,
    "storage_used_gb": 0.0977,
    "storage_limit_gb": 100
}

Resume Upload

POST

Check if an incomplete upload exists and get the list of already uploaded chunks to resume from where you left off.

Endpoint
/?key=YOUR_KEY&action=upload-resume&path=/
JavaScript Example
async function resumeUpload(fileName, sdxKey, path = '/') {
    const formData = new FormData();
    formData.append('fileName', fileName);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=upload-resume&path=${path}`,
        { method: 'POST', body: formData }
    );
    
    return await response.json();
}
Python Example
def resume_upload(file_name, sdx_key, path='/'):
    data = {'fileName': file_name}
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=upload-resume&path={path}',
        data=data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=upload-resume&path=/" \
  -F "fileName=example.mp4"
Success Response
{
    "success": true,
    "can_resume": true,
    "upload_id": "sdx_67890abcdef",
    "uploaded_chunks": [0, 1, 2, 3, 4],
    "total_chunks": 20,
    "progress_percent": 25.0,
    "bytes_uploaded": 26214400,
    "bytes_remaining": 78643200
}

List Contents

GET

List all files and folders in a specified directory path.

Endpoint
/?key=YOUR_KEY&action=list-contents&path=/
JavaScript Example
async function listContents(sdxKey, path = '/') {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=list-contents&path=${path}`
    );
    
    return await response.json();
}
Python Example
def list_contents(sdx_key, path='/'):
    response = requests.get(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=list-contents&path={path}'
    )
    
    return response.json()
cURL Example
curl "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=list-contents&path=/"
Success Response
{
    "success": true,
    "path": "",
    "full_path": "/your_key/",
    "items": [
        {
            "name": "videos",
            "path": "videos",
            "type": "folder",
            "size": 0,
            "size_formatted": "-",
            "modified": 1697385600,
            "modified_formatted": "2025-10-15 12:00:00"
        },
        {
            "name": "example.mp4",
            "path": "example.mp4",
            "type": "file",
            "size": 104857600,
            "size_formatted": "100 MB",
            "modified": 1697385645,
            "modified_formatted": "2025-10-15 12:00:45",
            "mime_type": "video/mp4",
            "can_read": false
        }
    ],
    "total_items": 2,
    "folders": 1,
    "files": 1
}

Download File

GET

Download a file from your SDX storage. Returns the file as a binary stream.

Endpoint
/?key=YOUR_KEY&action=download&path=/file.ext
JavaScript Example
async function downloadFile(sdxKey, filePath) {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=download&path=${filePath}`
    );
    
    const blob = await response.blob();
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filePath.split('/').pop();
    a.click();
    window.URL.revokeObjectURL(url);
}
Python Example
def download_file(sdx_key, file_path, save_path):
    response = requests.get(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=download&path={file_path}',
        stream=True
    )
    
    with open(save_path, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)
    
    return save_path
cURL Example
curl "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=download&path=/example.mp4" \
  -o example.mp4

Read File Content

GET

Read the contents of a text-based file (max 100MB). Only works with readable file types.

Endpoint
/?key=YOUR_KEY&action=read-file&path=/file.txt
JavaScript Example
async function readFile(sdxKey, filePath) {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=read-file&path=${filePath}`
    );
    
    return await response.json();
}
Python Example
def read_file(sdx_key, file_path):
    response = requests.get(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=read-file&path={file_path}'
    )
    
    return response.json()
cURL Example
curl "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=read-file&path=/config.json"
Success Response
{
    "success": true,
    "file_name": "config.json",
    "file_size": 1024,
    "mime_type": "application/json",
    "content": "{\"setting\": \"value\"}",
    "encoding": "UTF-8"
}

Delete File/Folder

DELETE

Delete a file or folder (including all contents). This action is irreversible.

Endpoint
/?key=YOUR_KEY&action=delete&path=/file.ext
JavaScript Example
async function deleteItem(sdxKey, itemPath) {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=delete&path=${itemPath}`,
        { method: 'DELETE' }
    );
    
    return await response.json();
}
Python Example
def delete_item(sdx_key, item_path):
    response = requests.delete(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=delete&path={item_path}'
    )
    
    return response.json()
cURL Example
curl -X DELETE "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=delete&path=/example.mp4"
Success Response
{
    "success": true,
    "message": "Deleted successfully",
    "path": "example.mp4",
    "size_freed": 104857600,
    "size_freed_formatted": "100 MB"
}

Rename File/Folder

POST

Rename a file or folder to a new name within the same directory.

Endpoint
/?key=YOUR_KEY&action=rename&path=/oldname.ext
JavaScript Example
async function renameItem(sdxKey, oldPath, newName) {
    const formData = new FormData();
    formData.append('newName', newName);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=rename&path=${oldPath}`,
        { method: 'POST', body: formData }
    );
    
    return await response.json();
}
Python Example
def rename_item(sdx_key, old_path, new_name):
    data = {'newName': new_name}
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=rename&path={old_path}',
        data=data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=rename&path=/old.mp4" \
  -F "newName=new.mp4"
Success Response
{
    "success": true,
    "message": "Renamed successfully",
    "old_name": "old.mp4",
    "new_name": "new.mp4",
    "new_path": "new.mp4"
}

Create Folder

POST

Create a new folder (sub-bucket) to organize your files better.

Endpoint
/?key=YOUR_KEY&action=create-folder&path=/
JavaScript Example
async function createFolder(sdxKey, folderName, path = '/') {
    const formData = new FormData();
    formData.append('folderName', folderName);
    
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=create-folder&path=${path}`,
        { method: 'POST', body: formData }
    );
    
    return await response.json();
}
Python Example
def create_folder(sdx_key, folder_name, path='/'):
    data = {'folderName': folder_name}
    
    response = requests.post(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=create-folder&path={path}',
        data=data
    )
    
    return response.json()
cURL Example
curl -X POST "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=create-folder&path=/" \
  -F "folderName=videos"
Success Response
{
    "success": true,
    "message": "Folder created successfully",
    "folder_name": "videos",
    "path": "videos"
}

Get File/Folder Info

GET

Get detailed information about a specific file or folder including size, type, and modification date.

Endpoint
/?key=YOUR_KEY&action=info&path=/file.ext
JavaScript Example
async function getInfo(sdxKey, itemPath) {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=info&path=${itemPath}`
    );
    
    return await response.json();
}
Python Example
def get_info(sdx_key, item_path):
    response = requests.get(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=info&path={item_path}'
    )
    
    return response.json()
cURL Example
curl "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=info&path=/example.mp4"
Success Response (File)
{
    "success": true,
    "name": "example.mp4",
    "path": "example.mp4",
    "type": "file",
    "modified": 1697385645,
    "modified_formatted": "2025-10-15 12:00:45",
    "size": 104857600,
    "size_formatted": "100 MB",
    "mime_type": "video/mp4",
    "checksum": "d41d8cd98f00b204e9800998ecf8427e",
    "can_read": false
}

Get Account Info

GET

Retrieve information about your SDX account including storage usage and limits.

Endpoint
/?key=YOUR_KEY&action=account-info
JavaScript Example
async function getAccountInfo(sdxKey) {
    const response = await fetch(
        `https://node-in0-bucket.shulker.in/?key=${sdxKey}&action=account-info`
    );
    
    return await response.json();
}
Python Example
def get_account_info(sdx_key):
    response = requests.get(
        f'https://node-in0-bucket.shulker.in/?key={sdx_key}&action=account-info'
    )
    
    return response.json()
cURL Example
curl "https://node-in0-bucket.shulker.in/?key=YOUR_KEY&action=account-info"
Success Response
{
    "success": true,
    "account": {
        "sdx_key": "your_key_here",
        "owner": "[email protected]",
        "storage_used_gb": 10.5,
        "storage_limit_gb": 100,
        "storage_used_percent": 10.5,
        "storage_available_gb": 89.5,
        "billing_amount": "5.00",
        "billing_period": "monthly",
        "next_billing": "2025-11-15",
        "created_at": "2025-01-01 00:00:00"
    }
}

Error Handling

Status CodeMeaningCommon Causes
400Bad RequestInvalid SDX key, missing parameters, or data validation failed
401UnauthorizedBilling overdue or inactive account
403ForbiddenNode mismatch - key doesn't match the node being accessed
404Not FoundFile or folder doesn't exist
500Internal Server ErrorDatabase connection failed or server-side issue
Error Response Format
{
    "success": false,
    "error": "Insufficient storage space. Used: 95.5GB, Limit: 100GB, Required: 5GB",
    "timestamp": 1697385645
}

SDX API Tester

🚀 Try the Interactive API Tester — Want to test the SDX API without writing code? Use our interactive API tester tool to explore all endpoints, upload files, manage folders, and see real-time responses.

Open SDX API Tester