Max 5MB / File • 15 Files Quota

Click to browse or drag & drop files here

Supports single or multi-file uploads (Images, PDFs, CSV, JSON, TXT). Single file limit: 5 MB.

Cloud Storage CDN Architecture & Security Guardrails

Playground API provides a production-grade simulated Cloud Storage CDN sandbox powered by Cloudinary. Uploaded files are processed in zero-disk memory buffers, inspected with binary magic bytes sniffing, partitioned into deep per-identity isolation folders, and assigned publicly accessible HTTPS CDN URLs with instant latency simulation.

Magic Bytes & Anti-Malware

Binary header signature inspection prevents executable masking (e.g. .exe, .sh, .php renamed to .png). Prohibited extensions are immediately rejected.

Itemized Bulk Uploads

Uploading multiple files returns an itemized per-file status list. If 3 files succeed and 2 fail (e.g. oversized or blocked type), valid files are stored while failed files return exact reason codes.

Network Delay Simulation

Use X-Simulate-Delay: 1500 or ?_delay=1500 to test client progress spinners, cancel tokens, and slow 3G network conditions before files reach the CDN.

Strict Thresholds & Quotas

ParameterLimitError CodeDescription
Single File Size5 MBFILE_TOO_LARGEFiles exceeding 5,242,880 bytes are rejected before memory allocation.
Bulk Batch Total25 MB / 10 filesBATCH_TOO_LARGETotal size of files in a single bulk request cannot exceed 25 MB.
Active Files Quota15 files / identityQUOTA_EXCEEDEDPer-session storage quota. Reset session or delete old files to free capacity.
Blocked Formats.exe, .sh, .bat, .php, .js, .jarPROHIBITED_FILE_TYPEDangerous executable script files are strictly blocked via extension and magic byte headers.

REST API Endpoints Reference

POST/api/v1/uploads

Upload a single multipart file (field: file, optional: category).

multipart/form-data
POST/api/v1/uploads/bulk

Upload multiple files simultaneously with itemized validation results (field: files).

multipart/form-data
GET/api/v1/uploads?category=avatars

List all uploaded files in current sandbox identity with optional category filter.

application/json
DELETE/api/v1/uploads/:id

Purge an uploaded file from sandbox storage and Cloudinary CDN.

application/json

Code Integration Examples

Official TypeScript SDK: Single File Upload

typescript
1
// 1. Single File Upload using TypeScript SDK (Browser or Node.js)
2
import { PlaygroundClient } from 'playground-api';
3
4
const client = new PlaygroundClient({
5
identityToken: 'your_sandbox_identity_token'
6
});
7
8
// In Browser (from HTML <input type="file">):
9
const fileInput = document.querySelector<HTMLInputElement>('#avatarInput');
10
if (fileInput?.files?.[0]) {
11
const result = await client.uploads.upload(fileInput.files[0], {
12
category: 'avatars',
13
onProgress: (percent, loaded, total) => {
14
console.log(Upload Progress: ${percent}% (${loaded}/${total} bytes));
15
}
16
});
17
18
console.log('File uploaded to CDN:', result.url);
19
console.log('File ID:', result.id);
20
}

Official TypeScript SDK: Itemized Bulk Upload

typescript
1
// 2. Itemized Bulk Uploads with Granular Per-File Breakdown
2
const fileList = document.querySelector<HTMLInputElement>('#documentsInput')?.files;
3
4
if (fileList && fileList.length > 0) {
5
const bulkResult = await client.uploads.uploadBulk(Array.from(fileList), {
6
category: 'documents',
7
simulateDelayMs: 500,
8
onProgress: (percent) => console.log(Bulk progress: ${percent}%)
9
});
10
11
console.log(Uploaded ${bulkResult.summary.successful} / ${bulkResult.summary.total} files);
12
13
// Each file has its own individual status & error details
14
bulkResult.results.forEach((item) => {
15
if (item.status === 'success') {
16
console.log( ${item.original_name} -> ${item.url});
17
} else {
18
console.error( ${item.original_name} failed: ${item.error} (${item.code}));
19
}
20
});
21
}

Standard Fetch & FormData API

javascript
1
// 3. Standard Fetch API (Vanilla JavaScript)
2
const formData = new FormData();
3
formData.append('file', selectedFile);
4
formData.append('category', 'attachments');
5
6
const response = await fetch('https://playground.nileslabs.com/api/v1/uploads', {
7
method: 'POST',
8
headers: {
9
'X-Playground-Identity': 'your_sandbox_identity_token'
10
// Note: Do NOT manually set 'Content-Type'; fetch sets boundary automatically!
11
},
12
body: formData
13
});
14
15
const data = await response.json();
16
console.log('Uploaded CDN URL:', data.data.url);

Automated E2E Test Suite (Playwright)

typescript
1
// 4. Automated E2E File Upload Testing (Playwright)
2
import { test, expect } from '@playwright/test';
3
import path from 'path';
4
5
test('upload profile avatar and verify CDN preview', async ({ request, page }) => {
6
// Attach file using Playwright APIRequestContext
7
const response = await request.post('https://playground.nileslabs.com/api/v1/uploads', {
8
headers: {
9
'X-Playground-Identity': 'test_e2e_session'
10
},
11
multipart: {
12
file: {
13
name: 'sample_avatar.png',
14
mimeType: 'image/png',
15
buffer: Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==', 'base64')
16
},
17
category: 'avatars'
18
}
19
});
20
21
expect(response.status()).toBe(201);
22
const json = await response.json();
23
24
expect(json.data.category).toBe('avatars');
25
expect(json.data.url).toContain('cloudinary.com');
26
expect(json.data.size_bytes).toBeGreaterThan(0);
27
});

cURL Terminal Commands

bash
1
# 5. Single File Upload via cURL
2
curl -X POST "https://playground.nileslabs.com/api/v1/uploads" \
3
-H "X-Playground-Identity: your_session_token" \
4
-F "file=@/path/to/profile.png" \
5
-F "category=avatars"
6
7
# 6. Bulk Upload via cURL (Up to 10 files)
8
curl -X POST "https://playground.nileslabs.com/api/v1/uploads/bulk" \
9
-H "X-Playground-Identity: your_session_token" \
10
-F "files=@/path/to/doc1.pdf" \
11
-F "files=@/path/to/doc2.jpg" \
12
-F "category=documents"