DokumentasiReferensi API

Respons dan kegagalan media

Bentuk respons media, tiga penolakan sebelum saldo ditahan, dan cara memilih model.

Bentuk respons

Semua rute media menjawab dalam satu body utuh, bukan tautan ke tempat lain dan bukan aliran.

Respons media dikirim inline: isinya ada di body respons itu sendiri. Tidak ada URL yang harus diunduh menyusul, tidak ada id job yang harus dipolling, dan tidak ada masa berlaku tautan yang perlu kamu jaga. Satu request selesai, satu body berisi hasilnya.

Bentuk isinya mengikuti rutenya: gambar dan audio menghasilkan byte artefak, sementara embeddings dan decisions menghasilkan JSON. Yang sama di semua rute adalah cara membacanya — sekali baca sampai selesai, tanpa menunggu bagian berikutnya.

HeaderNilaiSelalu adaArtinya
content-typedari modelyaTipe isi yang dinyatakan model, diteruskan apa adanya. Kalau model tidak menyebutkannya, body datang sebagai application/octet-stream.
cache-controlno-storeyaHasilnya tidak boleh disimpan perantara.
x-content-type-optionsnosniffyaPeramban tidak boleh menebak tipe isinya.

Karena semuanya inline, ukuran respons mengikuti ukuran artefaknya. Gambar besar dalam jumlah banyak bisa menjadi body yang besar, dan itu biaya jaringan di sisimu, bukan sesuatu yang bisa dihindari dengan membaca sebagian.

Tiga penolakan sebelum saldo ditahan

Ketiganya berarti request tidak pernah sampai ke model, dan ketiganya terjadi sebelum ada dana yang ditahan.

KodeStatusPenyebabYang perlu dilakukan
capability_mismatch422Model menyatakan kapabilitas yang dibutuhkan rute itu bernilai false. Modelnya ada, tapi tidak untuk modalitas ini.Pakai model lain. Mengulang request yang sama akan ditolak lagi.
capabilities_not_declared422Model belum menyatakan apa pun: capabilities bernilai null, atau objeknya tidak memuat flag yang dibutuhkan rute itu.Isi capabilities.<nama> = true pada model itu, lalu ulangi. Kalau kamu bukan pemilik modelnya, pakai model lain.
surface_not_served501Kapabilitasnya lolos, tapi model itu tidak punya jalur media di deployment ini. Ia tetap bisa dipakai di rute lain, hanya bukan di rute media.Pakai model yang punya jalur media. Ini bukan gangguan, jadi menunggu tidak mengubah apa pun.
422 application/json
{
  "error": {
    "message": "Model '…' tidak dideklarasikan untuk permintaan jenis ini (butuh kapabilitas 'audio'). Pakai model lain, atau deklarasikan kapabilitas itu pada modelnya.",
    "type": "invalid_request_error",
    "code": "capability_mismatch"
  }
}

Urutannya menguntungkanmu: kapabilitas diperiksa lebih dulu, lalu apakah modelnya punya jalur media, baru setelah itu saldo ditahan. Jadi request yang salah pilih model tidak pernah memotong saldo dan tidak menyisakan dana tertahan yang harus dilepas.

Memilih model tanpa menebak

Baca kapabilitasnya lebih dulu. Kedua katalog memuatnya, dan keduanya bisa dibaca sebelum kamu mengirim request apa pun.

GET/v1/modelsbutuh API key
GET/public/catalogpublik
200 application/json
{
  "id": "…",
  "object": "model",
  "created": 1790000000,
  "owned_by": "…",
  "display_name": "…",
  "context_window": null,
  "max_output_tokens": null,
  "capabilities": { "audio": true },
  "price": {
    "unit": "thousand_chars",
    "unit_price": "…",
    "quoted_at_submit": false,
    "unit_price_display": "Rp… / 1.000 karakter"
  },
  "is_free": false
}

Setiap entri /v1/models membawa lebih dari empat field standar: display_name, context_window, max_output_tokens, capabilities, price, dan penanda model gratis. Field tambahan itu ada supaya kamu tidak perlu menebak dari nama model.

capabilities di /v1/models adalah apa yang dideklarasikan model itu, jadi bentuknya bisa null dan bisa tidak memuat sebuah flag. Itu bukan jawaban “tidak”, melainkan “belum dinyatakan” — dan gate memperlakukannya sebagai belum dinyatakan, bukan sebagai izin.

Katalog publik memakai bentuk yang lebih rata: flag modalitasnya selalu ada, dan yang tidak dideklarasikan muncul sebagai false. Satu perbedaan yang perlu kamu tahu: di sana chat tidak muncul sebagai field tersendiri, melainkan sebagai streaming dan functionCalling, yang keduanya diturunkan dari chat. Rute ini tidak butuh key, jadi ia berguna untuk memeriksa ketersediaan sebelum kamu memegang kredensial.

cek kapabilitas dari katalog publik
curl -s https://api.menvora.web.id/public/catalog \
  | jq '.data[] | select(.capabilities.audio) | .id'

Ganti .audio dengan .image atau .embeddings sesuai rute yang akan kamu panggil. Untuk decisions, yang dicari adalah .streaming di katalog publik, atau .chat di /v1/models.