KKiosapi.id

← Dokumentasi

Panduan JavaScript/TypeScript — SDK OpenAI

Kiosapi 100% kompatibel dengan SDK resmi openai npm untuk chat, streaming, tool-calling, vision, dan embeddings — cukup ganti baseURL & apiKey. Contoh di bawah jalan sama persis di JavaScript maupun TypeScript (ESM). Endpoint khusus Kiosapi (gambar, video, musik, TTS, reranking, vector DB) punya bentuk sendiri, dipanggil lewat fetch biasa — contoh lengkap di bagian 10.

Daftar isi

1. Persiapan

Dapatkan API key

Masuk ke dashboard → Kunci API, beri nama (mis. "node-app"), klik Buat key, salin kios_live_… (ditampilkan sekali).

Install SDK

npm install openai
Keamanan: panggil API dari server/backend (Node.js, API route, server action) — jangan taruh kios_live_… di kode yang jalan di browser. Simpan sebagai environment variable, jangan hardcode.
# .env
KIOSAPI_API_KEY=kios_live_xxxxxxxxxxxx

2. Inisialisasi client

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.kiosapi.id/v1",
  apiKey: process.env.KIOSAPI_API_KEY,
});

Model ID berformat provider/nama-model — lihat daftar lengkap via GET /v1/models atau /pricing. Contoh: openai/gpt-4o, anthropic/claude-sonnet-4-6, deepseek/deepseek-v4-flash.

3. Chat completion dasar

const resp = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4-6",
  messages: [
    { role: "system", content: "Kamu asisten yang ringkas dan ramah." },
    { role: "user", content: "Jelaskan apa itu RAG dalam 2 kalimat." },
  ],
});
console.log(resp.choices[0].message.content);
console.log("Token dipakai:", resp.usage?.total_tokens);

4. Streaming

Tambahkan stream: true — respons muncul token demi token (SSE).

const stream = await client.chat.completions.create({
  model: "deepseek/deepseek-v4-flash",
  messages: [{ role: "user", content: "Tulis puisi pendek tentang hujan di Jakarta." }],
  stream: true,
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) process.stdout.write(delta);
}

Model reasoning (🧠) bisa mengirim delta reasoning_content terpisah dari content — cek atribut itu untuk menampilkan status "sedang berpikir" alih-alih menganggapnya bagian jawaban akhir.

5. Tool calling / function calling

Format sama persis dengan OpenAI — didukung untuk model bertanda 🔧 di katalog, termasuk Claude & Gemini (diterjemahkan otomatis oleh gateway ke format native masing-masing).

const tools = [
  {
    type: "function",
    function: {
      name: "get_weather",
      description: "Ambil cuaca terkini untuk sebuah kota",
      parameters: {
        type: "object",
        properties: { city: { type: "string", description: "Nama kota" } },
        required: ["city"],
      },
    },
  },
];

const messages = [{ role: "user", content: "Cuaca di Bandung sekarang gimana?" }];
const resp = await client.chat.completions.create({ model: "openai/gpt-4o", messages, tools });

const msg = resp.choices[0].message;
if (msg.tool_calls) {
  for (const call of msg.tool_calls) {
    console.log("Model minta panggil:", call.function.name, call.function.arguments);
    messages.push(msg);
    messages.push({
      role: "tool",
      tool_call_id: call.id,
      content: JSON.stringify({ suhu_celsius: 27, kondisi: "berawan" }),
    });
  }
  const followup = await client.chat.completions.create({ model: "openai/gpt-4o", messages });
  console.log(followup.choices[0].message.content);
}

6. Vision (kirim gambar ke model)

Kirim gambar lewat content berbentuk array (image_url + text) — format persis yang dipakai perintah lihat di Kiosapi CLI. Gambar bisa berupa URL publik atau data URL base64.

import { readFileSync } from "node:fs";

const b64 = readFileSync("foto.jpg").toString("base64");

const resp = await client.chat.completions.create({
  model: "google/gemini-2.5-flash", // pilih model yang mendukung vision
  messages: [
    {
      role: "user",
      content: [
        { type: "text", text: "Ada apa saja di foto ini?" },
        { type: "image_url", image_url: { url: `data:image/jpeg;base64,${b64}` } },
      ],
    },
  ],
});
console.log(resp.choices[0].message.content);

