KKiosapi.id

← Dokumentasi

Panduan PHP

Kiosapi kompatibel OpenAI lewat REST biasa — di PHP dipakai cURL native (tanpa SDK/dependensi) untuk chat, streaming, tool-calling, vision, dan embeddings, plus endpoint khusus Kiosapi (gambar, video, musik, TTS, reranking, vector DB).

Daftar isi

1. Persiapan

Masuk ke dashboard → Kunci API, beri nama, klik Buat key, salin kios_live_… (ditampilkan sekali). Butuh ekstensi curl PHP (aktif secara default di kebanyakan instalasi).

Keamanan: panggil API dari server, bukan dari kode yang dikirim ke browser. Simpan key di environment variable (getenv()), jangan hardcode.
export KIOSAPI_API_KEY="kios_live_xxxxxxxxxxxx"

2. Fungsi helper request

Satu fungsi kecil dipakai ulang untuk semua panggilan JSON ke Kiosapi.

<?php

define('KIOSAPI_BASE', 'https://api.kiosapi.id/v1');
define('KIOSAPI_KEY', getenv('KIOSAPI_API_KEY'));

function kiosapi_post(string $path, array $body): array {
    $ch = curl_init(KIOSAPI_BASE . $path);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . KIOSAPI_KEY,
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

function kiosapi_get(string $path): array {
    $ch = curl_init(KIOSAPI_BASE . $path);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . KIOSAPI_KEY],
    ]);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

Model ID berformat provider/nama-model — lihat daftar lengkap via GET /v1/models atau /pricing.

3. Chat completion dasar

$resp = kiosapi_post('/chat/completions', [
    '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.'],
    ],
]);
echo $resp['choices'][0]['message']['content'];
echo "\nToken dipakai: " . $resp['usage']['total_tokens'];

4. Streaming

Tambahkan "stream": true dan proses baris SSE lewat CURLOPT_WRITEFUNCTION.

$ch = curl_init(KIOSAPI_BASE . '/chat/completions');
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . KIOSAPI_KEY,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'model' => 'deepseek/deepseek-v4-flash',
        'messages' => [['role' => 'user', 'content' => 'Tulis puisi pendek tentang hujan di Jakarta.']],
        'stream' => true,
    ]),
    CURLOPT_WRITEFUNCTION => function ($ch, $chunk) {
        foreach (explode("\n", $chunk) as $line) {
            if (!str_starts_with($line, 'data: ')) continue;
            $data = substr($line, 6);
            if ($data === '[DONE]') continue;
            $json = json_decode($data, true);
            $delta = $json['choices'][0]['delta']['content'] ?? '';
            echo $delta;
        }
        return strlen($chunk);
    },
]);
curl_exec($ch);
curl_close($ch);

Model reasoning (🧠) bisa mengirim delta reasoning_content terpisah dari content — cek key 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).

$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 = kiosapi_post('/chat/completions', [
    'model' => 'openai/gpt-4o', 'messages' => $messages, 'tools' => $tools,
]);

$msg = $resp['choices'][0]['message'];
if (!empty($msg['tool_calls'])) {
    foreach ($msg['tool_calls'] as $call) {
        echo "Model minta panggil: {$call['function']['name']} {$call['function']['arguments']}\n";
        $messages[] = $msg;
        $messages[] = [
            'role' => 'tool',
            'tool_call_id' => $call['id'],
            'content' => json_encode(['suhu_celsius' => 27, 'kondisi' => 'berawan']),
        ];
    }
    $followup = kiosapi_post('/chat/completions', ['model' => 'openai/gpt-4o', 'messages' => $messages]);
    echo $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.

$b64 = base64_encode(file_get_contents('foto.jpg'));

$resp = kiosapi_post('/chat/completions', [
    '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}"]],
        ],
    ]],
]);
echo $resp['choices'][0]['message']['content'];

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.

$resp = kiosapi_post('/chat/completions', [
    'model' => 'openai/gpt-4o',
    'messages' => [['role' => 'user', 'content' => 'Beri saya data profil singkat dalam JSON: nama, umur.']],
    'response_format' => ['type' => 'json_object'],
]);
$data = json_decode($resp['choices'][0]['message']['content'], true);
print_r($data);

8. Embeddings

$resp = kiosapi_post('/embeddings', [
    'model' => 'openai/text-embedding-3-small',
    'input' => 'Selamat datang di Kiosapi!',
]);
$vector = $resp['data'][0]['embedding'];
echo count($vector) . ' dimensi';

9. Daftar model & cek saldo

$models = kiosapi_get('/models');

// Saldo & kuota gratis harian (endpoint khusus Kiosapi)
$saldo = kiosapi_get('/saldo');
print_r($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)

