Skip to main content

JS/TS Examples for adaline.ink

JavaScript and TypeScript code examples for the Adaline platform API using fetch with async/await.

All examples use the native fetch API with async/await. Works in Node.js 18+, Deno, Bun, and all modern browsers.

TypeScript Types

interface User {
  id: string;
  email: string;
  full_name: string | null;
  is_active: boolean;
  onboarding_step: number;
  onboarding_completed: boolean;
}

interface Document {
  id: string;
  filename: string;
  content_type: string;
  size_bytes: number | null;
  doc_type: string;
  created_at: string;
  uploaded_by_name?: string;
  tags: Tag[];
}

interface Tag {
  id: string;
  name: string;
  color: string | null;
}

interface ComplianceReport {
  overall_score: number;
  grade: "A" | "B" | "C" | "D" | "F";
  compliant: boolean;
  total_passed: number;
  total_checks: number;
  categories: Record<string, { score: number; weight: number; passed: number; total: number }>;
  checks: { check_id: string; passed: boolean; details: string; severity: string }[];
}

interface ConversionJob {
  id: string;
  document_id: string;
  status: string;
  steps: { step_name: string; status: string; duration_ms: number | null }[];
}

Setup

const BASE_URL = "https://api.adaline.ink";
let accessToken = "";
let refreshToken = "";

async function api(path: string, options: RequestInit = {}) {
  const res = await fetch(`${BASE_URL}${path}`, {
    ...options,
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
      ...options.headers,
    },
  });
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    throw new Error(body.detail || body.error || `API error: ${res.status}`);
  }
  if (res.status === 204) return null;
  return res.json();
}

Authentication

async function login(email: string, password: string) {
  const data = await api("/api/v1/auth/login", {
    method: "POST",
    body: JSON.stringify({ email, password }),
  });
  accessToken = data.access_token;
  refreshToken = data.refresh_token;
  return data;
}

async function register(email: string, password: string, fullName: string) {
  const res = await fetch(`${BASE_URL}/api/v1/auth/register`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, password, full_name: fullName }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.detail || "Registration failed");
  accessToken = data.tokens.access_token;
  refreshToken = data.tokens.refresh_token;
  return data.user;
}

async function refreshAccessToken() {
  const data = await api("/api/v1/auth/refresh", {
    method: "POST",
    body: JSON.stringify({ refresh_token: refreshToken }),
  });
  accessToken = data.access_token;
  refreshToken = data.refresh_token;
}

await login("you@example.com", "your-password");

Upload a Document

async function uploadDocument(orgId: string, file: File): Promise<Document> {
  const formData = new FormData();
  formData.append("file", file);

  const res = await fetch(
    `${BASE_URL}/api/v1/documents/upload?org_id=${orgId}`,
    {
      method: "POST",
      headers: { Authorization: `Bearer ${accessToken}` },
      body: formData,
    }
  );
  if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
  return res.json();
}

Node.js File Upload

import { readFileSync } from "fs";

async function uploadFile(orgId: string, filePath: string) {
  const file = readFileSync(filePath);
  const blob = new Blob([file]);
  const formData = new FormData();
  formData.append("file", blob, filePath.split("/").pop());

  const res = await fetch(
    `${BASE_URL}/api/v1/documents/upload?org_id=${orgId}`,
    {
      method: "POST",
      headers: { Authorization: `Bearer ${accessToken}` },
      body: formData,
    }
  );
  if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
  return res.json();
}

const doc = await uploadFile("your-org-id", "./syllabus.pdf");
console.log(`Uploaded: ${doc.id} (${doc.doc_type})`);

List Documents

async function listDocuments(orgId: string): Promise<{ items: Document[]; total: number }> {
  return api(`/api/v1/documents/?org_id=${orgId}`);
}

const { items } = await listDocuments("your-org-id");
for (const doc of items) {
  const tags = doc.tags.map((t) => t.name).join(", ");
  console.log(`${doc.filename} (${doc.doc_type}) - ${doc.uploaded_by_name || "Unknown"}`);
  if (tags) console.log(`  Tags: ${tags}`);
}

Run Compliance Check