Catatan: fitur ini sudah jalan di level API/CLI. Tombol upload gambar langsung di dashboard web belum tersedia — pakai jalur API/CLI ini sementara.

7. Structured output / JSON mode

response_format diteruskan langsung ke provider upstream — jalan penuh untuk model yang mendukungnya secara native. Belum ada lapisan pemaksaan JSON yang seragam untuk semua model di katalog — untuk model yang tidak mendukung native, parameter ini bisa diabaikan diam-diam, jadi tetap validasi hasilnya sendiri.

const resp = await client.chat.completions.create({
  model: "openai/gpt-4o",
  messages: [{ role: "user", content: "Beri saya data profil singkat dalam JSON: nama, umur." }],
  response_format: { type: "json_object" },
});
const data = JSON.parse(resp.choices[0].message.content);
console.log(data);

8. Embeddings

const resp = await client.embeddings.create({
  model: "openai/text-embedding-3-small",
  input: "Selamat datang di Kiosapi!",
});
const vector = resp.data[0].embedding;
console.log(vector.length, "dimensi");

9. Daftar model & cek saldo

const headers = { Authorization: `Bearer ${process.env.KIOSAPI_API_KEY}` };

const models = await (await fetch("https://api.kiosapi.id/v1/models", { headers })).json();

// Saldo & kuota gratis harian (endpoint khusus Kiosapi)
const saldo = await (await fetch("https://api.kiosapi.id/v1/saldo", { headers })).json();
console.log(saldo);

10. Endpoint khusus Kiosapi (via fetch)

Bentuknya beda dari method SDK OpenAI standar (mis. images.generate), jadi dipanggil langsung lewat HTTP.

Gambar — POST /v1/images/generations (sinkron)

import { writeFileSync } from "node:fs";

const res = await fetch("https://api.kiosapi.id/v1/images/generations", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "google/imagen-3",
    prompt: "kucing oranye memakai topi koki, fotorealistik",
    option: "standard",
    n: 1,
  }),
});
const data = await res.json();
writeFileSync("hasil.png", Buffer.from(data.data[0].b64_json, "base64"));
console.log("Biaya:", data.kiosapi.cost_rupiah, "rupiah");

Video — POST /v1/videos/generations (asinkron, perlu polling)

const submit = await (await fetch("https://api.kiosapi.id/v1/videos/generations", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "alibaba/wan2.7-t2v",
    prompt: "ombak pantai saat matahari terbenam, sinematik",
    option: "standard",
    duration_seconds: 5,
  }),
})).json();

let job;
do {
  await new Promise((r) => setTimeout(r, 5000));
  job = await (await fetch(`https://api.kiosapi.id/v1/jobs/${submit.job_id}`, { headers })).json();
} while (job.status === "running");

if (job.status === "succeeded") console.log("Video siap:", job.video_url);
else if (job.status === "failed") console.log("Gagal:", job.error);

Image-to-video: sertakan image (base64) + image_mime di body request.

Musik — POST /v1/music/generations

google/lyria-2 = klip instrumental 30 detik, sinkron. minimax/music-2.6 = lagu bervokal penuh hingga ±5 menit, asinkron (pola polling sama seperti video, hasil di audio_url).

const resp = await (await fetch("https://api.kiosapi.id/v1/music/generations", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "minimax/music-2.6",
    prompt: "pop akustik Indonesia yang hangat, vokal wanita",
    lyrics: "[Verse]\nPagi cerah di kota\n[Chorus]\nBersama kita bisa",
  }),
})).json();
// poll GET /v1/jobs/{resp.job_id} sampai status "succeeded" → field "audio_url"

Text-to-speech — POST /v1/audio/speech

Kompatibel OpenAI (input + voice), respons berupa bytes audio mentah.

const res = await fetch("https://api.kiosapi.id/v1/audio/speech", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "minimax/speech-2.8-turbo",
    input: "Selamat datang di Kiosapi!",
    voice: "Indonesian_CalmWoman", // 9 suara asli Indonesia (model MiniMax)
  }),
});
writeFileSync("suara.mp3", Buffer.from(await res.arrayBuffer()));

Reranking — POST /v1/rerank (bentuk Cohere, self-hosted)

