Developers

TypeScript SDK

A tiny, dependency-free TypeScript helper that wraps the presigned upload flow, downloads, and provenance verification — paste it into your project and go.

Overview

There is no package to install — the API is plain HTTP/JSON, so the “SDK” is a small client you can drop into any TypeScript project. It uses only the built-in fetch and crypto.subtle, so it runs in modern browsers, Node 18+, Deno, and edge runtimes.

Note

The client mirrors the three-step upload flow and the REST endpoints. Response shapes match the DTOs at the bottom of this page.

The client

udrive.tsTypeScript
export interface UdriveOptions {
  /** Base URL, e.g. https://udrive.one */
  baseUrl?: string;
  /** Forwarded as the Cookie header for authenticated calls (server-side). */
  cookie?: string;
}

export interface UploadInit {
  name: string;
  contentType?: string;
  visibility?: "public" | "unlisted" | "private";
  allowTraining?: boolean;
  trainingPrice?: number;
  expiresAt?: string | null;
}

export interface UploadResult {
  shortId: string;
  shareUrl: string;
}

async function sha256Hex(data: ArrayBuffer): Promise<string> {
  const digest = await crypto.subtle.digest("SHA-256", data);
  return [...new Uint8Array(digest)]
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

export function createUdrive(opts: UdriveOptions = {}) {
  const base = (opts.baseUrl ?? "https://udrive.one").replace(/\/+$/, "");

  async function api<T>(path: string, init?: RequestInit): Promise<T> {
    const res = await fetch(base + path, {
      ...init,
      headers: {
        "content-type": "application/json",
        ...(opts.cookie ? { cookie: opts.cookie } : {}),
        ...init?.headers,
      },
    });
    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      throw new Error(body?.error?.message ?? `udrive: ${res.status}`);
    }
    return res.json() as Promise<T>;
  }

  return { base, api, sha256Hex };
}

Uploading

One call presigns, PUTs the bytes, and finalizes — returning the share URL. It hashes the file so integrity is recorded.

upload.tsTypeScript
export async function upload(
  client: ReturnType<typeof createUdrive>,
  data: Blob | ArrayBuffer,
  init: UploadInit,
): Promise<UploadResult> {
  const bytes = data instanceof Blob ? await data.arrayBuffer() : data;
  const contentType =
    init.contentType ??
    (data instanceof Blob ? data.type : "application/octet-stream");

  // 1. Presign.
  const presign = await client.api<{
    fileId: string;
    uploadUrl: string;
    headers: Record<string, string>;
  }>("/api/upload/presign", {
    method: "POST",
    body: JSON.stringify({
      name: init.name,
      size: bytes.byteLength,
      contentType,
      visibility: init.visibility ?? "unlisted",
      allowTraining: init.allowTraining,
      trainingPrice: init.trainingPrice,
      expiresAt: init.expiresAt,
    }),
  });

  // 2. Upload bytes straight to storage.
  const put = await fetch(presign.uploadUrl, {
    method: "PUT",
    headers: presign.headers,
    body: bytes,
  });
  if (!put.ok) throw new Error(`upload failed: ${put.status}`);

  // 3. Finalize with an integrity digest.
  return client.api<UploadResult>("/api/upload/complete", {
    method: "POST",
    body: JSON.stringify({
      fileId: presign.fileId,
      sha256: await client.sha256Hex(bytes),
    }),
  });
}
TypeScript
const udrive = createUdrive();
const file = new Blob(["id,score\n1,42\n"], { type: "text/csv" });

const { shareUrl } = await upload(udrive, file, {
  name: "scores.csv",
  visibility: "public",
});

console.log(shareUrl); // https://udrive.one/f/a1B2c3D4e5F6

Downloads & verification

TypeScript
// Public-safe metadata for a file view.
const meta = await udrive.api(`/api/f/${shortId}/meta`);

// Re-verify a provenance signature.
const proof = await udrive.api<{
  signed: boolean;
  verified: boolean;
  signerPubkey: string | null;
}>(`/api/verify/${shortId}`);

// The download URL mints a fresh presigned link on each hit.
const downloadUrl = `${udrive.base}/api/f/${shortId}/download`;

Shared types

The API responds with the same DTOs the udrive UI is typed against. These are the most useful ones to copy into your project:

dto.tsTypeScript
export type Visibility = "public" | "unlisted" | "private";
export type Encryption = "none" | "server" | "e2e";

export interface FileDTO {
  id: string;
  shortId: string;
  name: string;
  size: number;
  contentType: string;
  visibility: Visibility;
  encryption: Encryption;
  signed: boolean;
  signerPubkey: string | null;
  downloadCount: number;
  allowTraining: boolean;
  trainingPrice: string;
  shareUrl: string;
  downloadUrl: string;
  createdAt: string;
  expiresAt: string | null;
}

export interface ProvenanceResult {
  signed: boolean;
  verified: boolean;
  signerPubkey: string | null;
  statement: string | null;
}

Tip

Authenticated calls (your drive, earnings, account) need the udrive_sessioncookie. In the browser it's sent automatically; server-side, pass it via the cookie option.