Skip to content

JavaScript Examples

Complete working examples using the built-in fetch API (Node.js 18+).

Setup

const fs = require("fs");
const path = require("path");

const BASE_URL = "https://api.icana.ai/api/v1";
const API_KEY = "sk_test_your_api_key_here"; // Use an environment variable in production!
const HEADERS = { "X-API-Key": API_KEY };

Submit a transcription

async function transcribe(filePath, language = "en", prompt = null) {
  const formData = new FormData();
  const fileBuffer = fs.readFileSync(filePath);
  const blob = new Blob([fileBuffer]);
  formData.append("file", blob, path.basename(filePath));
  formData.append("language", language);
  if (prompt) {
    formData.append("prompt", prompt);
  }

  const response = await fetch(`${BASE_URL}/transcribe`, {
    method: "POST",
    headers: HEADERS,
    body: formData,
  });

  if (!response.ok) {
    throw new Error(`Transcribe failed: ${response.status} ${await response.text()}`);
  }

  return response.json();
}
const result = await transcribe("meeting.mp3", "en", "Icana, APAC, CallCoach, AUD");
console.log(`Job ID: ${result.job_id}`);
// Job ID: 550e8400-e29b-41d4-a716-446655440000

Poll for results

async function pollJob(jobId, intervalMs = 5000, maxAttempts = 120) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(`${BASE_URL}/jobs/${jobId}`, {
      headers: HEADERS,
    });

    if (!response.ok) {
      throw new Error(`Status check failed: ${response.status}`);
    }

    const job = await response.json();
    console.log(`Attempt ${attempt}: ${job.status}`);

    if (job.status === "completed") {
      return job;
    } else if (job.status === "failed") {
      throw new Error(`Job failed: ${job.error_message}`);
    }

    await new Promise((resolve) => setTimeout(resolve, intervalMs));
  }

  throw new Error(`Job ${jobId} did not complete after ${maxAttempts} attempts`);
}
const job = await pollJob(result.job_id);
console.log(`Transcription: ${job.transcription.substring(0, 200)}...`);
console.log(`Duration: ${job.audio_duration_minutes.toFixed(1)} minutes`);

List jobs

async function listJobs(page = 1, pageSize = 20, status = null) {
  const params = new URLSearchParams({ page, page_size: pageSize });
  if (status) {
    params.append("status", status);
  }

  const response = await fetch(`${BASE_URL}/jobs?${params}`, {
    headers: HEADERS,
  });

  if (!response.ok) {
    throw new Error(`List jobs failed: ${response.status}`);
  }

  return response.json();
}
const result = await listJobs(1, 5, "completed");
console.log(`Total jobs: ${result.total}`);
for (const job of result.jobs) {
  console.log(`  ${job.id} - ${job.original_filename} (${job.audio_duration_minutes.toFixed(1)} min)`);
}

Check usage

async function getUsage() {
  const response = await fetch(`${BASE_URL}/usage`, {
    headers: HEADERS,
  });

  if (!response.ok) {
    throw new Error(`Usage check failed: ${response.status}`);
  }

  return response.json();
}
const usage = await getUsage();
console.log(`Minutes used: ${usage.minutes_used}`);
console.log(`Balance: $${usage.balance_aud} AUD`);

Complete example

End-to-end script that transcribes a file and prints the results:

const fs = require("fs");
const path = require("path");

const BASE_URL = "https://api.icana.ai/api/v1";
const API_KEY = process.env.ICANA_API_KEY;
const HEADERS = { "X-API-Key": API_KEY };

async function transcribeFile(filePath, language = "en", prompt = null) {
  // 1. Submit the file
  console.log(`Submitting ${filePath}...`);
  const formData = new FormData();
  const fileBuffer = fs.readFileSync(filePath);
  const blob = new Blob([fileBuffer]);
  formData.append("file", blob, path.basename(filePath));
  formData.append("language", language);
  if (prompt) {
    formData.append("prompt", prompt);
  }

  const submitResponse = await fetch(`${BASE_URL}/transcribe`, {
    method: "POST",
    headers: HEADERS,
    body: formData,
  });

  if (!submitResponse.ok) {
    throw new Error(`Submit failed: ${submitResponse.status} ${await submitResponse.text()}`);
  }

  const { job_id: jobId } = await submitResponse.json();
  console.log(`Job submitted: ${jobId}`);

  // 2. Poll for results
  while (true) {
    const statusResponse = await fetch(`${BASE_URL}/jobs/${jobId}`, {
      headers: HEADERS,
    });

    if (!statusResponse.ok) {
      throw new Error(`Status check failed: ${statusResponse.status}`);
    }

    const job = await statusResponse.json();

    if (job.status === "completed") {
      console.log(`Completed — ${job.audio_duration_minutes.toFixed(1)} minutes of audio`);
      return job;
    } else if (job.status === "failed") {
      throw new Error(`Transcription failed: ${job.error_message}`);
    }

    console.log(`  Status: ${job.status}...`);
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
}

// Run
(async () => {
  try {
    const result = await transcribeFile("meeting.mp3");

    console.log("\n--- Transcription ---");
    console.log(result.transcription);

    console.log("\n--- Speaker Diarization ---");
    console.log(result.diarization);
  } catch (error) {
    console.error("Error:", error.message);
    process.exit(1);
  }
})();

Run it:

export ICANA_API_KEY="sk_test_your_api_key_here"
node transcribe.js