const res = await (await fetch("https://api.kiosapi.id/v1/rerank", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "baai/bge-reranker-base",
    query: "apa itu kucing?",
    documents: [
      "Kucing adalah hewan mamalia berkaki empat.",
      "Mobil listrik semakin populer di Indonesia.",
    ],
    return_documents: true,
  }),
})).json();
for (const r of res.results) console.log(r.index, r.relevance_score);

Vector DB — POST /v1/vector-indexes/... (bentuk Pinecone, self-hosted)

// 1) Bikin index (gratis)
await fetch("https://api.kiosapi.id/v1/vector-indexes", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "artikel-saya" }),
});

// 2) Buat embedding lalu upsert (values wajib 1536 angka, cocok text-embedding-3-small)
const emb = await client.embeddings.create({
  model: "openai/text-embedding-3-small",
  input: "Isi artikel di sini",
});
const vector = emb.data[0].embedding;

await fetch("https://api.kiosapi.id/v1/vector-indexes/artikel-saya/vectors/upsert", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({
    vectors: [{ id: "artikel-1", values: vector, metadata: { kategori: "berita" } }],
  }),
});

// 3) Cari yang paling relevan
const hasil = await (await fetch("https://api.kiosapi.id/v1/vector-indexes/artikel-saya/query", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ vector, top_k: 5, include_metadata: true }),
})).json();
console.log(hasil.matches);

11. Penanganan error

import OpenAI from "openai";

try {
  const resp = await client.chat.completions.create({
    model: "openai/gpt-4o",
    messages: [{ role: "user", content: "Halo!" }],
  });
} catch (err) {
  if (err instanceof OpenAI.APIError) {
    console.log("HTTP status:", err.status);
    console.log("Detail:", err.error);
  } else {
    throw err;
  }
}

Kode HTTP umum: 401 API key salah, 400 model tak dikenal/parameter salah, 402 saldo kurang atau batas pengeluaran bulanan tercapai, 422 ditolak moderasi, 429 rate limit, 502/504 provider upstream bermasalah/timeout. Kode error media lengkap ada di /docs.

12. Rate limit & kuota

FreeBerbayar
Rate limit5 req/menit60 req/menit
Kuota harian50 request/hari (reset 07:00 WIB), email terverifikasitanpa batas harian
Output maks~2048 tokensesuai maxOutput model
Input maks~24k karaktersesuai kapasitas model

13. Contoh lengkap — mini pipeline RAG

Menggabungkan embeddings + vector DB + chat dalam satu alur.

import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.kiosapi.id/v1", apiKey: process.env.KIOSAPI_API_KEY });
const headers = { Authorization: `Bearer ${process.env.KIOSAPI_API_KEY}`, "Content-Type": "application/json" };
const BASE = "https://api.kiosapi.id/v1";

async function embed(text) {
  const r = await client.embeddings.create({ model: "openai/text-embedding-3-small", input: text });
  return r.data[0].embedding;
}

// Index dokumen (sekali saja)
await fetch(`${BASE}/vector-indexes`, { method: "POST", headers, body: JSON.stringify({ name: "basis-pengetahuan" }) });
const dokumen = ["Kiosapi adalah AI API gateway Indonesia.", "Kiosapi mendukung 100+ model AI."];
const vectors = await Promise.all(
  dokumen.map(async (d, i) => ({ id: `doc-${i}`, values: await embed(d), metadata: { text: d } })),
);
await fetch(`${BASE}/vector-indexes/basis-pengetahuan/vectors/upsert`, {
  method: "POST", headers, body: JSON.stringify({ vectors }),
});

// Query + jawab pakai konteks yang relevan
const pertanyaan = "Apa itu Kiosapi?";
const hasil = await (await fetch(`${BASE}/vector-indexes/basis-pengetahuan/query`, {
  method: "POST", headers,
  body: JSON.stringify({ vector: await embed(pertanyaan), top_k: 2, include_metadata: true }),
})).json();
const konteks = hasil.matches.map((m) => m.metadata.text).join("\n");

const jawaban = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4-6",
  messages: [
    { role: "system", content: `Jawab berdasar konteks ini:\n${konteks}` },
    { role: "user", content: pertanyaan },
  ],
});
console.log(jawaban.choices[0].message.content);

Referensi lain: spesifikasi OpenAPI 3.1 lengkap, harga & daftar model di /pricing, panduan Python, dan dokumentasi utama di /docs.