@vaultsens/sdk

Ship uploads fast with a clean API-key SDK.

A dual ESM/CJS client for VaultSens. Upload, list, update, and manage files and folders with predictable typed responses and built-in retry support.

Dual ESM + CJSRetry & timeoutAPI key authTyped errors

Quick start

npm install @vaultsens/sdk

import { readFile } from 'node:fs/promises';
import { VaultSensClient, fileFromBuffer } from '@vaultsens/sdk';

const client = new VaultSensClient({
  baseUrl: 'https://api.vaultsens.com',
  apiKey: 'fs_xxx',
  apiSecret: 'sk_xxx',
});

// Node.js: read from disk and convert to File
const buffer = await readFile('./photo.png');
const file = fileFromBuffer(buffer, 'photo.png', 'image/png');
await client.uploadFile(file);

// Browser: File from <input type="file"> works directly
// await client.uploadFile(input.files[0]);

Install

Install the SDK with your package manager of choice.

npm install @vaultsens/sdk

Authentication

Pass your API key and secret in the constructor. All requests are authenticated via x-api-key and x-api-secret headers. The Node SDK also exposes setAuth() for runtime credential swaps.

const client = new VaultSensClient({
  baseUrl: 'https://api.vaultsens.com',
  apiKey: 'fs_123',
  apiSecret: 'sk_456',
});

// Swap credentials at runtime
client.setAuth('fs_new', 'sk_new');

Upload files

Upload a single file or a batch of files. Optionally set a display name, compression level, and a target folderId.

LevelWhat happens
noneFile stored as-is, original format and quality preserved
lowConverted to WebP at quality 90, no resize
mediumConverted to WebP at quality 75, resized if wider than 2000px
highConverted to WebP at quality 60, resized to max 1200px wide, EXIF stripped — default
Non-image files. Compression is only applied to images. For all other file types (PDF, text, video, audio, archives, etc.) the file is stored as-is regardless of the compression value passed.
Blob required.uploadFile accepts a Blob (or File). In the browser a <input type="file"> element returns a File directly. In Node.js, read the file from disk and wrap it with the exported fileFromBuffer helper first.
import { readFile } from 'node:fs/promises';
import { fileFromBuffer } from '@vaultsens/sdk';

// Node.js — convert disk file to File first
const buffer = await readFile('./photo.png');
const file = fileFromBuffer(buffer, 'photo.png', 'image/png');

const result = await client.uploadFile(file, {
  name: 'marketing-hero',
  compression: 'low',
  folderId: 'folder_id',
});
console.log(result.data.url);
// Multiple files
const result = await client.uploadFiles([
  { file: image1, filename: 'one.png' },
  { file: image2, filename: 'two.png' },
], { compression: 'medium', folderId: 'folder_id' });
console.log(result.data); // FileRecord[]

List, get & delete

List files optionally filtered by folder, fetch metadata for a single file, or remove a file by its ID.

// List all files
const list = await client.listFiles();

// List files in a specific folder
const folderFiles = await client.listFiles('folder_id');

// Get metadata for one file
const meta = await client.getFileMetadata('file_id');
console.log(meta.data.url, meta.data.size);

// Delete a file
const first = list.data[0];
if (first) {
  await client.deleteFile(first.id);
}

Update a file

Replace a file's content in-place. The file ID stays the same and existing URLs remain valid. Optionally change the display name or compression level.

const result = await client.updateFile('file_id', newBlob, {
  name: 'hero-v2',
  compression: 'high',
});
console.log(result.data.url);

Folders

Create, list, rename, and delete folders to organise your files. Every folder has a parentId field — when it is null the folder sits at the top level (root). To nest a folder inside another, pass the parent folder's id as the parentId when creating it. Folders must be empty before deletion; move or delete contained files and subfolders first.

// List all folders
const { data: folders } = await client.listFolders();

// Create a top-level folder
const { data: folder } = await client.createFolder('Marketing');

// Create a nested folder
await client.createFolder('2024', folder.id);

// Rename
await client.renameFolder(folder.id, 'Campaigns');

// Delete an empty folder
await client.deleteFolder(folder.id);

Image transforms

Use buildFileUrl() to generate a URL with on-the-fly transform parameters — resize, reformat, and adjust quality without re-uploading. Transform options are appended as query parameters.

OptionTypeDescription
widthnumberTarget width in pixels
heightnumberTarget height in pixels
formatstringOutput format, e.g. webp, jpeg, png
qualitynumberQuality 1–100 (for lossy formats)
fitstringHow to fit the image into the given dimensions: inside (default, preserve ratio), cover (crop to fill), contain (pad to fill), fill (stretch), outside (scale to cover without crop)
// No transforms — original URL
const url = client.buildFileUrl('file_id');

// Resize to 800 px wide, convert to WebP (preserve ratio)
const thumb = client.buildFileUrl('file_id', {
  width: 800,
  format: 'webp',
  quality: 80,
});