async function runCompliance(documentId: string): Promise<ComplianceReport> {
  return api("/api/v1/compliance/test", {
    method: "POST",
    body: JSON.stringify({ document_id: documentId }),
  });
}

const report = await runCompliance(doc.id);
console.log(`Score: ${report.overall_score}% (Grade ${report.grade})`);
console.log(`Passed: ${report.total_passed}/${report.total_checks}`);

// Failed checks
report.checks
  .filter((c) => !c.passed)
  .forEach((c) => console.log(`  [${c.severity}] ${c.details}`));

Start a Conversion

async function convertDocument(documentId: string): Promise<ConversionJob> {
  // Start the job
  const job = await api("/api/v1/conversions/", {
    method: "POST",
    body: JSON.stringify({ document_id: documentId }),
  });

  // Poll for completion
  const jobId = job.job_id;
  while (true) {
    const status: ConversionJob = await api(`/api/v1/conversions/${jobId}`);
    console.log(`Status: ${status.status}`);
    status.steps.forEach((s) => {
      const ms = s.duration_ms ? ` (${s.duration_ms}ms)` : "";
      console.log(`  ${s.step_name}: ${s.status}${ms}`);
    });

    if (["completed", "failed", "error"].includes(status.status)) {
      return status;
    }
    await new Promise((r) => setTimeout(r, 2000));
  }
}

const result = await convertDocument(doc.id);

Manage Tags

async function createTag(orgId: string, name: string, color?: string): Promise<Tag> {
  return api("/api/v1/tags", {
    method: "POST",
    body: JSON.stringify({ name, color, org_id: orgId }),
  });
}

async function tagDocument(tagId: string, docId: string) {
  return api(`/api/v1/tags/${tagId}/documents/${docId}`, { method: "POST" });
}

async function removeTag(tagId: string, docId: string) {
  return api(`/api/v1/tags/${tagId}/documents/${docId}`, { method: "DELETE" });
}

const tag = await createTag("your-org-id", "reviewed", "green");
await tagDocument(tag.id, doc.id);

Share a Document

async function shareWithUser(docId: string, email: string, permission = "view") {
  return api(`/api/v1/documents/${docId}/shares`, {
    method: "POST",
    body: JSON.stringify({ user_email: email, permission }),
  });
}

async function createPublicLink(docId: string) {
  return api(`/api/v1/documents/${docId}/public-share`, {
    method: "POST",
    body: JSON.stringify({}),
  });
}

const share = await shareWithUser(doc.id, "colleague@example.com");
const publicLink = await createPublicLink(doc.id);
console.log(`Public link: ${publicLink.url}`);

Batch Upload and Score

import { readdir } from "fs/promises";
import { join } from "path";

async function batchUploadAndScore(orgId: string, directory: string) {
  const files = await readdir(directory);
  const supported = [".pdf", ".docx", ".pptx", ".html"];
  const results = [];

  for (const file of files) {
    if (!supported.some((ext) => file.endsWith(ext))) continue;

    console.log(`Processing ${file}...`);
    try {
      const doc = await uploadFile(orgId, join(directory, file));
      const report = await runCompliance(doc.id);
      results.push({ file, score: report.overall_score, grade: report.grade });
      console.log(`  ${report.overall_score}% (${report.grade})`);
    } catch (err) {
      results.push({ file, error: (err as Error).message });
    }
  }
  return results;
}

const results = await batchUploadAndScore("your-org-id", "./documents");
console.table(results);

Error Handling

async function safeApi<T>(fn: () => Promise<T>): Promise<T | null> {
  try {
    return await fn();
  } catch (err) {
    const msg = (err as Error).message;
    if (msg.includes("401")) {
      console.error("Token expired. Refreshing...");
      await refreshAccessToken();
      return fn(); // retry once
    }
    if (msg.includes("429")) {
      console.error("Rate limited. Waiting 5s...");
      await new Promise((r) => setTimeout(r, 5000));
      return fn();
    }
    console.error("API error:", msg);
    return null;
  }
}

const report = await safeApi(() => runCompliance("doc-id"));
© 2026 Adaline LLC