UploadAura
UploadAura SDK

Ship uploads in three lines.

A small Node.js client for the UploadAura file API. Point it at a path, a Buffer, or a stream — get back stable file IDs and public URLs.

Node 18+ TypeScript Server-side

01Installation

Install from npm. The SDK ships its own types — no @types needed.

bash
npm install uploadaura-sdk

02Quick start

Create a client with your API key, then upload. Files resolve to a typed result.

ts
import { UploadAura } from "uploadaura-sdk";

const aura = new UploadAura({
  apiKey: "sk_live_your_key_here", // from the UploadAura dashboard
});

const { files, failed } = await aura.upload("./photo.jpg");

console.log(files[0].fileId);       // "64f1a2b3c4d5e6f7a8b9c0d1"
console.log(files[0].originalName);  // "photo.jpg"
console.log(files[0].size);          // 204800  (bytes)

03File sources

upload() accepts a path, an in-memory buffer, a readable stream, or an array mixing all three (up to 10 files per call).

Path

ts
// Single file
await aura.upload("./report.pdf");

// Multiple files (max 10)
await aura.upload(["./a.jpg", "./b.png", "./c.pdf"]);

Buffer

ts
import fs from "node:fs";

const buffer = fs.readFileSync("./photo.jpg");

await aura.upload({
  buffer,
  name: "photo.jpg",                 // required: name with extension
  type: "image/jpeg",                // optional: defaults to application/octet-stream
});

Stream

ts
import fs from "node:fs";

const stream = fs.createReadStream("./data.csv");

await aura.upload({
  stream,
  name: "data.csv",
  type: "text/csv",
});

Mixed array

ts
import fs from "node:fs";

await aura.upload([
  "./cover.jpg",
  { buffer: pdfBytes, name: "doc.pdf", type: "application/pdf" },
  { stream: fs.createReadStream("./log.txt"), name: "log.txt" },
]);

04API reference

new UploadAura(config)

ts
interface UploadAuraConfig {
  /** Your API key from the dashboard. Must start with "sk_". */
  apiKey: string;
  /**
   * Backend base URL (no trailing slash). Optional — resolved in this order:
   *   1. this value
   *   2. the UPLOADAURA_BASE_URL environment variable
   *   3. the hosted default https://uploadaurabackend.yaqoobhalepoto.dev
   */
  baseUrl?: string;
}

aura.upload(files)

ts
// Accepts a single source or an array of up to 10 sources.
upload(files: FileSource | FileSource[]): Promise<UploadResult>

type FileSource =
  | string                 // path on disk
  | BufferSource          // { buffer, name, type? }
  | StreamSource          // { stream, name, type? }

Returns

ts
interface UploadResult {
  files:   UploadedFile[]; // successfully uploaded files
  failed:  number;         // files that failed on the server
  message: string;         // human-readable summary
}

interface UploadedFile {
  fileId:       string;  // MongoDB ObjectId — share or manage this file
  originalName: string;
  size:         number;  // bytes
  ext:          string;  // e.g. "pdf", "jpg" (no dot)
  mimeType:     string;  // e.g. "application/pdf"
  url:          string;  // public, viewable URL: /files/:fileId/view
}

05Error handling

Network and validation failures throw a typed UploadAuraError with a stablecode you can branch on.

ts
import { UploadAura, UploadAuraError } from "uploadaura-sdk";

try {
  await aura.upload("./huge.zip");
} catch (err) {
  if (err instanceof UploadAuraError) {
    console.error(err.message); // "Insufficient Storage . 123456 needed"
    console.error(err.code);    // "INSUFFICIENT_STORAGE"
    console.error(err.status);  // 400
  }
}
CodeHTTPWhen
INSUFFICIENT_STORAGE400Storage quota exceeded
VALIDATION_ERROR400Invalid request body
ACCESS_UNAUTHORIZED401Invalid or missing API key
NETWORK_ERROR0Could not reach the backend

06Constraints

10Max files / request
100 MBMax file size
2 GBStorage quota (free)
18+Minimum Node.js

07Frameworks

The SDK is server-side only (Node APIs). Drop it into your backend — an Express route, a Next.js Route Handler, or a NestJS controller — and forward the upload.

Express

server.ts
import express from "express";
import multer from "multer";
import { UploadAura, UploadAuraError } from "uploadaura-sdk";

const upload = multer(); // in-memory
const aura = new UploadAura({ apiKey: process.env.UPLOADAURA_API_KEY! });

const app = express();

app.post("/upload", upload.array("files"), async (req, res) => {
  try {
    const sources = (req.files as Express.Multer.File[]).map((f) => ({
      buffer: f.buffer,
      name: f.originalname,
      type: f.mimetype,
    }));
    const { files } = await aura.upload(sources);
    res.json({ files });
  } catch (err) {
    if (err instanceof UploadAuraError) {
      res.status(err.status || 500).json({ error: err.message, code: err.code });
    } else {
      res.status(500).json({ error: "Upload failed" });
    }
  }
});

Next.js (App Router)

app/api/upload/route.ts
// app/api/upload/route.ts
import { NextRequest, NextResponse } from "next/server";
import { UploadAura, UploadAuraError } from "uploadaura-sdk";

export const runtime = "nodejs"; // required: the SDK relies on Node APIs (fs, Buffer, streams)

const aura = new UploadAura({ apiKey: process.env.UPLOADAURA_API_KEY! });

export async function POST(req: NextRequest) {
  const form = await req.formData();
  const file = form.get("file");

  if (!(file instanceof File)) {
    return NextResponse.json({ error: "No file provided" }, { status: 400 });
  }

  const buffer = Buffer.from(await file.arrayBuffer());

  try {
    const { files } = await aura.upload({
      buffer,
      name: file.name,
      type: file.type,
    });
    return NextResponse.json({ url: files[0].url });
  } catch (err) {
    if (err instanceof UploadAuraError) {
      return NextResponse.json(
        { error: err.message, code: err.code },
        { status: err.status || 500 },
      );
    }
    return NextResponse.json({ error: "Upload failed" }, { status: 500 });
  }
}

NestJS

upload.controller.ts
import { Controller, Post, UploadedFiles, UseInterceptors, BadRequestException } from "@nestjs/common";
import { FilesInterceptor } from "@nestjs/platform-express";
import { UploadAura, UploadAuraError } from "uploadaura-sdk";

const aura = new UploadAura({ apiKey: process.env.UPLOADAURA_API_KEY! });

@Controller("upload")
export class UploadController {
  @Post()
  @UseInterceptors(FilesInterceptor("files"))
  async upload(@UploadedFiles() files: Express.Multer.File[]) {
    if (!files?.length) throw new BadRequestException("No files");
    const sources = files.map((f) => ({
      buffer: f.buffer,
      name: f.originalname,
      type: f.mimetype,
    }));
    try {
      const { files: uploaded } = await aura.upload(sources);
      return { files: uploaded };
    } catch (err) {
      if (err instanceof UploadAuraError) {
        throw new BadRequestException(err.message);
      }
      throw err;
    }
  }
}

Plain Node.js / CommonJS

upload.js
const { UploadAura, UploadAuraError } = require("uploadaura-sdk");

const aura = new UploadAura({ apiKey: "sk_live_..." });

aura.upload("./file.pdf")
  .then(({ files }) => console.log(files))
  .catch(console.error);

Need a signed URL or resumable upload? The REST API mirrors this SDK 1:1 — see POST /api/v1/upload with Authorization: Bearer <key>.