File Manager API — Integration Guide

This guide is everything a 3rd-party application needs to integrate with the File Manager API: a REST API for buckets, folders, files, shareable download links, a private file manager, and a real-time event feed. Every call is authenticated with a vendor API key and is automatically scoped to your tenant.

Base URL: https://cdn.betazeninfotech.com/api/v145 endpoints

1. Authentication

Authenticate every request with a vendor API key (it looks like `fmsk_…`). Create one in your vendor dashboard under “API keys” — the secret is shown only once, so store it safely. Send it on every request as a Bearer token (or the `x-api-key` header). Each key carries a set of scopes (permissions) and may optionally be restricted to specific buckets; a request that needs a scope the key doesn’t have is rejected with `403`. The SAME key authenticates all three transports — the REST endpoints, the SSE feed (`/events`), and the WebSocket feed (`/ws`) — so one credential drives everything.

# Either header works:
-H "Authorization: Bearer fmsk_YOUR_KEY"
-H "x-api-key: fmsk_YOUR_KEY"

Every endpoint declares the scope it requires. Grant a key only the scopes it needs. The available scopes:

Buckets
bucket:readList & view buckets
bucket:createCreate buckets
bucket:updateRename / change settings
bucket:deleteDelete buckets
Files
file:listList files & folders
file:readView details / read text / list links
file:downloadDownload files
file:uploadUpload, edit, copy, extract, multipart
file:deleteTrash & restore files
Folders
folder:createCreate folders
folder:updateRename / move / delete folders
folder:hideHide / unhide files & folders
Share links
publicurl:createCreate share links
publicurl:revokeReset / revoke links
Realtime
events:subscribeSubscribe to the realtime event feed

2. Quick start

1. Verify your key (list buckets)
curl -H "Authorization: Bearer fmsk_YOUR_KEY" \
  https://cdn.betazeninfotech.com/api/v1/buckets
2. Create a bucket
curl -X POST https://cdn.betazeninfotech.com/api/v1/buckets \
  -H "Authorization: Bearer fmsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"invoices"}'
3. Upload a file
curl -X POST https://cdn.betazeninfotech.com/api/v1/buckets/BUCKET_ID/files \
  -H "Authorization: Bearer fmsk_YOUR_KEY" \
  -F "file=@/path/to/file.pdf" -F "path=/"
4. Create a public share link
curl -X POST https://cdn.betazeninfotech.com/api/v1/files/FILE_ID/links \
  -H "Authorization: Bearer fmsk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"public"}'
5. Receive real-time updates
curl -N https://cdn.betazeninfotech.com/api/v1/events \
  -H "Authorization: Bearer fmsk_YOUR_KEY" \
  -H "Accept: text/event-stream"

3. Core concepts

Buckets
Top-level containers for your files (one tenant can have many). Names are unique per vendor. Creating a bucket also provisions a matching folder in your File Manager.
Folders
Optional hierarchy inside a bucket. Files can live at the bucket root or inside nested folders.
Files
Uploaded objects. Small files use a single multipart/form-data upload; large files use the multipart flow (init → upload parts → complete). Uploads are also mirrored into your File Manager so they show up there.
Share links
Three kinds of shareable download URLs: public (/p/…, anyone with the URL), temporary (/t/…, auto-expires), and private (/d/…, requires a 3rd-party JWT). Temporary links require an explicit expiresIn; public/private links can be made permanent with neverExpire. Links stream the file through the app, so they work from any browser.
File Manager
A private, jailed filesystem per tenant. You can create folders, read/write text files, upload, compress/extract, change permissions, hide files, and move items to a recoverable Trash (restore or permanently delete).
Real-time events
A live feed of everything happening on your account (uploads, deletes, link creation, file-manager operations…), delivered over a standard HTTPS stream (Server-Sent Events). Use it to keep a 3rd-party UI in sync instantly instead of polling.

4. API reference

Every endpoint with its required scope. For full request/response details and a live tester, open the interactive explorer.

Buckets & Folders

Containers for files. Every query is scoped to your vendor.

GET/bucketsbucket:readList buckets
POST/bucketsbucket:createCreate bucket
GET/buckets/:bidbucket:readBucket details
PATCH/buckets/:bidbucket:updateUpdate bucket
DELETE/buckets/:bidbucket:deleteDelete bucket
GET/buckets/:bid/foldersfile:listList folders
POST/buckets/:bid/foldersfolder:createCreate folder
PATCH/folders/:idfolder:updateRename folder
DELETE/folders/:idfolder:updateDelete folder
PATCH/folders/:idfolder:updateMove folder
POST/folders/:id/hidefolder:hideHide folder
POST/folders/:id/unhidefolder:hideUnhide folder
Files

