Panduan Java
Kiosapi kompatibel OpenAI lewat REST biasa. Contoh di bawah pakai java.net.http.HttpClient bawaan JDK 11+ (tanpa dependensi eksternal) — gampang diadaptasi ke Jackson/Gson kalau proyek Anda sudah memakainya.
Daftar isi
1. Persiapan
Masuk ke dashboard → Kunci API, beri nama, klik Buat key, salin kios_live_… (ditampilkan sekali). Butuh JDK 11+ untuk java.net.http.
export KIOSAPI_API_KEY="kios_live_xxxxxxxxxxxx"2. Fungsi helper request
Contoh JSON manual pakai string builder sederhana — di proyek nyata, pakai Jackson (ObjectMapper) atau Gson untuk serialisasi yang lebih rapi.
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpResponse.BodyHandlers;
public class Kiosapi {
static final String BASE = "https://api.kiosapi.id/v1";
static final String API_KEY = System.getenv("KIOSAPI_API_KEY");
static final HttpClient client = HttpClient.newHttpClient();
static String post(String path, String jsonBody) throws Exception {
var req = HttpRequest.newBuilder(URI.create(BASE + path))
.header("Authorization", "Bearer " + API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
var res = client.send(req, BodyHandlers.ofString());
if (res.statusCode() >= 400) throw new RuntimeException("Kiosapi error " + res.statusCode() + ": " + res.body());
return res.body();
}
static String get(String path) throws Exception {
var req = HttpRequest.newBuilder(URI.create(BASE + path))
.header("Authorization", "Bearer " + API_KEY)
.GET().build();
return client.send(req, BodyHandlers.ofString()).body();
}
}Model ID berformat provider/nama-model — lihat daftar lengkap via GET /v1/models atau /pricing.
3. Chat completion dasar
var body = """
{"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."}
]}
""";
String json = Kiosapi.post("/chat/completions", body);
System.out.println(json); // parse dengan Jackson/Gson untuk ambil choices[0].message.content4. Streaming
Tambahkan "stream": true dan konsumsi respons per-baris (SSE) lewat BodyHandlers.ofLines().
var body = """
{"model":"deepseek/deepseek-v4-flash",
"messages":[{"role":"user","content":"Tulis puisi pendek tentang hujan di Jakarta."}],
"stream":true}
""";
var req = HttpRequest.newBuilder(URI.create(Kiosapi.BASE + "/chat/completions"))
.header("Authorization", "Bearer " + Kiosapi.API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
Kiosapi.client.send(req, HttpResponse.BodyHandlers.ofLines()).body()
.filter(line -> line.startsWith("data: ") && !line.equals("data: [DONE]"))
.map(line -> line.substring(6))
.forEach(chunkJson -> {
// parse chunkJson dengan Jackson/Gson, ambil choices[0].delta.content
System.out.print(extractDeltaContent(chunkJson));
});Model reasoning (🧠) bisa mengirim delta reasoning_content terpisah dari content — cek field itu di JSON delta untuk status "sedang berpikir".
5. Tool calling / function calling
Format sama persis OpenAI — didukung untuk model bertanda 🔧 di katalog, termasuk Claude & Gemini (diterjemahkan otomatis oleh gateway). Body JSON di bawah disederhanakan — pakai Jackson untuk membangun/membaca struktur ini di proyek nyata.
var body = """
{"model":"openai/gpt-4o",
"messages":[{"role":"user","content":"Cuaca di Bandung sekarang gimana?"}],
"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"]}
}
}]}
""";
String json = Kiosapi.post("/chat/completions", body);
// Jika respons mengandung tool_calls: kirim balik pesan assistant + { "role":"tool",
// "tool_call_id": ..., "content": "{\"suhu_celsius\":27,\"kondisi\":\"berawan\"}" }
// sebagai entri messages tambahan, lalu panggil ulang /chat/completions.6. Vision (kirim gambar ke model)
Kirim gambar lewat content berbentuk array (image_url + text) — format persis yang dipakai perintah lihat di Kiosapi CLI.
import java.util.Base64;
import java.nio.file.Files;
import java.nio.file.Path;
String b64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Path.of("foto.jpg")));
var body = """
{"model":"google/gemini-2.5-flash",
"messages":[{"role":"user","content":[
{"type":"text","text":"Ada apa saja di foto ini?"},
{"type":"image_url","image_url":{"url":"data:image/jpeg;base64,%s"}}
]}]}
""".formatted(b64);
String json = Kiosapi.post("/chat/completions", body);
System.out.println(json);Catatan: fitur ini sudah jalan di level API/CLI. Tombol upload gambar langsung di dashboard web belum tersedia.
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.
var body = """
{"model":"openai/gpt-4o",
"messages":[{"role":"user","content":"Beri saya data profil singkat dalam JSON: nama, umur."}],
"response_format":{"type":"json_object"}}
""";
String json = Kiosapi.post("/chat/completions", body);
// parse choices[0].message.content sebagai JSON dengan Jackson/Gson8. Embeddings
var body = """
{"model":"openai/text-embedding-3-small","input":"Selamat datang di Kiosapi!"}
""";
String json = Kiosapi.post("/embeddings", body);
// parse data[0].embedding sebagai array double9. Daftar model & cek saldo
String models = Kiosapi.get("/models");
// Saldo & kuota gratis harian (endpoint khusus Kiosapi)
String saldo = Kiosapi.get("/saldo");
System.out.println(saldo);10. Endpoint khusus Kiosapi
Bentuknya beda dari chat completions standar, tapi tetap lewat helper Kiosapi.post/Kiosapi.get yang sama.
Gambar — POST /v1/images/generations (sinkron)
var body = """
{"model":"google/imagen-3","prompt":"kucing oranye memakai topi koki, fotorealistik",
"option":"standard","n":1}
""";
String json = Kiosapi.post("/images/generations", body);
// parse data[0].b64_json, lalu:
// Files.write(Path.of("hasil.png"), Base64.getDecoder().decode(b64Json));Video — POST /v1/videos/generations (asinkron, perlu polling)
var submitBody = """
{"model":"alibaba/wan2.7-t2v","prompt":"ombak pantai saat matahari terbenam, sinematik",
"option":"standard","duration_seconds":5}
""";
String submitJson = Kiosapi.post("/videos/generations", submitBody);
String jobId = extractJobId(submitJson); // parse "job_id" dengan Jackson/Gson
String status;
String jobJson;
do {
Thread.sleep(5000);
jobJson = Kiosapi.get("/jobs/" + jobId);
status = extractStatus(jobJson);
} while ("running".equals(status));
if ("succeeded".equals(status)) System.out.println("Video siap: " + extractVideoUrl(jobJson));
else System.out.println("Gagal: " + extractError(jobJson));Image-to-video: sertakan image (base64) + image_mime di body request.
Musik — POST /v1/music/generations
var body = """
{"model":"minimax/music-2.6","prompt":"pop akustik Indonesia yang hangat, vokal wanita",
"lyrics":"[Verse]\nPagi cerah di kota\n[Chorus]\nBersama kita bisa"}
""";
String submitJson = Kiosapi.post("/music/generations", body);
// poll GET /jobs/{job_id} sampai status "succeeded" → field "audio_url"Text-to-speech — POST /v1/audio/speech
Respons berupa bytes audio mentah, jadi dipanggil pakai BodyHandlers.ofByteArray() alih-alih helper post() di atas.
var body = """
{"model":"minimax/speech-2.8-turbo","input":"Selamat datang di Kiosapi!",
"voice":"Indonesian_CalmWoman"}
""";
var req = HttpRequest.newBuilder(URI.create(Kiosapi.BASE + "/audio/speech"))
.header("Authorization", "Bearer " + Kiosapi.API_KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
var res = Kiosapi.client.send(req, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("suara.mp3"), res.body());Reranking — POST /v1/rerank (bentuk Cohere, self-hosted)
var body = """
{"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}
""";
String json = Kiosapi.post("/rerank", body);
// parse results[] → { index, relevance_score }Vector DB — POST /v1/vector-indexes/... (bentuk Pinecone, self-hosted)
// 1) Bikin index (gratis)
Kiosapi.post("/vector-indexes", "{\"name\":\"artikel-saya\"}");
// 2) Buat embedding lalu upsert (values wajib 1536 angka, cocok text-embedding-3-small)
String emb = Kiosapi.post("/embeddings", "{\"model\":\"openai/text-embedding-3-small\",\"input\":\"Isi artikel di sini\"}");
// ambil vector dari emb → data[0].embedding, lalu:
Kiosapi.post("/vector-indexes/artikel-saya/vectors/upsert",
"{\"vectors\":[{\"id\":\"artikel-1\",\"values\":" + vectorJson + ",\"metadata\":{\"kategori\":\"berita\"}}]}");
// 3) Cari yang paling relevan
String hasil = Kiosapi.post("/vector-indexes/artikel-saya/query",
"{\"vector\":" + vectorJson + ",\"top_k\":5,\"include_metadata\":true}");
System.out.println(hasil); // parse matches[]11. Penanganan error
try {
String json = Kiosapi.post("/chat/completions",
"{\"model\":\"openai/gpt-4o\",\"messages\":[{\"role\":\"user\",\"content\":\"Halo!\"}]}");
} catch (RuntimeException e) {
// Kiosapi.post sudah membungkus status HTTP >= 400 ke pesan exception
System.err.println(e.getMessage());
}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 (pemetaan JSON disederhanakan — pakai Jackson ObjectMapper di proyek nyata untuk serialisasi/deserialisasi yang aman-tipe).
// 1) Index dokumen (sekali saja)
Kiosapi.post("/vector-indexes", "{\"name\":\"basis-pengetahuan\"}");
String[] dokumen = {
"Kiosapi adalah AI API gateway Indonesia.",
"Kiosapi mendukung 100+ model AI.",
};
for (int i = 0; i < dokumen.length; i++) {
String emb = Kiosapi.post("/embeddings",
"{\"model\":\"openai/text-embedding-3-small\",\"input\":\"" + dokumen[i] + "\"}");
String vectorJson = extractEmbedding(emb); // parse data[0].embedding
Kiosapi.post("/vector-indexes/basis-pengetahuan/vectors/upsert",
"{\"vectors\":[{\"id\":\"doc-" + i + "\",\"values\":" + vectorJson +
",\"metadata\":{\"text\":\"" + dokumen[i] + "\"}}]}");
}
// 2) Query + jawab pakai konteks yang relevan
String pertanyaan = "Apa itu Kiosapi?";
String embQ = Kiosapi.post("/embeddings",
"{\"model\":\"openai/text-embedding-3-small\",\"input\":\"" + pertanyaan + "\"}");
String vectorQJson = extractEmbedding(embQ);
String hasil = Kiosapi.post("/vector-indexes/basis-pengetahuan/query",
"{\"vector\":" + vectorQJson + ",\"top_k\":2,\"include_metadata\":true}");
String konteks = extractContextFromMatches(hasil); // gabungkan metadata.text tiap match
String jawaban = Kiosapi.post("/chat/completions", """
{"model":"anthropic/claude-sonnet-4-6",
"messages":[
{"role":"system","content":"Jawab berdasar konteks ini:\n%s"},
{"role":"user","content":"%s"}
]}
""".formatted(konteks, pertanyaan));
System.out.println(jawaban);Referensi lain: spesifikasi OpenAPI 3.1 lengkap, harga & daftar model di /pricing, dan dokumentasi utama di /docs.