Finetuning.aiFinetuning.ai

JavaScript / TypeScript

API examples using JavaScript and TypeScript

Setup

const API_KEY = process.env.FINETUNING_API_KEY;
const BASE_URL = 'https://pub.finetuning.ai';

async function api(path: string, options?: RequestInit) {
  const res = await fetch(`${BASE_URL}${path}`, {
    ...options,
    headers: {
      'X-API-Key': API_KEY!,
      'Content-Type': 'application/json',
      ...options?.headers,
    },
  });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(`API error ${res.status}: ${error.error.message}`);
  }

  return res.json();
}

Check account info

const me = await api('/v1/me');
console.log(`Credits remaining: ${me.data.limits.totalRemaining}`);

Create a generation

const generation = await api('/v1/generations', {
  method: 'POST',
  body: JSON.stringify({
    tags: 'chill lo-fi hip hop beat with vinyl crackle and soft piano',
    duration: 60,
    bpm: 85,
    key: 'D',
    scale: 'minor',
  }),
});

console.log(`Generation ID: ${generation.data.id}`);
console.log(`Status: ${generation.data.status}`);

Poll for completion

async function waitForGeneration(id: string): Promise<any> {
  while (true) {
    const { data } = await api(`/v1/generations/${id}`);

    if (data.status === 'completed') {
      console.log(`Done! Audio URL: ${data.audioUrl}`);
      return data;
    }

    if (data.status === 'failed') {
      throw new Error(`Generation failed: ${data.errorMessage}`);
    }

    console.log(`Status: ${data.status}... waiting`);
    await new Promise(r => setTimeout(r, 3000));
  }
}

const completed = await waitForGeneration(generation.data.id);

Download the track

import { writeFile } from 'fs/promises';

const audioRes = await fetch(completed.audioUrl);
const buffer = Buffer.from(await audioRes.arrayBuffer());
await writeFile('output.mp3', buffer);
console.log('Saved to output.mp3');

Full example: Generate and download

import { writeFile } from 'fs/promises';

const API_KEY = process.env.FINETUNING_API_KEY!;
const BASE = 'https://pub.finetuning.ai';

async function main() {
  // 1. Create generation
  const res = await fetch(`${BASE}/v1/generations`, {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      tags: 'epic cinematic orchestral piece with rising strings',
      duration: 90,
    }),
  });
  const { data: gen } = await res.json();
  console.log(`Created: ${gen.id}`);

  // 2. Poll until complete
  let result;
  while (true) {
    const check = await fetch(`${BASE}/v1/generations/${gen.id}`, {
      headers: { 'X-API-Key': API_KEY },
    });
    const { data } = await check.json();
    result = data;
    if (result.status === 'completed' || result.status === 'failed') break;
    await new Promise(r => setTimeout(r, 3000));
  }

  if (result.status === 'failed') {
    console.error('Failed:', result.errorMessage);
    return;
  }

  // 3. Download
  const audio = await fetch(result.audioUrl);
  await writeFile('epic-track.mp3', Buffer.from(await audio.arrayBuffer()));
  console.log('Saved to epic-track.mp3');
}

main();

On this page