Dokumentasi

Dokumentasi

Kesalahan

Kunavo mengembalikan isi kesalahan berformat OpenAI dengan kode status HTTP yang menunjukkan apakah Anda perlu mencoba ulang. Gunakan penanganan kesalahan standar OpenAI SDK agar tidak mengalami masalah.

Setiap respons non-2xx memiliki bentuk JSON yang sama — standar OpenAI. Cocokkan error.code untuk penanganan terprogram dan status_code untuk kebijakan percobaan ulang.

Isi kesalahan

{
  "error": {
    "message": "Model 'xyz-2025' is not available",
    "type": "model_not_found",
    "code": "model_not_found",
    "param": null
  }
}
KolomTipeCatatan
messagestringDapat dibaca manusia. Aman untuk dicatat dalam log; tidak pernah menyertakan rahasia.
typestringKategori umum (authentication_error, invalid_request_error, …).
codestringPengidentifikasi terperinci. Gunakan untuk percabangan terprogram.
paramstring|nullJika error terkait dengan field tertentu, sebutkan nama field tersebut.

Kode status HTTP

HTTPMaknaRetry?
400invalid_request_error — payload Anda tidak valid.Tidak — perbaiki permintaan.
401authentication_error — API key buruk / tidak ada / dicabut.Tidak — rotasi key.
402insufficient_quota — saldo dompet kosong (code: insufficient_balance) atau batas bulanan tercapai.Tidak — isi saldo di /app/billing. Pengecualian: header Retry-After berarti pengisian saldo otomatis sedang berlangsung; coba lagi setelahnya.
403permission_error — key valid, tetapi daftar izin IP-nya tidak mencakup alamat Anda.Tidak — lakukan panggilan dari alamat yang diizinkan.
404model_not_found — ID model tidak dikenal atau dinonaktifkan.Tidak — periksa /v1/models.
404missing_v1_prefix — path endpoint di api.kunavo.com tanpa /v1, atau POST ke host dasar.Tidak — atur URL dasar ke https://api.kunavo.com/v1.
404unknown_url — tidak ada endpoint di path tersebut di bawah /v1; pesan menyebutkan endpoint terdekat.Tidak — perbaiki path.
408Waktu tunggu permintaan klien habis.Ya, dengan memperhatikan idempotensi.
422upstream_422 — penyedia upstream menolak input Anda (misalnya, ukuran tidak didukung).Tidak — sesuaikan input.
429Dibatasi oleh laju — terlalu banyak panggilan serentak.Ya — jeda eksponensial.
500Error internal Kunavo.Ya — jeda singkat.
502upstream_error — penyedia upstream gagal.Ya — jeda eksponensial.
504Waktu tugas habis (pembuatan gambar / video melampaui batas polling kami).Ya, tetapi perkirakan akan ada biaya.
Permintaan yang dijawab Kunavo dengan status 4xx atau 5xx tidak ditagih. Satu-satunya pengecualian adalah status 5xx pada pengiriman asinkron (POST /v1/videos, POST /v1/audio/music/jobs, atau permintaan gambar dengan async atau webhook_url: "https://…"): tugas mungkin telah dibuat sebelum terjadi kesalahan, dan tugas yang sudah ada akan berjalan serta ditagih setelah selesai.

Anggap respons 5xx pada pengiriman seperti itu sebagai hasil yang belum diketahui, bukan kegagalan. Kirim header Idempotency-Key pada setiap pengiriman seperti itu: setelah respons 5xx, permintaan yang sama dengan kunci yang sama akan mengembalikan tugas jika sudah ada dan memulainya jika belum ada.

Panggilan yang jawabannya tidak pernah sampai kepada Anda juga bukan panggilan yang gagal. Permintaan sinkron yang berjalan melampaui batas waktu klien Anda tetap berjalan hingga selesai dan ditagih. Stream yang Anda tutup lebih awal juga tetap berjalan hingga selesai dan ditagih untuk seluruh respons, bukan hanya untuk bagian yang sudah Anda baca.

Kode error umum

authentication_error

  • Lupa mengatur header Authorization: Bearer ....
  • API key dicabut dari /app/keys.
  • Key masih memiliki prefiks yang salah (harus diawali dengan sk-kn-).

insufficient_quota

  • Saldo dompet terlalu rendah untuk permintaan ini → error.code adalah insufficient_balance, dan error tersebut menyertakan jumlah saldo dompet (balance_usd), jumlah yang perlu ditahan untuk permintaan ini (needed_usd), serta dua tautan: topup_url membuka halaman penagihan dengan pengisian saldo yang sudah terpilih, sedangkan auto_recharge_url membukanya di pengaturan pengisian saldo otomatis. Kedua tautan tidak dengan sendirinya membebankan biaya apa pun.
  • Batas bulanan per key tercapai. Batas direset pada awal bulan kalender (UTC). Naikkan batas di /app/keys.
{
  "error": {
    "message": "Wallet balance is too low for this request. Top up at https://kunavo.com/app/billing. Once a top-up has been paid, you can also turn on auto-recharge there: a saved card then refills the wallet when its balance falls under a threshold you choose.",
    "type": "insufficient_quota",
    "code": "insufficient_balance",
    "param": null,
    "balance_usd": 0.0142,
    "needed_usd": 0.0381,
    "topup_url": "https://kunavo.com/app/billing?topup=20",
    "auto_recharge_url": "https://kunavo.com/app/billing?autorecharge=1&src=api_402"
  }
}

