EmberlyEmberly Docs

Files API

Upload, retrieve, update, and delete files via the Emberly REST API.

Endpoints Overview

Upload

MethodPathDescription
POST/api/filesSingle file upload
POST/api/files/chunksInitialize chunked upload
GET/api/files/chunks/[id]/part/[n]Get presigned S3 URL for a chunk
POST/api/files/chunks/[id]/completeFinalize chunked upload

File Management

MethodPathDescription
GET/api/files/[id]Get file metadata
PATCH/api/files/[id]Update visibility, password, etc.
DELETE/api/files/[id]Delete a file
GET/api/files/[id]/downloadDownload a file
POST/api/files/[id]/expirySet file expiration
DELETE/api/files/[id]/expiryCancel file expiration
GET/api/files/sharedList files shared with you

Single File Upload

POST /api/files

Content-Type: multipart/form-data
Auth: Bearer token

FieldTypeRequiredDescription
fileFileYesThe file to upload
visibilityPUBLIC | PRIVATENoDefault: PUBLIC
passwordstringNoPassword-protect the file
domainstringNoCustom domain for the URL
expiresAtISO 8601NoAuto-delete date (must be future)
allowSuggestions"true" | "false"NoAllow edit suggestions

Response (200):

{
  "success": true,
  "data": {
    "id": "cm7xabc123",
    "name": "document.pdf",
    "size": 2.5,
    "mimeType": "application/pdf",
    "url": "https://embrly.ca/yourusername/document.pdf",
    "urlPath": "/yourusername/document.pdf",
    "visibility": "PUBLIC",
    "password": false,
    "createdAt": "2026-03-29T15:30:00Z",
    "expiresAt": null,
    "downloads": 0
  }
}

cURL:

curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "[email protected]" \
  -F "visibility=PUBLIC" \
  -F "expiresAt=2026-12-31T23:59:59Z" \
  https://embrly.ca/api/files

JavaScript:

const form = new FormData();
form.append("file", fileInput.files[0]);
form.append("visibility", "PUBLIC");
 
const res = await fetch("/api/files", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_TOKEN" },
  body: form,
});
const { data } = await res.json();
console.log(data.url);

Plan Limits

PlanMax file size
Spark (Free)500 MB
Paid plansBased on subscription

Security Validation

Every upload runs:

  1. Extension + MIME type checks (50+ blocked types)
  2. Zip bomb detection (max 100:1 ratio)
  3. VirusTotal hash scan (71+ AV engines)

Blocked extensions: .exe, .bat, .sh, .py, .rb, .php, .dll, .jar, .msi, and others.


Chunked Upload

Use chunked upload for large files or unreliable connections.

Step 1 — Initialize: POST /api/files/chunks

{
  "filename": "large-video.mp4",
  "mimeType": "video/mp4",
  "size": 5368709120
}

Returns an uploadId and partSize for splitting the file.

Step 2 — Get presigned URL: GET /api/files/chunks/[uploadId]/part/[n]

Returns a temporary S3 URL for uploading each part.

Step 3 — Upload each chunk

PUT your chunk binary directly to the presigned S3 URL.

Step 4 — Complete: POST /api/files/chunks/[uploadId]/complete

{
  "parts": [{ "PartNumber": 1, "ETag": "..." }, ...]
}

Returns the same response format as single file upload.

Chunked upload defaults to PUBLIC with no password. Use PATCH /api/files/[id] after completion to change visibility or set a password.


Update a File

PATCH /api/files/[id]

Auth: Session or owner token

{
  "visibility": "PRIVATE",
  "password": "newpassword"
}

Returns updated file metadata.


Delete a File

DELETE /api/files/[id]

Auth: Session or owner token

Returns 204 No Content on success.

curl -X DELETE \
  -H "Authorization: Bearer YOUR_TOKEN" \
  https://embrly.ca/api/files/cm7xabc123

Set Expiration

POST /api/files/[id]/expiry

{ "expiresAt": "2026-12-31T23:59:59Z" }

DELETE /api/files/[id]/expiry

Cancels the scheduled deletion.


Files Shared With You

GET /api/files/shared

Returns a paginated list of files other users have shared with you as a collaborator.