$data = kiosapi_post('/images/generations', [
    'model' => 'google/imagen-3',
    'prompt' => 'kucing oranye memakai topi koki, fotorealistik',
    'option' => 'standard',
    'n' => 1,
]);
file_put_contents('hasil.png', base64_decode($data['data'][0]['b64_json']));
echo 'Biaya: ' . $data['kiosapi']['cost_rupiah'] . ' rupiah';

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

$submit = kiosapi_post('/videos/generations', [
    'model' => 'alibaba/wan2.7-t2v',
    'prompt' => 'ombak pantai saat matahari terbenam, sinematik',
    'option' => 'standard',
    'duration_seconds' => 5,
]);

do {
    sleep(5);
    $job = kiosapi_get('/jobs/' . $submit['job_id']);
} while ($job['status'] === 'running');

if ($job['status'] === 'succeeded') echo 'Video siap: ' . $job['video_url'];
else echo 'Gagal: ' . $job['error'];

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

Musik — POST /v1/music/generations

$resp = kiosapi_post('/music/generations', [
    'model' => 'minimax/music-2.6',
    'prompt' => 'pop akustik Indonesia yang hangat, vokal wanita',
    'lyrics' => "[Verse]\nPagi cerah di kota\n[Chorus]\nBersama kita bisa",
]);
// poll GET /jobs/{$resp['job_id']} sampai status "succeeded" → field "audio_url"

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

$ch = curl_init(KIOSAPI_BASE . '/audio/speech');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . KIOSAPI_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'model' => 'minimax/speech-2.8-turbo',
        'input' => 'Selamat datang di Kiosapi!',
        'voice' => 'Indonesian_CalmWoman', // 9 suara asli Indonesia (model MiniMax)
    ]),
]);
$audio = curl_exec($ch);
curl_close($ch);
file_put_contents('suara.mp3', $audio);

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

$res = kiosapi_post('/rerank', [
    '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,
]);
foreach ($res['results'] as $r) echo "{$r['index']}: {$r['relevance_score']}\n";

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)
$emb = kiosapi_post('/embeddings', ['model' => 'openai/text-embedding-3-small', 'input' => 'Isi artikel di sini']);
$vector = $emb['data'][0]['embedding'];

kiosapi_post('/vector-indexes/artikel-saya/vectors/upsert', [
    'vectors' => [['id' => 'artikel-1', 'values' => $vector, 'metadata' => ['kategori' => 'berita']]],
]);

// 3) Cari yang paling relevan
$hasil = kiosapi_post('/vector-indexes/artikel-saya/query', [
    'vector' => $vector, 'top_k' => 5, 'include_metadata' => true,
]);
print_r($hasil['matches']);

11. Penanganan error

function kiosapi_post_checked(string $path, array $body): array {
    $ch = curl_init(KIOSAPI_BASE . $path);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . KIOSAPI_KEY, 'Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    $res = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    $json = json_decode($res, true);
    if ($status >= 400) {
        throw new RuntimeException("Kiosapi error {$status}: " . ($json['error']['message'] ?? $res));
    }
    return $json;
}

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.

function embed(string $text): array {
    return kiosapi_post('/embeddings', ['model' => 'openai/text-embedding-3-small', 'input' => $text])['data'][0]['embedding'];
}

// Index dokumen (sekali saja)
kiosapi_post('/vector-indexes', ['name' => 'basis-pengetahuan']);
$dokumen = ['Kiosapi adalah AI API gateway Indonesia.', 'Kiosapi mendukung 100+ model AI.'];
$vectors = [];
foreach ($dokumen as $i => $d) {
    $vectors[] = ['id' => "doc-{$i}", 'values' => embed($d), 'metadata' => ['text' => $d]];
}
kiosapi_post('/vector-indexes/basis-pengetahuan/vectors/upsert', ['vectors' => $vectors]);

// Query + jawab pakai konteks yang relevan
$pertanyaan = 'Apa itu Kiosapi?';
$hasil = kiosapi_post('/vector-indexes/basis-pengetahuan/query', [
    'vector' => embed($pertanyaan), 'top_k' => 2, 'include_metadata' => true,
]);
$konteks = implode("\n", array_map(fn($m) => $m['metadata']['text'], $hasil['matches']));

$jawaban = kiosapi_post('/chat/completions', [
    'model' => 'anthropic/claude-sonnet-4-6',
    'messages' => [
        ['role' => 'system', 'content' => "Jawab berdasar konteks ini:\n{$konteks}"],
        ['role' => 'user', 'content' => $pertanyaan],
    ],
]);
echo $jawaban['choices'][0]['message']['content'];

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