Upload, fetch, update and download files. Uploads are multipart/form-data.

GET/buckets/:bid/filesfile:listList files
POST/buckets/:bid/filesfile:uploadUpload file
GET/files/:idfile:readFile details
PATCH/files/:idfile:uploadUpdate file
DELETE/files/:idfile:deleteTrash file
GET/files/:id/downloadfile:downloadDownload file
POST/files/:id/restorefile:deleteRestore from trash
POST/files/:id/copyfile:uploadCopy file
GET/files/:id/contentfile:readRead text content
PUT/files/:id/contentfile:uploadEdit text content
POST/files/:id/hidefolder:hideHide file
POST/files/:id/unhidefolder:hideUnhide file
POST/files/:id/extractfile:uploadExtract a .zip
POST/buckets/:bid/files/blankfile:uploadCreate a (text) file
POST/buckets/:bid/archivefile:readZip files into an archive
Large uploads (multipart)

For big files, upload in parts: init → upload each part → complete. Abort to cancel.

POST/files/multipart/initfile:uploadStart multipart upload
PUT/files/multipart/:uploadId/part/:nfile:uploadUpload a part
POST/files/multipart/:uploadId/completefile:uploadComplete upload
POST/files/multipart/:uploadId/abortfile:uploadAbort upload
Links

Three shareable link types: public, temporary (auto-expiring), private (JWT-gated).

GET/files/:id/linksfile:readList links
POST/files/:id/linkspublicurl:createCreate link
POST/files/:id/links/resetpublicurl:revokeReset all links
DELETE/links/:idpublicurl:revokeRevoke link
Realtime events

A live per-vendor activity feed (Server-Sent Events) so 3rd-party software gets pushed updates instead of polling — plus a JSON delta for fast catch-up.

GET/eventsevents:subscribeEvent stream / delta
GET/wsevents:subscribeWebSocket stream
File manager (your private folder)

A private, jailed filesystem area per vendor. Every path is relative to your home folder — you can never reach a parent, the server root, or another vendor.

GET/fsList a directory
POST/fsFile operation
GET/fs/readRead a text file
GET/fs/downloadDownload a file
POST/fs/uploadUpload into a folder
Shareable download URLs

Public-facing URLs returned by "Create link". These live at the site root (NOT under /api/v1) and need no API key — open them in a browser. Private links require a 3rd-party JWT.

GET/p/:tokenPublic download
GET/t/:tokenTemporary download
GET/d/:tokenPrivate download (JWT)

5. Real-time events (Server-Sent Events)

Open `GET /events` with a streaming HTTP client and your API key; the server keeps the connection open and pushes one event per change as it happens. Each event is a small JSON object. The connection auto-recovers: on reconnect, send the `Last-Event-ID` header (the id of the last event you saw) and you’ll receive everything you missed. For a one-shot catch-up (e.g. on first load) call `GET /events?since=<cursor>` for a JSON list plus a cursor to continue from. Keys restricted to specific buckets only receive events for those buckets.

Event payload
{
  "id": "6a2e7012c12f65f87232a1f3",
  "type": "file.upload",
  "vendorId": "6a2d7e0a626116c181d92a71",
  "resourceType": "file",
  "resourceId": "6a2e70b4c12f65f87232a201",
  "bucketId": "6a2e6fc6c12f65f87232a172",
  "actorType": "apikey",
  "at": "2026-06-14T09:10:42.615Z"
}
Event types (the type field)
Files
file.uploadA file was uploaded to a bucket.
file.createA file was created from inline text (blank file).
file.updateFile metadata changed (rename, tags, move…).
file.editA text file’s contents were overwritten.
file.copyA file was duplicated.
file.deleteA file was moved to trash.
file.restoreA trashed file was restored.
file.downloadA file was downloaded via the API.
file.hideA file was hidden.
file.unhideA file was un-hidden.
file.zipFiles/folders were archived into a .zip.
file.extractA .zip was extracted into the bucket.
file.multipart.initA large (multipart) upload started.
file.multipart.completeA multipart upload finished — file is ready.
file.multipart.abortA multipart upload was aborted.
Buckets
bucket.createA bucket was created.
bucket.updateA bucket was renamed or reconfigured.
bucket.deleteA bucket was deleted.
Folders
folder.createA folder was created.
folder.updateA folder was renamed or moved.
folder.deleteA folder was deleted.
folder.hideA folder was hidden.
folder.unhideA folder was un-hidden.
Share links
link.createA share link was created.
link.resetA file’s links were reset / regenerated.
link.revokeA share link was revoked.
link.download.publicA public link was opened / downloaded.
link.download.temporaryA temporary link was opened / downloaded.
link.download.privateA private (JWT) link was opened / downloaded.
File manager (jailed FS)
fs.mkdirA directory was created.
fs.newfileAn empty file was created.
fs.writeA file was written / edited.
fs.uploadA file was uploaded into the file manager.
fs.renameAn item was renamed / moved.
fs.copyAn item was copied.
fs.deleteAn item was permanently deleted.
fs.trashAn item was moved to the trash.
fs.restoreAn item was restored from the trash.
fs.chmodPermissions were changed.
fs.zipItems were compressed.
fs.extractA zip was extracted.
fs.hideAn item was hidden.
fs.unhideAn item was un-hidden.
Reference client (Node 18+, no dependencies)
const BASE = 'https://cdn.betazeninfotech.com/api/v1';
const KEY = process.env.FM_API_KEY; // fmsk_...

