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"));