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 openaikios_live_… di kode yang jalan di browser. Simpan sebagai environment variable, jangan hardcode.# .env
KIOSAPI_API_KEY=kios_live_xxxxxxxxxxxx2. 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
| Free | Berbayar | |
|---|---|---|
| Rate limit | 5 req/menit | 60 req/menit |
| Kuota harian | 50 request/hari (reset 07:00 WIB), email terverifikasi | tanpa batas harian |
| Output maks | ~2048 token | sesuai maxOutput model |
| Input maks | ~24k karakter | sesuai 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.