// 1) Fast initial load + resume cursor
let cursor = null;
async function catchUp() {
  const url = new URL(BASE + '/events');
  if (cursor) url.searchParams.set('since', cursor);
  const r = await fetch(url, { headers: { Authorization: 'Bearer ' + KEY } });
  const { events, cursor: next } = await r.json();
  events.forEach(handle);
  if (next) cursor = next;
}

// 2) Live stream (auto-reconnect with Last-Event-ID)
async function stream() {
  const res = await fetch(BASE + '/events', {
    headers: { Authorization: 'Bearer ' + KEY, Accept: 'text/event-stream',
               ...(cursor ? { 'Last-Event-ID': cursor } : {}) }
  });
  const reader = res.body.getReader();
  const dec = new TextDecoder();
  let buf = '';
  for (;;) {
    const { value, done } = await reader.read();
    if (done) break;
    buf += dec.decode(value, { stream: true });
    let i;
    while ((i = buf.indexOf('\n\n')) >= 0) {
      const frame = buf.slice(0, i); buf = buf.slice(i + 2);
      const line = frame.split('\n').find((l) => l.startsWith('data: '));
      if (line) { const e = JSON.parse(line.slice(6)); cursor = e.id; handle(e); }
    }
  }
  setTimeout(stream, 1000); // reconnect on drop
}

function handle(e) { console.log(e.type, e.resourceId, e.at); }
await catchUp();
stream();

WebSocket (wss://)

The same real-time feed is also available over WebSocket — for 3rd-party platforms that require it. It carries the identical event objects as the SSE feed and uses the same API key (events:subscribe scope). Bucket-scoped keys only receive their buckets’ events.

  • URL: wss://cdn.betazeninfotech.com/api/v1/ws
  • Auth (handshake): Authorization: Bearer fmsk_… (or x-api-key). Browsers can’t set handshake headers — use ?api_key=fmsk_… (query keys can appear in logs) or the Sec-WebSocket-Protocol value.
  • On connect: the server sends {"type":"__connected","cursor":"…"}, then one JSON message per event (same payload as above).
  • Resume: reconnect with ?since=<cursor> (the last event id you saw).
  • Heartbeat: the server pings every 30s; clients auto-reply. You may also send {"type":"ping"}.
Node (ws package — server-to-server, header auth)
import WebSocket from 'ws';
const ws = new WebSocket('wss://cdn.betazeninfotech.com/api/v1/ws', {
  headers: { Authorization: 'Bearer fmsk_YOUR_KEY' }   // or x-api-key
});
ws.on('open', () => console.log('connected'));
ws.on('message', (data) => {
  const e = JSON.parse(data.toString());
  if (e.type === '__connected') return;                // hello + resume cursor
  console.log(e.type, e.resourceId, e.at);
});
ws.on('close', () => setTimeout(reconnect, 1000));     // reconnect with ?since=<lastId>
Browser (headers not allowed — use the query param)
const ws = new WebSocket('wss://cdn.betazeninfotech.com/api/v1/ws?api_key=fmsk_YOUR_KEY');
ws.onmessage = (m) => { const e = JSON.parse(m.data); console.log(e.type); };
Quick test (wscat)
wscat -c "wss://cdn.betazeninfotech.com/api/v1/ws" -H "Authorization: Bearer fmsk_YOUR_KEY"

6. Responses & errors

A successful response returns the requested JSON directly (HTTP 200, or 201 on create). An error returns `{ "error": { "code": "…", "message": "…" } }` with an appropriate HTTP status:

{ "error": { "code": "FORBIDDEN", "message": "missing events:subscribe scope" } }
400Invalid input (bad body, missing/!invalid field).
401Missing or invalid credentials.
403Authenticated, but the key lacks the required scope / bucket, or the vendor is suspended.
404Resource not found (or not visible to your tenant).
410A share link has expired or hit its download limit.
429Rate limited — back off and retry.
5xxServer error — safe to retry idempotent requests.

7. Tools & downloads