Respons 402 karena saldo dompet berarti jumlah yang perlu ditahan untuk permintaan melebihi balance_usd dikurangi jumlah yang ditahan oleh permintaan dan tugas yang sedang berjalan. Jika pengisian saldo otomatis aktif, Kunavo terlebih dahulu mengisi saldo dompet melalui metode pembayaran yang tersimpan, tetapi hanya apabila balance_usd berada di bawah ambang pengisian otomatis yang Anda tetapkan dan batasan pengisian mengizinkannya, lalu mencoba permintaan itu sekali lagi. Jika pengisian tidak dilakukan atau tidak mencukupi, permintaan ditolak, sehingga respons 402 tetap bisa muncul meskipun pengisian saldo otomatis aktif.

Hentikan percobaan ulang pada insufficient_balance kecuali respons memiliki header Retry-After — header tersebut berarti pengisian saldo otomatis sedang menagih kartu tersimpan Anda, dan permintaan yang sama seharusnya berhasil beberapa detik kemudian.

GET /v1/balance mengembalikan saldo dompet, jumlah yang ditahan untuk tugas yang masih berjalan, dan sisa setiap batas bulanan. Anda dapat memanggilnya kapan saja: tidak diperlukan permintaan yang ditolak untuk melihat angka-angka ini. Respons 402 untuk batas bulanan tidak menyertakan balance_usd maupun needed_usd: pesannya menyebutkan batas mana yang telah tercapai, dan endpoint tersebut menunjukkan sisa setiap batas. Lihat Saldo.

permission_error

  • Key memiliki daftar izin IP dan panggilan Anda berasal dari alamat di luar daftar tersebut. Pesan menyebutkan alamat yang terdeteksi — tambahkan alamat itu (atau blok CIDR-nya) di /app/keys, atau hapus seluruh daftar izin agar semua alamat diizinkan.
  • Memindahkan agen ke host baru, gateway NAT baru, atau laptop di jaringan lain akan mengubah alamat tersebut. Key tanpa daftar izin tidak akan pernah ditolak karena alasan ini.

model_not_found

  • Slug salah eja. Gunakan /models untuk daftar kanonis.
  • Model saat ini dinonaktifkan (gangguan upstream atau peninjauan harga).

upstream_error

Menunjukkan bahwa penyedia model upstream mengembalikan error yang tidak dapat kami terjemahkan menjadi kode yang lebih spesifik. Isi respons mencakup pesan asli. Penyebab umum:

  • Beban berlebih di sisi penyedia.
  • Penolakan moderasi konten (coba prompt lain).
  • Pembatasan wilayah / ketersediaan.

Strategi percobaan ulang

Pola tangguh yang paling sederhana: jeda eksponensial dengan jitter hanya untuk 429 / 5xx.

import os
import random
import time

from openai import OpenAI, RateLimitError, APIError

client = OpenAI(api_key=os.environ["KUNAVO_API_KEY"], base_url="https://api.kunavo.com/v1")

def call_with_retry(call, max_attempts=5):
    for attempt in range(max_attempts):
        try:
            return call()
        except RateLimitError:
            if attempt + 1 == max_attempts: raise
            # 429: exponential backoff with jitter
            time.sleep(min(2 ** attempt, 30) + random.random())
        except APIError as e:
            if e.status_code and 500 <= e.status_code < 600 and attempt + 1 < max_attempts:
                time.sleep(min(2 ** attempt, 30) + random.random())
            else:
                raise

result = call_with_retry(lambda: client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "hi"}],
))
  • Batasi waktu tunggu hingga 30 detik per percobaan dan total hingga 5 percobaan.
  • Jangan coba ulang 4xx (kecuali 408 dan 429). Melakukannya hanya membuang waktu.
  • Pembuatan gambar, video, dan musik tidak idempoten: percobaan ulang memulai pembuatan baru dan ditagih jika berhasil. Untuk video, musik, dan gambar, header Idempotency-Key diterima pada pengiriman asinkron (POST /v1/videos, POST /v1/audio/music/jobs, dan kedua endpoint gambar dengan "async": true atau webhook_url): pengiriman ulang dengan kunci yang sama mengembalikan tugas pertama.
  • Untuk chat yang memiliki efek samping dalam kode Anda sendiri, lakukan deduplikasi melalui kunci idempotensi di lapisan aplikasi Anda.

Men-debug dari dasbor

Setiap panggilan API — berhasil maupun gagal — terlihat di /app/usage. Klik baris mana pun untuk membuka halaman detail permintaan/respons lengkap:

  • Kode status HTTP yang dikembalikan kepada klien.
  • Kode error upstream (jika berlaku).
  • Latensi, IP permintaan, agen pengguna.
  • Memfilter berdasarkan status membantu menemukan pola (misalnya, semua respons 422 pada model tertentu).

Melaporkan insiden

Jika Anda melihat error 5xx yang terus terjadi pada model yang seharusnya berfungsi, kirim email ke support@kunavo.com dengan informasi berikut:

  • Slug model dan contoh isi permintaan (samarkan rahasia).
  • Rentang waktu terjadinya kegagalan.
  • Error code + message dari respons.
  • Jika memungkinkan, tautan log penggunaan dari /app/usage/[id].

Waktu respons satu hari kerja; lebih cepat untuk masalah mendesak yang berdampak pada pendapatan.

Langkah selanjutnya