// Crop to exact 800×600 thumbnail
const crop = client.buildFileUrl('file_id', {
  width: 800,
  height: 600,
  format: 'webp',
  fit: 'cover',
});

console.log(thumb);
// https://api.vaultsens.com/api/v1/files/file_id?width=800&format=webp&quality=80

Metrics

Fetch storage usage metrics for the authenticated account — total files, bytes used, storage limit, remaining space, and a per-MIME breakdown.

const { data } = await client.getMetrics();

console.log(data.totalFiles);          // e.g. 142
console.log(data.totalStorageBytes);   // e.g. 524288000
console.log(data.storageUsedPercent);  // e.g. 48
console.log(data.storageRemainingBytes);
console.log(data.byMimeType);          // { 'image/png': 80, 'video/mp4': 12, ... }

Errors

All SDK methods throw / raise VaultSensError on any non-2xx response. It carries a machine-readable code, HTTP status, and a human-readable message.

import { VaultSensError, VaultSensErrorCode } from '@vaultsens/sdk';

try {
  await client.uploadFile(file);
} catch (err) {
  if (err instanceof VaultSensError) {
    console.log(err.status, err.code, err.message);

    if (err.code === VaultSensErrorCode.FILE_TOO_LARGE) {
      console.error('File exceeds your plan limit');
    } else if (err.code === VaultSensErrorCode.STORAGE_LIMIT) {
      console.error('Storage quota exceeded');
    } else if (err.code === VaultSensErrorCode.SUBSCRIPTION_INACTIVE) {
      console.error('Upgrade your plan to continue');
    } else if (err.code === VaultSensErrorCode.MIME_TYPE_NOT_ALLOWED) {
      console.error('File type not allowed on your plan');
    }
  }
}

Error codes

Every VaultSensError has a code string you can match against.

CodeHTTPWhen it happens
FILE_TOO_LARGE413File exceeds the plan's max file size
STORAGE_LIMIT413Account storage quota is full
FILE_COUNT_LIMIT403Plan's max file count reached
FOLDER_COUNT_LIMIT403Plan's max folder count reached
MIME_TYPE_NOT_ALLOWED415File type not permitted on the plan
COMPRESSION_NOT_ALLOWED403Compression level not permitted on the plan
SUBSCRIPTION_INACTIVE402No active subscription — upgrade required
UNAUTHORIZED401Missing or invalid API key / secret
NOT_FOUND404File or folder ID does not exist
TIMEOUT408Request exceeded the configured timeout
UNKNOWNUnexpected error; check message for details

SDK config

The Node SDK supports configurable timeouts and automatic retries with exponential back-off. Use setTimeout() and setRetry() to change settings at runtime.

const client = new VaultSensClient({
  baseUrl: 'https://api.vaultsens.com',
  apiKey: 'fs_xxx',
  apiSecret: 'sk_xxx',
  timeoutMs: 30000,
  retry: {
    retries: 2,
    retryDelayMs: 400,
    retryOn: [429, 500, 502, 503, 504],
  },
});

// Update at runtime
client.setTimeout(60000);
client.setRetry({ retries: 3, retryDelayMs: 800 });

Examples

Browser file input

const file = input.files[0];
const result = await client.uploadFile(file, { compression: 'low' });
console.log(result.data.url);

Node.js — upload from disk

import { readFile } from 'node:fs/promises';
import { fileFromBuffer } from '@vaultsens/sdk';

const buffer = await readFile('./logo.png');
const file   = fileFromBuffer(buffer, 'logo.png', 'image/png');
const result = await client.uploadFile(file);
console.log(result.data.url);

Responsive image URL

const src    = client.buildFileUrl(fileId, { width: 1200, format: 'webp' });
const srcset = [
  client.buildFileUrl(fileId, { width: 400,  format: 'webp' }) + ' 400w',
  client.buildFileUrl(fileId, { width: 800,  format: 'webp' }) + ' 800w',
  client.buildFileUrl(fileId, { width: 1200, format: 'webp' }) + ' 1200w',
].join(', ');

// <img src={src} srcset={srcset} />

Changelog

0.1.9 — Node SDK

  • Minor internal improvements and dependency updates

0.1.8

  • Folder management: createFolder, listFolders, renameFolder, deleteFolder
  • Compression option on upload: none / low / medium / high
  • folderId option on upload to place files in a folder
  • Typed error codes via VaultSensErrorCode across all three SDKs
  • New error codes: FILE_COUNT_LIMIT, FOLDER_COUNT_LIMIT, MIME_TYPE_NOT_ALLOWED, COMPRESSION_NOT_ALLOWED
  • Removed deprecated transform upload option
  • PHP: added version field to composer.json

0.1.0

  • Initial SDK release across Node, Python, and PHP
  • File upload, list, update, delete, and metadata
  • buildFileUrl with transform query params
  • Storage metrics via getMetrics
  • Node: built-in retry and timeout support

VaultSens SDK • Open source • MIT

GitHub