Panduan Python — SDK OpenAI
Kiosapi 100% kompatibel dengan SDK resmi openai Python untuk chat, streaming, tool-calling, vision, dan embeddings — cukup ganti base_url & api_key. Endpoint khusus Kiosapi (gambar, video, musik, TTS, reranking, vector DB) punya bentuk sendiri, dipanggil lewat requests biasa — contoh lengkap di bagian 10.
Daftar isi
1. Persiapan
Dapatkan API key
Masuk ke dashboard → Kunci API, beri nama (mis. "python-app"), klik Buat key, salin kios_live_… (ditampilkan sekali).
Install SDK
pip install openaiexport KIOSAPI_API_KEY="kios_live_xxxxxxxxxxxx"2. Inisialisasi client
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.kiosapi.id/v1",
api_key=os.environ["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
resp = 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."},
],
)
print(resp.choices[0].message.content)
print("Token dipakai:", resp.usage.total_tokens)4. Streaming
Tambahkan stream=True — respons muncul token demi token (SSE).
stream = client.chat.completions.create(
model="deepseek/deepseek-v4-flash",
messages=[{"role": "user", "content": "Tulis puisi pendek tentang hujan di Jakarta."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)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).
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"],
},
},
}
]
messages = [{"role": "user", "content": "Cuaca di Bandung sekarang gimana?"}]
resp = client.chat.completions.create(model="openai/gpt-4o", messages=messages, tools=tools)
msg = resp.choices[0].message
if msg.tool_calls:
for call in msg.tool_calls:
print("Model minta panggil:", call.function.name, call.function.arguments)
messages.append(msg)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": '{"suhu_celsius": 27, "kondisi": "berawan"}',
})
followup = client.chat.completions.create(model="openai/gpt-4o", messages=messages)
print(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 base64
with open("foto.jpg", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = 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": f"data:image/jpeg;base64,{b64}"}},
],
}
],
)
print(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.
resp = 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"},
)
import json
data = json.loads(resp.choices[0].message.content)
print(data)8. Embeddings
resp = client.embeddings.create(
model="openai/text-embedding-3-small",
input="Selamat datang di Kiosapi!",
)
vector = resp.data[0].embedding
print(len(vector), "dimensi")9. Daftar model & cek saldo
import requests
headers = {"Authorization": f"Bearer {os.environ['KIOSAPI_API_KEY']}"}
models = requests.get("https://api.kiosapi.id/v1/models", headers=headers).json()
# Saldo & kuota gratis harian (endpoint khusus Kiosapi)
saldo = requests.get("https://api.kiosapi.id/v1/saldo", headers=headers).json()
print(saldo)10. Endpoint khusus Kiosapi (via requests)
Bentuknya beda dari method SDK OpenAI standar (mis. images.generate), jadi dipanggil langsung lewat HTTP.
Gambar — POST /v1/images/generations (sinkron)
import base64, requests
res = requests.post(
"https://api.kiosapi.id/v1/images/generations",
headers={**headers, "Content-Type": "application/json"},
json={
"model": "google/imagen-3",
"prompt": "kucing oranye memakai topi koki, fotorealistik",
"option": "standard",
"n": 1,
},
)
data = res.json()
img_b64 = data["data"][0]["b64_json"]
with open("hasil.png", "wb") as f:
f.write(base64.b64decode(img_b64))
print("Biaya:", data["kiosapi"]["cost_rupiah"], "rupiah")Video — POST /v1/videos/generations (asinkron, perlu polling)
import time, requests
submit = requests.post(
"https://api.kiosapi.id/v1/videos/generations",
headers={**headers, "Content-Type": "application/json"},
json={
"model": "alibaba/wan2.7-t2v",
"prompt": "ombak pantai saat matahari terbenam, sinematik",
"option": "standard",
"duration_seconds": 5,
},
).json()
job_id = submit["job_id"]
while True:
job = requests.get(f"https://api.kiosapi.id/v1/jobs/{job_id}", headers=headers).json()
if job["status"] == "succeeded":
print("Video siap:", job["video_url"])
break
if job["status"] == "failed":
print("Gagal:", job["error"])
break
time.sleep(5)Image-to-video: sertakan "image": "<base64>" + "image_mime": "image/png" 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).
resp = requests.post(
"https://api.kiosapi.id/v1/music/generations",
headers={**headers, "Content-Type": "application/json"},
json={
"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()
job_id = resp["job_id"] # poll GET /v1/jobs/{job_id} sampai status "succeeded" → "audio_url"Text-to-speech — POST /v1/audio/speech
Kompatibel OpenAI (input + voice), respons berupa bytes audio mentah.
res = requests.post(
"https://api.kiosapi.id/v1/audio/speech",
headers={**headers, "Content-Type": "application/json"},
json={
"model": "minimax/speech-2.8-turbo",
"input": "Selamat datang di Kiosapi!",
"voice": "Indonesian_CalmWoman", # 9 suara asli Indonesia (model MiniMax)
},
)
with open("suara.mp3", "wb") as f:
f.write(res.content)Reranking — POST /v1/rerank (bentuk Cohere, self-hosted)
res = requests.post(
"https://api.kiosapi.id/v1/rerank",
headers={**headers, "Content-Type": "application/json"},
json={
"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 r in res["results"]:
print(r["index"], r["relevance_score"])Vector DB — POST /v1/vector-indexes/... (bentuk Pinecone, self-hosted)
# 1) Bikin index (gratis)
requests.post(
"https://api.kiosapi.id/v1/vector-indexes",
headers={**headers, "Content-Type": "application/json"},
json={"name": "artikel-saya"},
)
# 2) Buat embedding lalu upsert (values wajib 1536 angka, cocok text-embedding-3-small)
emb = client.embeddings.create(model="openai/text-embedding-3-small", input="Isi artikel di sini")
vector = emb.data[0].embedding
requests.post(
"https://api.kiosapi.id/v1/vector-indexes/artikel-saya/vectors/upsert",
headers={**headers, "Content-Type": "application/json"},
json={"vectors": [{"id": "artikel-1", "values": vector, "metadata": {"kategori": "berita"}}]},
)
# 3) Cari yang paling relevan
hasil = requests.post(
"https://api.kiosapi.id/v1/vector-indexes/artikel-saya/query",
headers={**headers, "Content-Type": "application/json"},
json={"vector": vector, "top_k": 5, "include_metadata": True},
).json()
print(hasil["matches"])11. Penanganan error
from openai import APIError, APIStatusError
try:
resp = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "Halo!"}],
)
except APIStatusError as e:
print("HTTP status:", e.status_code)
print("Detail:", e.response.text)
except APIError as e:
print("Error API:", e)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 os, requests
from openai import OpenAI
client = OpenAI(base_url="https://api.kiosapi.id/v1", api_key=os.environ["KIOSAPI_API_KEY"])
headers = {"Authorization": f"Bearer {os.environ['KIOSAPI_API_KEY']}", "Content-Type": "application/json"}
BASE = "https://api.kiosapi.id/v1"
def embed(text: str) -> list[float]:
return client.embeddings.create(model="openai/text-embedding-3-small", input=text).data[0].embedding
# Index dokumen (sekali saja)
requests.post(f"{BASE}/vector-indexes", headers=headers, json={"name": "basis-pengetahuan"})
dokumen = ["Kiosapi adalah AI API gateway Indonesia.", "Kiosapi mendukung 100+ model AI."]
vectors = [{"id": f"doc-{i}", "values": embed(d), "metadata": {"text": d}} for i, d in enumerate(dokumen)]
requests.post(f"{BASE}/vector-indexes/basis-pengetahuan/vectors/upsert", headers=headers, json={"vectors": vectors})
# Query + jawab pakai konteks yang relevan
pertanyaan = "Apa itu Kiosapi?"
hasil = requests.post(
f"{BASE}/vector-indexes/basis-pengetahuan/query",
headers=headers,
json={"vector": embed(pertanyaan), "top_k": 2, "include_metadata": True},
).json()
konteks = "\n".join(m["metadata"]["text"] for m in hasil["matches"])
jawaban = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[
{"role": "system", "content": f"Jawab berdasar konteks ini:\n{konteks}"},
{"role": "user", "content": pertanyaan},
],
)
print(jawaban.choices[0].message.content)Referensi lain: spesifikasi OpenAPI 3.1 lengkap, harga & daftar model di /pricing, dan dokumentasi utama di /docs.