BazaarLinkBazaarLink
Masuk
DokumentasiReferensi APIReferensi SDKPenggunaan AgentikSkill AI

Dokumentasi BazaarLink

BazaarLink adalah gateway API AI terpadu untuk Taiwan — menyediakan akses ke ratusan model dari OpenAI, Anthropic, Google, Meta, dan lainnya melalui satu endpoint API yang kompatibel dengan OpenAI.

File Skill Agen AI
Muat file skill kami ke asisten AI Anda (Claude, Cursor, Copilot…) untuk memberikan pengetahuan lengkap tentang API BazaarLink:
Read https://bazaarlink.ai/skill.md and follow the instructions to integrate BazaarLink into your app.
Model gratis & batas laju
Mencari informasi tentang model gratis, batas permintaan per menit, dan kredit gratis? Lihat Batas laju · FAQ

Harga

BazaarLink menetapkan harga penggunaan model dengan markup nol (sama dengan daftar harga resmi masing-masing penyedia). Biaya platform dibebankan saat isi ulang (deposit): biaya transaksi 10%, ditambah 5% Taiwan VAT di saluran TWD. Ditagih dalam USD dengan kutipan TWD dan faktur terpadu elektronik. Top-up bayar sesuai pemakaian layanan mandiri; perusahaan dapat mengatur penagihan bulanan (Net-30, dapat dinegosiasikan).

Cara kerja

  • Konsumsi (debit): setiap panggilan API ditagih berdasarkan penggunaan token aktual sesuai harga daftar USD resmi penyedia, dipotong dari saldo Anda — tanpa markup, tanpa biaya tambahan untuk konsumsi.
  • Top-up (deposit): TWD dikonversi menjadi USD dengan kurs jual real-time dan ditambahkan ke saldo Anda; biaya transaksi 10% dibebankan saat isi ulang.
  • • Metode pembayaran dan biaya khusus kanal ditampilkan pada checkout langsung.
  • • Kanal TWD yang memenuhi syarat menampilkan pajak dan ketentuan faktur elektronik Taiwan sebelum pembayaran.
  • • Transfer bank: untuk isi ulang skala besar atau perusahaan, hubungi kami untuk mengatur transfer kawat dan pembuatan faktur khusus.
  • Faktur hanya tersedia melalui kanal yang sedang ditawarkan dan ditandai memenuhi syarat, atau melalui ketentuan perusahaan yang telah dikonfirmasi. Hubungi tim penjualan sebelum membayar bila memerlukan nomor pajak, penawaran, atau tagihan bulanan.
Contoh
Saat membeli kredit US$10.00, checkout langsung menampilkan metode yang tersedia, jumlah akhir, biaya atau pajak, serta kelayakan tanda terima atau faktur sebelum konfirmasi. Saldo kemudian digunakan pada harga resmi tanpa markup model.

Tentang nilai tukar

Konversi valuta asing menggunakan kurs real-time; penagihan bulanan menggunakan tarif pada waktu penagihan (laporan), sedangkan isi ulang prabayar dikonversi berdasarkan tarif waktu isi ulang. Tarif dan stempel waktu disimpan dalam catatan penagihan.

Perlindungan tagihan untuk permintaan gagal

Jika permintaan upstream gagal tanpa data penggunaan yang dapat ditagih, BazaarLink otomatis mengembalikan seluruh jumlah yang dicadangkan. Tagihan percobaan tersebut tetap USD 0 meskipun stream sudah dimulai sebelum gagal.

Kapan Anda tidak ditagih
Tidak perlu pengaturan. Aturan ini otomatis berlaku untuk API inferensi publik dan media. BazaarLink dapat menanggung biaya yang sudah ditagihkan penyedia upstream alih-alih membebankan biaya kegagalan itu kepada Anda.
  • Upstream tidak dapat terhubung, menolak permintaan, atau tidak memberikan hasil yang dapat digunakan
  • Stream berhenti sebelum catatan penggunaan akhir diterima, meskipun sebagian konten sudah dikirim
  • Respons tidak memiliki usage atau hanya memiliki objek usage kosong dengan semua nilai nol

0 token output tidak selalu berarti gratis

usage.cost adalah jumlah USD yang ditagihkan untuk permintaan ini. Respons dengan 0 output token tetap dapat dikenai biaya input token; cek usage.cost atau catatan Activity untuk jumlah akhir.

Mulai Cepat

Tiga Cara Integrasi

Pendekatan
Cocok untuk
Mulai
Xqzbtkn0000zxq mentahBahasa apa pun, tanpa dependensi, kontrol penuh atas permintaan→
OpenAI / Anthropic SDKSudah memakai SDK resmi — cukup ganti base URL dan kunci→
Framework agenLangChain, Vercel AI SDK, CrewAI, dan aplikasi agen lainnya→
Semua permintaan secara otomatis ditinjau sebelum dikirim ke model; permintaan yang melanggar kebijakan penggunaan kami akan ditolak dan mengembalikan error 403.

Mulai dalam waktu kurang dari 5 menit. BazaarLink sepenuhnya kompatibel dengan OpenAI SDK — cukup ubah

Untuk permintaan yang lebih panjang dari 100 detik, sebaiknya gunakan stream:true. Untuk permintaan non-streaming, setelah sekitar 12 detik (nilai default yang dapat disesuaikan melalui pengaturan deployment), respons terlebih dahulu mengembalikan 200 dan mulai mengirim whitespace keepalive; jika kemudian terjadi kesalahan, kesalahan tersebut dikembalikan sebagai 200 + error JSON. Keepalive berupa whitespace sebelum body JSON, yang diabaikan oleh parser JSON standar.

Base URL

https://api.bazaarlink.ai/v1

api.bazaarlink.ai adalah titik masuk khusus API yang di-deploy terpisah dari situs web. Base URL sebelumnya https://bazaarlink.ai/api/v1 tetap didukung penuh — integrasi yang ada tidak perlu diubah.

Menggunakan OpenAI SDK

BazaarLink sepenuhnya kompatibel dengan OpenAI SDK. Cukup ubah base URL dan kunci API — semua kode lainnya tetap sama.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/v1",
    api_key="sk-bl-YOUR_API_KEY",
)

completion = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[
        {"role": "user", "content": "What is the meaning of life?"}
    ],
)

print(completion.choices[0].message.content)
Butuh kunci API?
Dapatkan kunci API Anda dari halaman Kunci API. Semua kunci dimulai dengan sk-bl-.
Memanggil langsung dari browser (CORS)
API publik membalas setiap permintaan /v1 dengan Access-Control-Allow-Origin: *, jadi Anda bisa memanggilnya langsung dari JavaScript browser lewat fetch atau OpenAI SDK. Jangan pernah menaruh kunci API di kode front-end — siapa pun yang membuka halaman bisa membacanya; gunakan kunci yang bisa dicabut dan dibatasi kuotanya, atau teruskan panggilan lewat backend Anda sendiri.
Format ID Model — gunakan format provider/model-name
GET /v1/models mencantumkan id seperti "claude-sonnet-4.6" dan alias kanonis seperti "anthropic/claude-sonnet-4.6". Permintaan menerima keduanya; gunakan id atau alias yang tercantum.
✓ claude-sonnet-4.6   anthropic/claude-sonnet-4.6

Bawa Kunci Sendiri (BYOK)

Hubungkan kunci API upstream ke akun pribadi atau organisasi. Permintaan yang memenuhi syarat menggunakan kunci Anda lebih dulu. Setelah upstream error, permintaan dapat mencoba sumber lain yang tersedia; jika tidak ada, permintaan menghasilkan error. Kelola kunci pribadi di halaman kunci dan kunci organisasi di pengaturan organisasi. Buka pengaturan BYOK →

Penyaringan konten

Perlindungan konten dua arah untuk lalu lintas API Anda: permintaan yang terdeteksi membawa prompt injection diblokir (400), dan data sensitif pada permintaan maupun respons (kunci API, nomor kartu, nomor identitas, dll.) otomatis disamarkan. Aturan dan daftar pengecualian dapat disesuaikan, lengkap dengan statistik penggunaan. Buka pengaturan filter konten →

Data sosial (:social)

Tambahkan :social di belakang nama model jika pertanyaan Anda tentang platform sosial. Sebelum model menjawab, BazaarLink mengambil postingan, profil, atau komentar yang relevan dari platform tersebut dan menyediakannya sebagai bahan referensi. Jika data platform tidak dapat diambil tepat waktu, permintaan dialihkan ke pencarian web biasa sehingga Anda tetap mendapat jawaban.

Contoh

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 60 \
  -d '{
    "model": "gpt-5.4-mini:social",
    "messages": [{ "role": "user", "content": "Postingan terbaru di X tentang GPT-6" }]
  }'

Yang perlu diketahui

  • Waktu tunggu: data sosial diambil secara langsung, sehingga permintaan :social dapat memerlukan 20 hingga 40 detik sebelum jawaban mulai muncul. Setelah 40 detik, permintaan dialihkan ke pencarian web. Atur timeout klien minimal 60 detik. :online tetap cepat karena merupakan pencarian web biasa.
  • Harga: kueri yang dijawab dengan data sosial memakai kuota gratis harian untuk pencarian yang sama seperti :online (5 per hari tanpa saldo, 10 dengan saldo atau langganan, direset pada 00:00 UTC). Di luar kuota, setiap kueri ditagih sesuai tabel harga Data API (lihat GET /v1/data/catalog), di luar biaya token model itu sendiri. Kueri yang dialihkan ke pencarian web ditagih seperti :online.
  • Cakupan: :social hanya membaca sebagian platform sosial, dan daftarnya bergantung pada pengaturan yang aktif; daftar terkini ada di /solutions/data-api#social-suffix. Platform yang ada di katalog Data API tetapi tidak ada di daftar itu tidak dibaca oleh :social, sehingga kueri tentangnya, atau tanpa platform tertentu, dijawab dengan pencarian web.
  • Kompatibilitas: berfungsi pada POST /api/v1/chat/completions, /api/v1/messages, dan /api/v1/responses, baik streaming maupun non-streaming, dengan sitasi yang sama seperti :online. :online dan :social tidak dapat digabungkan dalam satu nama model (400 invalid_web_search_options).

Migrasi dari OpenRouter

API BazaarLink kompatibel dengan OpenRouter — sebagian besar integrasi cukup mengubah dua nilai: base URL menjadi https://api.bazaarlink.ai/v1 dan kunci API menjadi kunci BazaarLink yang dimulai dengan sk-bl-.

  1. Basis URL: https://openrouter.ai/api/v1 → https://api.bazaarlink.ai/v1
  2. Kunci API: sk-or-... → sk-bl-... (buat di /keys)
  3. ID model: format provider/model yang sama (mis. anthropic/claude-sonnet-4.6); katalog lengkap di GET /v1/models
  4. Fallback models[], streaming, tool calling, dan output terstruktur memakai bentuk permintaan yang sama
  from openai import OpenAI

  client = OpenAI(
-     base_url="https://openrouter.ai/api/v1",
-     api_key="sk-or-...",
+     base_url="https://api.bazaarlink.ai/v1",
+     api_key="sk-bl-...",
  )
Note
Penagihan dalam USD dan tersedia e-faktur Taiwan. Kontrol perutean khusus upstream seperti :nitro diabaikan. Lihat Referensi API untuk opsi perutean yang didukung BazaarLink.

Autentikasi

Semua permintaan API memerlukan header Authorization dengan kunci API Anda.

Authorization: Bearer sk-bl-YOUR_API_KEY

Dapatkan kunci API Anda dari dasbor. Jaga keamanan kunci Anda — jangan mengeksposnya di kode sisi klien.

Catatan Keamanan
Jangan pernah mengekspos kunci API di JavaScript sisi klien. Selalu proksi permintaan melalui server backend Anda.

Header Opsional

HTTP-Referer
string
URL situs Anda, untuk pelacakan penggunaan dan analitik (opsional)
X-Title
string
Nama aplikasi Anda, ditampilkan di dasbor (opsional)

Prinsip

BazaarLink dirancang berdasarkan tiga prinsip utama:

1. Antarmuka Terpadu

Satu API, satu SDK, ratusan model. Beralih antara OpenAI, Anthropic, Google Gemini, Meta Llama, dan lainnya tanpa mengubah kode Anda — cukup ubah ID model.

2. Optimasi Harga

BazaarLink secara otomatis mengarahkan ke penyedia paling hemat biaya untuk model yang Anda pilih. Anda hanya membayar apa yang Anda gunakan, ditagih dalam USD dengan dukungan faktur penuh.

3. Penanganan Permintaan

Jika sumber upstream bermasalah, permintaan dapat mencoba sumber lain yang tersedia. Jika tidak ada yang tersedia, permintaan menghasilkan error.

Multimoda

BazaarLink mendukung input multimodal — kirim gambar, audio, dan file bersamaan dengan teks ke model yang mendukungnya. Konten diteruskan ke penyedia upstream.

Modalitas yang Didukung

Masukan
Deskripsi
Contoh Model
TeksPesan teks standarSemua model
GambarURL atau data URI base64 — PNG, JPEG, WebP, GIFopenai/gpt-6-lunaanthropic/claude-sonnet-4.6google/gemini-4-argon+98 lainnya
File / PDFDokumen via data URI base64 (`data:application/pdf;base64,...`)openai/gpt-6-lunaanthropic/claude-sonnet-4.6google/gemini-4-argon+41 lainnya
AudioRaw base64 — tanpa dukungan URL. Memerlukan field `format`google/gemini-4-argonelevenlabs/scribe-v2google/gemini-3.1-flash-lite-preview+15 lainnya
VideoURL (CDN) atau data URI base64google/gemini-4-argonqwen/qwen3.8-maxminimax/minimax-m3+39 lainnya

Contoh:

# Image — URL or base64 data URI
curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-3.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"What is in this?"},
        {"type":"image_url","image_url":{"url":"https://example.com/photo.jpg"}}
      ]}]}'

# File / PDF — base64 data URI only, no URL
curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-3.5-flash","messages":[{"role":"user","content":[
        {"type":"file","file":{"filename":"doc.pdf","file_data":"data:application/pdf;base64,JVBER..."}},
        {"type":"text","text":"Summarize this."}
      ]}]}'

# Audio — raw base64, no URL. "format" is required
curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-3.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"Transcribe this."},
        {"type":"input_audio","input_audio":{"data":"UklGRi...","format":"wav"}}
      ]}]}'

# Video — URL (CDN) or base64 data URI
curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-3.5-flash","messages":[{"role":"user","content":[
        {"type":"text","text":"Describe this video."},
        {"type":"video_url","video_url":{"url":"https://example.com/clip.mp4"}}
      ]}]}'

Mengirim Gambar

Gunakan format array content dengan bagian image_url. Format yang didukung: PNG, JPEG, WebP, dan GIF (termasuk animasi). Anda dapat menyertakan banyak gambar dalam satu pesan — masing-masing sebagai bagian image_url terpisah:

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer sk-bl-YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role":"user","content":[
      {"type":"text","text":"What is in this image?"},
      {"type":"image_url","image_url":{"url":"https://example.com/photo.jpg","detail":"auto"}}
    ]}]
  }'
Mengirim Gambar
Selalu sertakan bagian teks bersamaan dengan gambar. Urutan teks-dulu (bagian teks sebelum bagian gambar) direkomendasikan untuk kompatibilitas terbaik di semua penyedia.
Mengirim Gambar
Periksa halaman Model untuk modalitas input yang didukung setiap model. Kolom modalitas menunjukkan input apa yang diterima setiap model.

Batas

BazaarLink menerapkan dua batas independen: batas rate untuk permintaan per menit, dan batas kredit untuk pengeluaran akun. Melebihi batas rate mengembalikan HTTP 429; kredit habis mengembalikan HTTP 402.

Batas Rate

Batas rate per pengguna (bukan per kunci), diukur dalam permintaan per menit (RPM). Tidak ada batas harian. Tier ditentukan secara otomatis berdasarkan saldo kredit akun Anda.

Tingkat
RPM
Penggunaan Harian
Catatan
Gratis (< $5 kredit)20 RPMTidak terbatasPengembangan & pengujian
Berbayar (>= $5 kredit)200 RPMTidak terbatasBeban kerja produksi

Ketika batas rate terlampaui, Anda menerima respons 429 dengan header Retry-After. Terapkan exponential backoff saat mencoba ulang permintaan.

Judul Respons

Respons dapat menyertakan x-request-id; x-generation-id pada respons non-streaming; x-ratelimit-*; retry-after bila berlaku; dan x-auto-resolved-model untuk routing auto atau auto:free.

x-request-id: 85e6f35c71a31f19-SJC
x-generation-id: 85e6f35c71a31f19-SJC
x-ratelimit-limit: 200
x-ratelimit-remaining: 198
x-ratelimit-reset: 1740000060
retry-after: 5
x-auto-resolved-model: openai/gpt-4o

Batas Kredit

Respons 402 berarti saldo akun Anda atau batas pengeluaran kunci telah mencapai nol — bukan berarti Anda mengirim permintaan terlalu cepat. Respons ini tidak menyertakan header rate limit, dan jika batas tercapai di tengah streaming, Anda akan menerima event error SSE, bukan perubahan status HTTP.

402 Kredit Tidak Cukup
Saat saldo Anda mencapai $0, API mengembalikan HTTP 402 dengan pesan "Insufficient credits. Please top up to continue." — pantau usage.cost di response untuk melacak pengeluaran secara real time.

Daftar izin IP

Setiap kunci API dapat memiliki daftar izin IP sendiri, sehingga hanya request dari IP sumber yang ditentukan yang dapat menggunakan kunci tersebut.

Kapan sebaiknya digunakan

Fitur ini cocok untuk deployment server production dengan IP outbound tetap. Jika aplikasi mengirim request dari jaringan rumah, jaringan seluler, atau alamat yang berubah-ubah, pastikan IP outbound stabil terlebih dahulu agar Anda tidak mengunci diri sendiri.

Cara mengatur

Buka /keys , buka menu "⋯" pada kunci yang dipilih, pilih "Daftar izin IP", masukkan entri, lalu simpan.

Anda juga dapat menggunakan PATCH /api/v1/keys/:id dengan session yang sudah login atau Management API key:

PATCH https://api.bazaarlink.ai/v1/keys/KEY_ID
Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY
Content-Type: application/json

{
  "allowedCidrs": [
    "203.0.113.7",
    "198.51.100.0/24"
  ]
}

# Clear the allowlist and return to unrestricted access
{"allowedCidrs": []}

Format entri

Di UI, masukkan satu nilai per baris. Di API, kirim nilai yang sama dalam array `allowedCidrs`. Format yang diterima adalah IPv4 polos, IPv4 CIDR, atau literal IPv6 (hanya pencocokan persis).

203.0.113.7
198.51.100.0/24
2001:db8::1

Perilaku

Kosongkan (kirim array [] kosong) untuk tidak membatasi IP sumber. Ini adalah nilai default, sehingga perilaku kunci yang sudah ada tetap sama.

IP sumber diambil dari header `cf-connecting-ip`.

Jika daftar tidak kosong tetapi IP sumber tidak dapat ditentukan, request akan ditolak (fail-closed).

⚠️ Penting: penolakan hanya mengembalikan 401 umum
Request dari luar daftar, atau request yang IP sumbernya tidak dapat ditentukan, menerima HTTP 401 umum yang sama persis seperti kunci tidak valid tanpa pesan error khusus. Ini adalah desain keamanan yang disengaja agar orang yang mendapatkan kunci tidak tahu bahwa daftar izin ada. Konsekuensinya, konfigurasi yang salah terlihat persis seperti kunci tidak valid dan sangat sulit di-debug. Sebelum menyimpan, pastikan IP outbound server Anda sudah ada di dalam daftar.
⚠️ Penting: IPv6 hanya mendukung pencocokan string persis
IPv6 tidak menggunakan perhitungan subnet; string alamat harus sama persis. Jika alamat IPv6 Anda berubah, Anda dapat terkunci di luar. Rentang CIDR /0–/32 hanya didukung untuk IPv4.
Kapan perubahan berlaku
Setelah PATCH atau penyimpanan UI berhasil, instance yang melakukan update langsung menghapus cache-nya. Dalam kondisi normal, instance lain tersinkron paling lambat sekitar 15 detik. Jika Redis bersama sedang tidak tersedia, invalidasi antar-instance tidak dapat tersebar segera dan dapat tertunda hingga TTL cache satu jam.

Pemutus Sirkuit Pribadi

Batas pengeluaran USD tetap 1 menit dan 1 jam yang diterapkan ke semua kunci API Anda. Permintaan baru mendapat HTTP 429 saat ambang batas jendela tercapai; jendela direset otomatis pada batas waktu.

cbEnabled
boolean
Aktif
cbMinuteUsd
number | null
Batas USD per menit · Gunakan default
cbHourlyUsd
number | null
Batas USD per jam · Gunakan default
(mewarisi default)
Nilai minimal 0,01 (atau kosong untuk default)
Pemutus Sirkuit Pribadi · Atur →

Keamanan Akun

Selain kata sandi, BazaarLink juga mendukung verifikasi dua langkah untuk lapisan perlindungan tambahan saat masuk.

Aktifkan verifikasi dua langkah (TOTP)

  1. Buka halaman "Pengaturan", temukan bagian "Verifikasi dua langkah (TOTP)", lalu klik "Aktifkan verifikasi dua langkah".
  2. Pindai kode QR di layar dengan aplikasi authenticator (seperti Google Authenticator), atau masukkan secret yang ditampilkan di bawah secara manual.
  3. Masukkan kode 6 digit yang dihasilkan aplikasi authenticator dan konfirmasi untuk menyelesaikan aktivasi.

Setelah diaktifkan, sistem akan menampilkan 8 kode cadangan (hanya ditampilkan sekali) — masing-masing 10 karakter dan hanya berlaku sekali. Segera catat atau salin dan simpan di tempat aman selain ponsel Anda; gunakan kode cadangan untuk masuk jika ponsel hilang atau aplikasi authenticator tidak dapat diakses.

Alur masuk setelah diaktifkan
Setelah itu, setiap kali masuk Anda perlu memasukkan kode dari aplikasi authenticator atau satu kode cadangan, selain kata sandi (atau masuk dengan Google).

Cara lain melindungi akun Anda

Gabungkan fitur berikut dengan verifikasi dua langkah untuk lebih membatasi kerugian akibat kunci yang bocor atau disalahgunakan:

  • Daftar Izin IP — membatasi API key hanya dapat digunakan dari IP sumber tertentu.
  • Pemutus Sirkuit Pribadi — menetapkan batas pengeluaran per menit dan per jam yang berhenti otomatis saat terlampaui.
  • Batas pengeluaran per key — menetapkan batas pengeluaran harian, mingguan, atau bulanan saat membuat atau memperbarui API key.

Pembuatan Gambar

Buat gambar via /v1/chat/completions dengan modalities:["image"], atau /v1/images/generations yang kompatibel dengan OpenAI DALL·E.

curl -N https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"openai/gpt-5.4-image-2","messages":[{"role":"user","content":"a red cat on a sofa"}],"modalities":["image","text"],"stream":true}'

Alur lengkap (streaming, edit gambar, protokol SSE, daftar model) lihat Referensi API →

Pembuatan Video

Alur 3-langkah async (submit → poll → content). Pembuatan video membutuhkan 30 detik hingga 5 menit.

curl https://api.bazaarlink.ai/v1/videos \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"bytedance/seedance-2.0","prompt":"a bird flying over mountains","duration":3}'
# → 202 { "id": "vjob_xxx", "status": "pending" }

Alur lengkap (polling, unduhan, jenis tugas, catatan) lihat Referensi API →

Input PDF

Kirim dokumen PDF langsung dalam pesan ke model yang mendukung input PDF secara native (mis. Claude, Gemini). BazaarLink meneruskan file langsung ke model — ditagih sebagai input token biasa, tanpa biaya tambahan atau langkah pemrosesan ekstra.

Format yang Didukung

  • Dokumen PDF (teks, gambar, tabel, pindai)
  • URL data base64 (`data:application/pdf;base64,...`)
  • Dokumen multi-halaman
  • Hanya PDF tanpa kata sandi
import base64

with open("document.pdf", "rb") as f:
    pdf_data = base64.b64encode(f.read()).decode()

response = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "file",
                "file": {
                    "filename": "document.pdf",
                    "file_data": f"data:application/pdf;base64,{pdf_data}",
                },
            },
            {"type": "text", "text": "Summarize this document."},
        ],
    }],
)

Input Video

Kirim file video ke model yang mendukung input video untuk dianalisis, diberi keterangan, atau dijawab pertanyaannya seputar adegan dan peristiwa. Bisa pakai URL langsung atau base64 data URI — URL lebih efisien untuk video yang dapat diakses publik; base64 untuk file lokal atau video privat.

Format yang Didukung

MP4 (H.264)MPEGMOVWebM
response = client.chat.completions.create(
    model="google/gemini-3.5-flash",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "video_url",
                "video_url": {"url": "https://example.com/video.mp4"},
            },
            {"type": "text", "text": "What is happening in this video?"},
        ],
    }],
)

Referensi API lengkap →

OAuth PKCE

OAuth 2.0 PKCE (Proof Key for Code Exchange) memungkinkan aplikasi klien publik (browser SPA, aplikasi mobile) membuat panggilan API atas nama pengguna individu tanpa menyimpan rahasia server jangka panjang di sisi klien.

Kapan Menggunakan OAuth PKCE

  • Membangun browser SPA atau aplikasi mobile yang membutuhkan tagihan per pengguna
  • SaaS multi-tenant — setiap pengguna akhir membayar penggunaan API mereka sendiri
  • Anda tidak dapat menyimpan rahasia bersama di sisi klien (klien publik)
  • Anda membutuhkan kunci terpisah yang dapat dicabut untuk setiap pengguna (berlaku sampai pengguna mencabutnya) alih-alih satu kunci API bersama

Yang akan dilihat pengguna Anda

Jelaskan langkah-langkah ini di layar masuk Anda sendiri:

  1. Di aplikasi Anda, mereka memilih "Masuk dengan BazaarLink" (atau apa pun nama tombol Anda).
  2. Browser mereka membuka halaman otorisasi BazaarLink. Jika belum masuk, mereka masuk terlebih dahulu lalu otomatis kembali ke halaman ini.
  3. Halaman menampilkan alamat aplikasi Anda dan apa yang terjadi jika mereka mengizinkan: kunci API baru dibuat untuk aplikasi, penggunaan ditagihkan ke saldo BazaarLink mereka, dan mereka dapat mencabut kunci kapan saja. Mereka dapat menamai kunci dan menetapkan batas pengeluaran bulanan (keduanya opsional).
  4. Mereka mengklik Izinkan lalu dikembalikan ke aplikasi Anda. Jika mereka mengklik Tolak, tidak ada kunci yang dibuat, aplikasi Anda tidak diberi tahu, dan mereka melihat halaman "Akses ditolak".
  5. Untuk mencabut akses nanti, mereka membuka halaman Kunci API (https://bazaarlink.ai/keys) dan menonaktifkan atau menghapus kunci yang dinamai sesuai aplikasi Anda.

Cara kerjanya

Langkah 1 — Mulai Autentikasi — Hasilkan code_verifier acak (string acak panjang) dan hash SHA-256-nya sebagai code_challenge, lalu arahkan pengguna ke halaman autentikasi BazaarLink.

https://bazaarlink.ai/auth?callback_url=https://yourapp.com/callback&code_challenge=CODE_CHALLENGE&code_challenge_method=S256

Parameter URL otorisasi

  • callback_url (wajib) — tujuan pengguna kembali setelah mengizinkan. Aturan di bawah.
  • code_challenge (wajib) — SHA-256 dari code_verifier Anda yang dikodekan base64url (43 karakter, tanpa padding).
  • code_challenge_method (wajib) — harus S256.
  • state (opsional) — nilai CSRF buram milik Anda sendiri, 1 sampai 256 karakter ASCII yang dapat dicetak. BazaarLink mengembalikannya apa adanya sebagai &state=… tepat setelah code. State yang salah format membuat halaman otorisasi menampilkan "Permintaan otorisasi tidak valid".
  • key_label (opsional) — hingga 100 karakter. Mengisi nama kunci di halaman persetujuan secara otomatis (pengguna tetap dapat mengubahnya). Label yang terlalu panjang atau kosong diabaikan.
  • Headless tools (CLI / desktop, no callback_url) — omit callback_url. After the user allows, the page shows a one-time code (valid 5 minutes, single use) for them to enter into your tool; exchange it exactly like a redirected code. The page cannot show which app is asking, so tell users to enter the code only in a tool they started themselves.

Tidak didukung

  • workspace_id dan required_workspace_id — tidak didukung. Kunci selalu milik akun pengguna sendiri.
  • code_challenge_method=plain — tidak didukung (hanya S256).

Aturan callback_url

  • Harus https://. http:// hanya diterima untuk localhost, 127.0.0.1, dan [::1] (port apa pun); halaman persetujuan kemudian menampilkan peringatan pengembangan lokal.
  • Tanpa fragmen (#), tanpa nama pengguna atau kata sandi di URL, maksimal 2048 karakter.
  • Halaman persetujuan menampilkan nama host callback Anda agar pengguna tahu aplikasi mana yang meminta.
  • Setelah pengguna mengizinkan, browser diarahkan ke callback_url Anda dengan code=… ditambahkan (dan state=… jika Anda mengirimnya; query string yang sudah ada dipertahankan). Code berlaku 10 menit dan hanya dapat dipakai sekali.

Langkah 2 — Tukar Kode dengan Kunci API — Setelah pengguna mengotorisasi permintaan, BazaarLink mengarahkan ke callback_url Anda dengan code sekali pakai. Code berlaku selama 10 menit dan hanya dapat dipakai sekali; code_verifier yang salah akan menghanguskannya. POST code, code_verifier, dan code_challenge_method (ketiganya wajib) untuk menerima kunci API pengguna.

curl https://bazaarlink.ai/api/v1/auth/keys \
  -H "Content-Type: application/json" \
  -d '{
    "code": "<CODE_FROM_CALLBACK_URL>",
    "code_verifier": "<CODE_VERIFIER>",
    "code_challenge_method": "S256"
  }'

# Response
# { "key": "sk-bl-...", "user_id": "..." }

Langkah 3 — Gunakan Kunci Cakupan Pengguna — Kunci yang dikembalikan adalah kunci API BazaarLink biasa milik pengguna yang memberi otorisasi — penggunaan ditagihkan ke saldo pengguna tersebut, bukan saldo Anda.

curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer sk-bl-..." \
  -H "Content-Type: application/json" \
  -d '{"model": "google/gemini-3.5-flash", "messages": [{"role": "user", "content": "Hello"}]}'

Contoh JavaScript (browser)

// 1) Create a verifier + S256 challenge, then send the user to BazaarLink
const b64url = (buf) => btoa(String.fromCharCode(...new Uint8Array(buf)))
  .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
const verifier = b64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = b64url(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)));
sessionStorage.setItem("bl_verifier", verifier);
// "state" is optional: BazaarLink hands it back unchanged next to the code.
const state = b64url(crypto.getRandomValues(new Uint8Array(16)));
sessionStorage.setItem("bl_state", state);
location.href =
  "https://bazaarlink.ai/auth?callback_url=" + encodeURIComponent(location.origin + "/callback") +
  "&code_challenge=" + challenge + "&code_challenge_method=S256&state=" + state;

// 2) On /callback: check your own state, then exchange the one-time code for a user key
const params = new URLSearchParams(location.search);
if (params.get("state") !== sessionStorage.getItem("bl_state")) throw new Error("state mismatch");
const res = await fetch("https://bazaarlink.ai/api/v1/auth/keys", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    code: params.get("code"),
    code_verifier: sessionStorage.getItem("bl_verifier"),
    code_challenge_method: "S256",
  }),
});
if (!res.ok) throw new Error((await res.json()).error?.message ?? "exchange failed"); // 403 invalid_code: ask the user to authorize again
const { key } = await res.json(); // use as: Authorization: Bearer <key>
Keamanan: Hanya S256
Atur code_challenge_method ke S256 (hash SHA-256). Hanya S256 yang didukung: permintaan dengan plain atau tanpa code_challenge_method ditolak dengan HTTP 400.
Catatan
Jika pengguna menolak, BazaarLink tidak mengalihkan kembali ke callback_url Anda dan tidak memberi tahu aplikasi Anda. Hanya halaman "Akses ditolak" yang ditampilkan, sehingga /auth tidak pernah menjadi open redirect. Tangani status belum diotorisasi di dalam aplikasi Anda (misalnya dengan timeout atau tombol coba lagi).

Halaman /auth dan POST /api/v1/auth/keys dilayani dari https://bazaarlink.ai (bukan api.bazaarlink.ai). Kunci yang Anda terima berfungsi di kedua base URL: https://bazaarlink.ai/api/v1 dan https://api.bazaarlink.ai/v1.

Jika pengguna menetapkan batas pengeluaran saat memberi otorisasi, batas itu bersifat bulanan dan direset mengikuti periode bulanan akun.

Kesalahan

Kesalahan menggunakan format ala OpenAI {"error":{"message","type","code"}}. POST /api/v1/auth/keys dapat mengembalikan:

  • 400 invalid_code_challenge_method — code_challenge_method tidak ada, plain, atau selain S256.
  • 400 — body JSON tidak valid, atau code / code_verifier tidak ada.
  • 403 invalid_code — code tidak dikenal, kedaluwarsa atau sudah dipakai, code_verifier salah, atau akun tidak lagi diizinkan. Semua kasus ini sengaja mengembalikan pesan yang sama agar pemanggil tidak dapat membedakannya. code_verifier yang salah juga menghanguskan code: minta pengguna mengotorisasi ulang.
  • 429 rate_limited — lebih dari 30 percobaan pertukaran dalam 10 menit dari satu IP (lihat header Retry-After).
  • 429 key_total_cap — akun sudah memiliki maksimum 200 kunci API.
  • 405 — hanya POST yang diterima.

Buat kode dari server Anda (Kunci Manajemen)

Pemilik Kunci Manajemen (Management Key) pribadi dapat membuat kode otorisasi langsung dengan POST /api/v1/auth/keys/code tanpa mengarahkan pengguna ke halaman browser (kompatibel dengan OpenRouter). Kode terikat pada pemilik Kunci Manajemen, sehingga kunci yang ditukar adalah kunci standar di akun pemilik tersebut, dengan batas, periode, masa berlaku, dan nama yang dipilih di sini. Gunakan bila alat Anda sendiri sudah memegang Kunci Manajemen dan ingin memberikan kunci terbatas kepada sebuah aplikasi. Penukaran (POST /api/v1/auth/keys) sama seperti di atas.

  • callback_url (wajib) dan code_challenge + code_challenge_method=S256 (wajib) — aturan sama dengan URL otorisasi.
  • key_label (opsional) — hingga 100 karakter; nama kunci. Default: "App: <host callback Anda>".
  • limit (opsional) — batas pengeluaran dalam USD, 0 atau lebih; 0 atau tidak diisi berarti tanpa batas.
  • usage_limit_type (opsional) — daily, weekly, atau monthly: seberapa sering batas direset. Hanya dipakai bersama limit; default monthly.
  • expires_at (opsional) — kapan kunci kedaluwarsa: waktu ISO 8601 UTC dengan detik di masa depan, misalnya 2026-12-31T23:59:59Z. Nilai dengan presisi menit ditolak. Jika tidak diisi, kunci tetap berlaku sampai dicabut.
  • workspace_id — tidak didukung (400). spawn_agent dan spawn_cloud diterima tetapi diabaikan.
curl https://bazaarlink.ai/api/v1/auth/keys/code \
  -H "Authorization: Bearer sk-bl-YOUR_MGMT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "callback_url": "https://yourapp.com/callback",
    "code_challenge": "<CODE_CHALLENGE>",
    "code_challenge_method": "S256",
    "key_label": "My app",
    "limit": 10,
    "usage_limit_type": "monthly",
    "expires_at": "2026-12-31T23:59:59Z"
  }'

# Response
# { "data": { "id": "<ONE_TIME_CODE>", "app_id": 123456789, "created_at": "2026-10-22T12:00:00.000Z" } }
# Then POST { "code": "<ONE_TIME_CODE>", "code_verifier": "<CODE_VERIFIER>", "code_challenge_method": "S256" } to /api/v1/auth/keys

Respons: { "data": { "id", "app_id", "created_at" } }. id adalah kode sekali pakai untuk ditukar (berlaku 10 menit, satu kali). BazaarLink tidak memiliki registri aplikasi, sehingga app_id adalah bilangan bulat tetap yang diturunkan dari alamat callback Anda: alamat yang sama selalu mendapat app_id yang sama.

  • 401 unauthorized — tidak ada kunci Bearer, atau kunci tidak dikenal.
  • 403 management_key_required — kunci bukan Kunci Manajemen pribadi (kunci standar dan Kunci Manajemen organisasi ditolak).
  • 403 account_not_allowed — pemilik kunci ditangguhkan atau dihapus.
  • 400 — invalid_callback_url, invalid_code_challenge_method, invalid_code_challenge, invalid_expires_at, workspace_not_supported, atau body yang tidak valid.
  • 429 rate_limited — lebih dari 30 kode per jam untuk satu pemilik atau 120 per jam dari satu IP (lihat Retry-After).

Kunci yang Anda terima

  • Kunci API BazaarLink standar (sk-bl-…), jenis yang sama dengan kunci yang dibuat di halaman Kunci API. Berlaku sampai pengguna mencabutnya.
  • Penggunaan ditagihkan ke saldo BazaarLink pengguna. Jika pengguna menetapkan batas pengeluaran di halaman persetujuan, batas itu bersifat bulanan.
  • Berfungsi di kedua base URL: https://bazaarlink.ai/api/v1 dan https://api.bazaarlink.ai/v1.
  • Dihitung dalam batas 200 kunci per akun dan muncul di daftar Kunci API pengguna, tempat pengguna dapat menonaktifkan atau menghapusnya kapan saja.
  • Akun yang ditangguhkan atau dihapus tidak dapat mengotorisasi aplikasi, dan code yang diterbitkan sebelum penangguhan ditolak saat pertukaran (403 invalid_code).

Yang Anda dapatkan

  • Alur Authorization Code + PKCE untuk aplikasi klien publik
  • Tagihan per pengguna: setiap pengguna membayar penggunaannya sendiri dari saldonya sendiri
  • Satu kunci terpisah untuk setiap pengguna, tercantum di halaman Kunci API pengguna tempat ia dapat mencabutnya

Kunci API Manajemen

Kunci manajemen dirancang untuk manajemen kunci programatik. Mereka dapat membuat, mendaftar, memperbarui, menonaktifkan, dan menghapus kunci API standar — tetapi tidak dapat melakukan panggilan model AI.

Catatan
Kunci manajemen tidak dapat memanggil model AI (chat/completions/messages/embeddings). Gunakan kunci API standar untuk akses model.

Membuat Kunci Manajemen

Buka halaman Management API Keys lalu klik "Create" — ini halaman terpisah dari API Keys standar, bukan pilihan tipe di halaman yang sama.

Daftar Kunci

GET https://api.bazaarlink.ai/v1/keys
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Response
{
  "keys": [
    {
      "id": "clxyz123...",
      "name": "Production Key",
      "keyType": "standard",
      "keyPrefix": "sk-bl-abc1",
      "keySuffix": "XyZ9",
      "enabled": true,
      "spendLimitUsd": 10.00,
      "spendLimitPeriod": "month",
      "expiresAt": null,
      "createdAt": "2026-01-01T00:00:00.000Z",
      "lastUsed": "2026-03-01T12:34:56.000Z",
      "requestCount": 1234,
      "totalTokens": 5678901
    }
  ]
}

Buat Sub-Kunci

POST https://api.bazaarlink.ai/v1/keys
Authorization: Bearer sk-bl-YOUR_MGMT_KEY
Content-Type: application/json

{
  "name": "Agent Key",
  "limit": 10.00,
  "limit_reset": "monthly",
  "expires_at": "2026-12-31T23:59:59Z"
}

# limit_reset: daily | weekly | monthly
# expires_at:  ISO 8601 datetime (optional)

# Response — save the key value, it won't be shown again
{
  "id": "clxyz789...",
  "name": "Agent Key",
  "key": "sk-bl-xyz789abcdef...",
  "keyType": "standard",
  "spendLimitUsd": 10.00,
  "spendLimitPeriod": "month",
  "expiresAt": "2026-12-31T23:59:59.000Z",
  "enabled": true,
  "createdAt": "2026-03-01T00:00:00.000Z"
}

Perbarui Kunci

PATCH https://api.bazaarlink.ai/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY
Content-Type: application/json

{"enabled": false}              # disable key
{"spendLimitUsd": 5, "spendLimitPeriod": "week"}  # set spend limit
{"spendLimitUsd": null}         # remove spend limit
# Response: {"updated": true}

Cabut Kunci

DELETE https://api.bazaarlink.ai/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Returns 204 No Content on success

Kueri Saldo

GET https://api.bazaarlink.ai/v1/credits
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Response
{
  "data": {
    "total_credits": 12.345,
    "total_usage": 3.210
  }
}

Kueri Penggunaan

GET https://api.bazaarlink.ai/v1/usage?period=month
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# period: day | week | month | year

Atribusi Aplikasi

Identifikasi aplikasi Anda di header permintaan untuk mengaktifkan pelacakan penggunaan, visibilitas dasbor, dan analitik terperinci.

Catatan
Header ini sepenuhnya opsional dan tidak mempengaruhi fungsionalitas API. Namun, mengaturnya direkomendasikan untuk debugging dan atribusi penggunaan.

Header yang Tersedia

HeaderDescription
HTTP-RefererURL situs Anda, untuk pelacakan penggunaan dan analitik (opsional)
X-TitleNama aplikasi Anda, ditampilkan di dasbor (opsional)
from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/v1",
    api_key="sk-bl-YOUR_KEY",
    default_headers={
        "HTTP-Referer": "https://yourapp.com",  # Optional: your site URL
        "X-Title": "My Application",             # Optional: your app name
    },
)

response = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)

Kode Error

Format respons kesalahan

Envelope error berbeda menurut endpoint. Gunakan status HTTP dan error.type bila tersedia. error.code dapat berupa string atau status numerik, atau tidak ada; error.message hanya untuk ditampilkan.

{
  "error": {
    "message": "Insufficient credits. Please top up to continue.",
    "type": "invalid_request_error",
    "code": "insufficient_credits"
  }
}

HTTP status dan kode kesalahan

Envelope error berbeda menurut endpoint. Gunakan status HTTP dan error.type bila tersedia. error.code dapat berupa string atau status numerik, atau tidak ada; error.message hanya untuk ditampilkan.

Kode
Nama
Deskripsi
424Dependensi GagalKunci BYOK yang Anda atur sendiri ditolak oleh penyedia upstream; periksa atau ganti di pengaturan BYOK. Ini hanya muncul dalam mode strict
400Permintaan BurukPermintaan salah format, array messages kosong, atau field wajib hilang
401Tidak SahKunci API hilang, tidak valid, atau dinonaktifkan
402Pembayaran DiperlukanKredit akun tidak cukup, batas pengeluaran per kunci tercapai, atau batas anggaran bulanan/mingguan terlampaui
403DilarangAkun ditangguhkan atau tidak memiliki izin
404Tidak DitemukanRequested model, generation, key, or other resource does not exist
409KonflikResource is not in the required state, such as an incomplete video job
410HilangRequested model has been retired and must be replaced
413Muatan Terlalu BesarBody permintaan melebihi 10 MB; kurangi ukuran konten atau pecah permintaan
416Rentang Tidak MemuaskanRequested byte range is invalid for generated video content
429Terlalu Banyak PermintaanBatas rate terlampaui; periksa header Retry-After sebelum mencoba ulang
432Kuota Gratis HabisEndpoint kompatibel Tavily (/v1/search, /v1/extract, /v1/crawl, /v1/map): kuota pencarian gratis sudah habis, atau saldo nol atau kurang; tambahkan kredit untuk melanjutkan. Isi respons berformat Tavily: {"detail":{"error":"..."}}
500Kesalahan ServerError internal BazaarLink
502Gerbang BurukTidak ada sumber upstream yang dapat menangani permintaan; permintaan menghasilkan error.
503Layanan Tidak TersediaTidak ada penyedia upstream yang dikonfigurasi untuk model ini; hubungi admin
504Gateway Batas WaktuUpstream connection or stream stalled and timed out

Kode penagihan yang dapat dibaca mesin

A 402 can represent different controls. Use these stable codes to choose the correct action.

Kode
Deskripsi
byok_key_invalidKunci BYOK yang Anda atur sendiri ditolak oleh penyedia upstream; periksa atau ganti di pengaturan BYOK. Ini hanya muncul dalam mode strict.
budget_cap_reachedA weekly or monthly budget cap was reached; raise or reset the cap.
credit_limit_exceededA monthly-billing organization's credit line was exhausted; contact billing.
insufficient_creditsThe prepaid balance is insufficient; add credits.
spend_limit_exceededThe API key reached its daily, weekly, or monthly spend limit.
capacity_unavailableThis model is temporarily at capacity. Retry shortly; the Retry-After header says how long to wait.

Stable error.code catalog

These string codes are emitted by public inference and media paths. Branch on the string code when present; the HTTP status remains the broad failure class.

Model dan titik akhir
Kesalahan pencarian model, siklus hidup, harga, modalitas, dan kompatibilitas titik akhir.
Kode
HTTP
unknown_model400
invalid_model_id400
model_not_found404
model_retired410
model_endpoint_mismatch400
embedding_on_chat_endpoint400
model_not_priced400
invalid_modality_for_model400
Permintaan dan keamanan
Parameter, konteks, alat, skema, dan penolakan keamanan konten tidak valid.
Kode
HTTP
missing_required_field400
unsupported_param400
max_tokens_invalid400
context_too_long400
tool_use_unsupported400
malformed_tool_messages400
invalid_response_format_schema400
invalid_tools_definition400
content_moderation403
content_filter403
unknown_4xx400
Pembuatan dan pengeditan gambar
Masukan gambar, pengeditan multibagian, keluaran, dan kesalahan saluran gambar.
Kode
HTTP
invalid_image_url400
input_images_not_supported400
invalid_content_type400
mask_not_supported400
unsupported_response_format400
missing_prompt400
missing_image400
too_many_images400
invalid_image_type400
image_too_large400
invalid_n400
pipeline_error502
no_images502
Perutean hulu
Konektivitas penyedia yang disanitasi, autentikasi, pembatasan, dan kesalahan ketersediaan.
Kode
HTTP
upstream_unreachable502
upstream_auth_failed502
upstream_rate_limited429
capacity_unavailable429
upstream_unavailable502/503
byok_key_invalid424

Moderasi Konten

Semua permintaan secara otomatis ditinjau sebelum dikirim ke model. Permintaan yang melanggar kebijakan penggunaan kami akan ditolak sebelum dikirim ke model, dan mengembalikan error 403.

Kategori yang akan diblokir

Moderasi didasarkan pada Kebijakan Penggunaan yang Dapat Diterima (Acceptable Use Policy) kami dan terutama memblokir kategori konten berikut:

  • Konten eksploitasi seksual
  • Ancaman kekerasan
  • Panduan operasional untuk tindakan ilegal
  • Konten terkait bahaya biologis

Format respons 403

Permintaan yang diblokir oleh moderasi akan mengembalikan error dengan format berikut:

{
  "error": {
    "message": "Your prompt was blocked by content moderation.",
    "type": "invalid_request_error",
    "code": "content_filter"
  }
}

Permintaan yang diblokir tidak dikenakan biaya — Anda tidak akan dikenakan biaya untuk permintaan yang ditolak.

Mengajukan banding atas kesalahan deteksi

Jika Anda yakin suatu permintaan diblokir secara keliru, hubungi dukungan dengan menyertakan waktu permintaan dan (jika memungkinkan) request id — kami akan meninjaunya.

Privasi

Permintaan ditinjau otomatis untuk keamanan konten; teks dan gambar dari input terbaru Anda dapat dikirim ke layanan penilaian keamanan konten pihak ketiga.

Untuk permintaan yang dinilai melanggar, diduga melanggar, mendekati ambang batas, atau diambil sebagai sampel acak, kami dapat menyimpan teks lengkap atau bagian awalnya sebagai bukti kepatuhan, penanganan sengketa, dan audit, tanpa menjanjikan jangka waktu penghapusan tetap.

Permintaan biasa lainnya yang berhasil tidak disimpan prompt dan responsnya; permintaan dengan kunci ZDR tidak tercakup dalam dua poin pertama.

Batas tarif, anggaran, dan rem darurat

These controls can reject an otherwise valid request and require different recovery actions.

Kontrol
HTTP
Cara mengidentifikasinya
Batas kecepatan permintaan429Kode string atau kode numerik 429; gunakan header Retry-After dan X-RateLimit-*.
Blok penalti batas tarif429Kode numerik 429 dan pesan pembatasan sementara; gunakan Coba Lagi-Setelah.
Global menghabiskan rem darurat503Kode numerik 503, pesan batas pembelanjaan global, dan Coba Lagi Setelah 30 atau 300 detik.
Scoped spend brake429Numeric code 429 and a spend circuit-breaker message naming the scope.
Penagihan dan kontrol anggaran402Gunakan kode string penagihan stabil yang tercantum di atas.

Envelope error berbeda menurut endpoint. Gunakan status HTTP dan error.type bila tersedia. error.code dapat berupa string atau status numerik, atau tidak ada; error.message hanya untuk ditampilkan.

Status sumber daya video dan media

Video validation commonly returns numeric code 400. Missing jobs return 404, retired models 410, unfinished video content 409, and invalid video byte ranges 416.

Kebijakan coba lagi

Retry only failures that may recover without changing the request. Honor Retry-After or use exponential backoff with jitter. Do not stack SDK and manual retries.

Coba lagi dengan backoff
429, 502, 503, and 504. Check the original generation job before creating another after an ambiguous network failure.
Perbaiki sebelum mencoba lagi
400, 401, 402, 403, 404, 409, 410, 413, and 416. Fix the request, credentials, balance, permissions, resource state, or Range header first.

Menangani Error

import random
import time
from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://api.bazaarlink.ai/v1",
    api_key="sk-bl-YOUR_API_KEY",
    max_retries=0,  # Avoid double retries; this example handles them.
)

RETRYABLE = {429, 502, 503, 504}

for attempt in range(5):
    try:
        response = client.chat.completions.create(
            model="openai/gpt-4o",
            messages=[{"role": "user", "content": "Hello!"}],
        )
        break
    except APIStatusError as error:
        if error.status_code not in RETRYABLE or attempt == 4:
            raise
        retry_after = error.response.headers.get("Retry-After")
        delay = (
            float(retry_after)
            if retry_after
            else min(8, 0.5 * (2 ** attempt)) + random.uniform(0, 0.25)
        )
        time.sleep(delay)

Format Error Streaming

Error yang terjadi sebelum token apa pun di-stream mengembalikan respons error HTTP standar dengan body JSON.

After a stream starts, the HTTP response is already 200. Parse each SSE data frame and treat a top-level error or choices[0].finish_reason === "error" as a failed, incomplete response.

Jika stream gagal setelah dimulai, BazaarLink dapat mengirim event SSE terakhir dengan objek error tingkat atas, diikuti data: [DONE]. Perlakukan respons sebagai belum lengkap; jangan gunakan output parsial sebagai hasil akhir.

data: {"error":{"message":"The request could not be completed.","type":"upstream_error","code":502}}

data: [DONE]

// Branch on error.code; error.type can vary by failure path.

Alat Memanggil

Tool calling (juga dikenal sebagai function calling) memungkinkan model memanggil fungsi eksternal yang Anda definisikan. Model memutuskan kapan memanggil tool dan menghasilkan argumen terstruktur — kode Anda mengeksekusi fungsi dan mengembalikan hasil untuk melanjutkan percakapan.

Model yang Didukung

Sebagian besar model frontier mendukung tool calling. Berikut beberapa pilihan populer:

Mendefinisikan Tools

Setiap tool adalah objek JSON yang mendeskripsikan fungsi yang dapat dipanggil model. Field parameters menggunakan JSON Schema.

namewajib
string
Nama fungsi (a-z, A-Z, 0-9, underscore, dash)
descriptionwajib
string
Deskripsi jelas kapan dan bagaimana fungsi harus digunakan
parameterswajib
object
Objek JSON Schema yang mendefinisikan parameter fungsi

Opsi tool_choice

Nilai
Perilaku
"auto"Model memutuskan apakah akan memanggil tool (default)
"none"Model tidak akan memanggil tool apa pun
"required"Model harus memanggil setidaknya satu tool
{"type": "function", "function": {"name": "get_weather"}}Model harus memanggil fungsi yang ditentukan

Alur Lengkap

Tool calling adalah proses multi-turn: (1) kirim permintaan dengan tools → (2) model mengembalikan tool_calls → (3) eksekusi fungsi → (4) kirim hasil kembali → (5) model menghasilkan respons akhir.

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role":"user","content":"What is the weather in Taipei?"}],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
          "type": "object",
          "properties": {
            "city": {"type": "string", "description": "City name"},
            "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
          },
          "required": ["city"]
        }
      }
    }],
    "tool_choice": "auto"
  }'
# Response carries tool_calls — run get_weather() yourself, then send the
# result back with role:"tool" (same shape as the Python/TS steps 3-5) to
# get the model's final answer.

Panggilan Tool Paralel

Beberapa model dapat memanggil banyak tool dalam satu respons. Tangani setiap panggilan tool dan kembalikan semua hasil:

# Model may return multiple tool_calls
if message.tool_calls:
    messages = [
        {"role": "user", "content": "Weather and time in Tokyo?"},
        message,
    ]

    for tool_call in message.tool_calls:
        # Execute each function
        if tool_call.function.name == "get_weather":
            result = {"temperature": 22, "condition": "Clear"}
        elif tool_call.function.name == "get_time":
            result = {"time": "2026-02-23T15:30:00+09:00"}

        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result),
        })

    # Send all results back at once
    final = client.chat.completions.create(
        model="openai/gpt-4o",
        messages=messages,
        tools=tools,
    )
    print(final.choices[0].message.content)

Panggilan Tool saat Streaming

Saat streaming, panggilan tool tiba sebagai delta parsial yang diindeks berdasarkan posisi — kumpulkan string argumen setiap delta berdasarkan indeks hingga finish_reason menjadi "tool_calls", yang menandakan panggilan telah selesai.

# Streaming: tool_calls arrive as partial deltas indexed by position —
# accumulate function.arguments per index until finish_reason == "tool_calls".
stream = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "What's the weather in Taipei?"}],
    tools=tools,
    tool_choice="auto",
    stream=True,
)

tool_calls = {}
for chunk in stream:
    delta = chunk.choices[0].delta
    if delta.tool_calls:
        for tc in delta.tool_calls:
            entry = tool_calls.setdefault(tc.index, {"id": "", "name": "", "arguments": ""})
            if tc.id:
                entry["id"] = tc.id
            if tc.function.name:
                entry["name"] = tc.function.name
            if tc.function.arguments:
                entry["arguments"] += tc.function.arguments
    if chunk.choices[0].finish_reason == "tool_calls":
        for call in tool_calls.values():
            print(call["name"], json.loads(call["arguments"]))

Loop Agentic Sederhana

Pola umum yang terus memanggil model selama model terus meminta tool, dan berhenti setelah model mengembalikan jawaban akhir — gunakan max_iterations untuk mencegah loop tak terbatas.

# Generic loop: keep calling the model while it keeps requesting tools,
# stop once it returns a plain answer. max_iterations guards against loops.
messages = [{"role": "user", "content": "What's the weather in Taipei, and what time is it there?"}]
max_iterations = 10

for _ in range(max_iterations):
    response = client.chat.completions.create(
        model="openai/gpt-4o",
        messages=messages,
        tools=tools,
    )
    message = response.choices[0].message
    messages.append(message)

    if not message.tool_calls:
        break  # model gave a final answer

    for tool_call in message.tool_calls:
        args = json.loads(tool_call.function.arguments)
        result = TOOL_MAPPING[tool_call.function.name](**args)
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result),
        })
else:
    print("Warning: max_iterations reached without a final answer")

print(messages[-1].content)

Praktik Terbaik Definisi Fungsi

  • Gunakan nama yang spesifik dan deskriptif — get_weather_forecast, bukan sekadar weather.
  • Tulis deskripsi yang jelas tentang apa yang dilakukan fungsi dan kapan harus digunakan — model hanya mengandalkan teks ini untuk memutuskan apakah akan memanggilnya.
  • Batasi nilai dengan enum jika memungkinkan dan sertakan contoh dalam deskripsi untuk mengurangi argumen yang salah bentuk.
  • Tandai hanya field yang benar-benar wajib sebagai required — field opsional harus benar-benar bisa dihilangkan.

Output Terstruktur

Paksa model mengembalikan JSON valid yang cocok dengan skema. Ini penting untuk membangun aplikasi andal yang mem-parse output model secara programatik.

Metode 1: response_format (JSON Schema)

untuk memaksa kepatuhan JSON Schema yang ketat:

typewajib
string
Harus "json_schema"
json_schema.namewajib
string
Nama untuk skema (digunakan untuk caching)
json_schema.strict
boolean
Jika true, menjamin kepatuhan skema yang tepat
json_schema.schemawajib
object
Definisi JSON Schema
curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role":"user","content":"Review the movie Inception"}],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "movie_review",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "title": {"type": "string"},
            "rating": {"type": "integer", "description": "Rating 1-10"},
            "summary": {"type": "string"},
            "pros": {"type": "array", "items": {"type": "string"}},
            "cons": {"type": "array", "items": {"type": "string"}}
          },
          "required": ["title", "rating", "summary", "pros", "cons"],
          "additionalProperties": false
        }
      }
    }
  }'

Tips

  • Gunakan nama properti yang jelas dan deskriptif — model menggunakannya sebagai konteks.
  • Tambahkan deskripsi ke properti skema untuk memandu model.
  • Atur strict: true untuk kepatuhan skema yang dijamin (mungkin sedikit meningkatkan latensi).
  • Jaga skema tetap sederhana — skema yang sangat bersarang dapat mengurangi kualitas output.
  • Uji dengan model berbeda — beberapa menangani skema kompleks lebih baik dari yang lain.

AAsisten Prefill

Tambahkan pesan assistant yang belum selesai sebagai item terakhir untuk meminta kelanjutan pada rute model yang kompatibel.

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-4.6",
    "messages": [
      {"role":"user","content":"What is the capital of France?"},
      {"role":"assistant","content":"The capital of France is"}
    ]
  }'
# Model continues: " Paris, known for the Eiffel Tower..."
Cara kerjanya
BazaarLink mempertahankan dan meneruskan pesan assistant terakhir. Perilaku kelanjutan diterapkan oleh model dan penyedia upstream yang dipilih, sehingga tidak dijamin pada setiap rute.

Transformasi Pesan

The client-supplied transforms field is ignored and removed before an upstream request. It cannot enable or disable message transformations. BazaarLink may apply context handling under its own server-side rules; shorten the input or select a model with a larger context window when needed.

Unsupported request field
Do not rely on transforms values such as middle-out; they do not change how this request is routed or processed.

Tanpa Penyimpanan Data

Untuk permintaan biasa yang berhasil, BazaarLink tidak menyimpan konten pesan Anda (pengecualian: lihat Kebijakan Privasi); mode kunci ZDR menyediakan zero data retention yang lebih ketat. Halaman ini menjelaskan bagaimana data Anda ditangani. Cocok untuk aplikasi yang memproses data sensitif.

Penanganan Data Saat Ini

  • Konten pesan: tidak disimpan untuk permintaan biasa yang berhasil (pengecualian: lihat Kebijakan Privasi); mode kunci ZDR lebih ketat
  • Catatan penggunaan untuk tagihan dan operasional: jumlah token, waktu, model, biaya, latensi, dan status
  • Log penggunaan: hanya statistik penggunaan untuk permintaan biasa yang berhasil, tanpa konten pesan
  • Penerusan upstream: pesan diteruskan ke penyedia upstream — tunduk pada kebijakan privasi mereka

Caching Cepat

Prompt caching menggunakan ulang token prompt yang sudah dihitung sebelumnya, secara signifikan mengurangi biaya dan latensi — terutama untuk aplikasi dengan prompt sistem besar yang berulang.

Note
BazaarLink secara otomatis melacak penghematan cache dan mencerminkannya dalam tagihan. Field `cached_tokens` dalam respons menunjukkan hit cache aktual; `cacheDiscount` menunjukkan jumlah yang dihemat pada permintaan tersebut.

Cara Kerjanya

Perlu tidaknya konfigurasi tergantung penyedia model. Model keluarga OpenAI meng-cache prefiks prompt yang panjang dan berulang secara otomatis — tidak perlu mengubah request. Model Claude (Anthropic) hanya meng-cache jika request menyertakan breakpoint cache_control secara eksplisit; BazaarLink tidak menambahkannya untuk Anda, jadi request Claude tanpa marker tidak akan pernah di-cache. BazaarLink meneruskan marker cache yang Anda kirim apa adanya dan melaporkan jumlah token cache read/write sebenarnya di respons penggunaan.

# OpenAI-family models: nothing to add, long repeated prefixes cache automatically.
response = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[
        {"role": "system", "content": "You are an expert..."},  # cached automatically if long/repeated
        {"role": "user", "content": "Question here"},
    ],
)

# Check cache savings in the response usage
usage = response.usage
print(f"Prompt tokens: {usage.prompt_tokens}")
print(f"Cached tokens: {usage.prompt_tokens_details.cached_tokens}")
print(f"Cache savings: {usage.prompt_tokens_details.cached_tokens / usage.prompt_tokens * 100:.1f}%")
Claude memerlukan marker cache_control eksplisit
Tambahkan cache_control: {"type": "ephemeral"} ke blok konten yang ingin Anda cache, seperti contoh di bawah. Anthropic juga menerapkan panjang prompt minimum miliknya sendiri — di bawah itu, meski ada marker, tetap tidak akan di-cache tanpa error apa pun. Periksa cached_tokens (format OpenAI) atau cache_read_input_tokens / cache_creation_input_tokens (format Anthropic) di respons untuk memastikan cache benar-benar terpakai.
# Claude models: you must mark the block to cache yourself.
response = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[
        {
            "role": "system",
            "content": [
                {"type": "text", "text": "You are an expert...", "cache_control": {"type": "ephemeral"}}
            ],
        },  # BazaarLink does not add cache_control on your behalf
        {"role": "user", "content": "Question here"},
    ],
)

usage = response.usage
print(f"Cache read tokens: {getattr(usage, 'cache_read_input_tokens', 0)}")
print(f"Cache write tokens: {getattr(usage, 'cache_creation_input_tokens', 0)}")

Token Penalaran

Model penalaran (mis., DeepSeek R1, seri o1) berpikir secara internal sebelum menghasilkan jawaban akhir. Token internal ini disebut token penalaran dan ditagih secara terpisah.

Note
BazaarLink melaporkan token penalaran di `usage.completion_tokens_details.reasoning_tokens` dan menampilkannya secara terpisah dalam tagihan.

Membaca Token Penalaran dari Respons

response = client.chat.completions.create(
    model="deepseek/deepseek-r1",
    messages=[{"role": "user", "content": "Solve: if f(x) = x^2 + 3x, what is f(5)?"}],
)

# Read reasoning tokens from usage
usage = response.usage
print(f"Completion tokens: {usage.completion_tokens}")
if hasattr(usage, "completion_tokens_details"):
    details = usage.completion_tokens_details
    print(f"Reasoning tokens: {details.reasoning_tokens}")
    print(f"Output tokens: {details.accepted_prediction_tokens}")
const response = await client.chat.completions.create({
  model: "openai/gpt-5.5",
  messages: [{ role: "user", content: "Prove that sqrt(2) is irrational." }],
  // @ts-ignore - BazaarLink extension
  reasoning_effort: "high",  // low | medium | high
});

const usage = response.usage;
console.log("Reasoning tokens:", usage?.completion_tokens_details?.reasoning_tokens);

Kontrol Mode Berpikir

Beberapa model mendukung pengaktifan mode "berpikir". Mode berpikir menghasilkan token penalaran internal sebelum menghasilkan jawaban akhir, meningkatkan kualitas dengan biaya token lebih banyak.

Keluarga ModelParameterDefault
qwen3-*enable_thinking: booleanfalse (default platform)
openai/gpt-5.5, gpt-5.6-sol, gpt-5.4reasoning_effort: "low" | "medium" | "high"medium
deepseek/deepseek-r1—Selalu aktif (tidak dapat dinonaktifkan)
# Qwen3: explicitly enable thinking mode
response = client.chat.completions.create(
    model="qwen/qwen3.7-flash",
    messages=[{"role": "user", "content": "Prove the Pythagorean theorem"}],
    extra_body={"enable_thinking": True},  # opt-in to thinking
)

# usage.completion_tokens_details.reasoning_tokens shows thinking token count

Objek reasoning Terpadu (Format Baru)

BazaarLink juga mendukung objek reasoning terpadu, yang berfungsi di semua keluarga model dengan satu API yang konsisten:

BidangNilaiBerlaku untuk
reasoning.effort"xhigh" | "high" | "medium" | "low" | "none"OpenAI o-series, Grok
reasoning.max_tokensintegerAnthropic Claude, Gemini
reasoning.excludebooleanSembunyikan penalaran dari respons (model tetap melakukan penalaran)
// Claude extended thinking — specify thinking budget in tokens
const response = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4.5",
  messages: [{ role: "user", content: "Prove the Pythagorean theorem" }],
  // @ts-ignore - BazaarLink extension
  reasoning: { max_tokens: 5000 },
});

// OpenAI GPT-5.6 Sol — specify effort level
const response2 = await client.chat.completions.create({
  model: "openai/gpt-5.6-sol",
  messages: [{ role: "user", content: "Solve this math problem..." }],
  // @ts-ignore - BazaarLink extension
  reasoning: { effort: "high" },
});

// Hide thinking content from response (model still thinks)
const response3 = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-4.5",
  messages: [{ role: "user", content: "What is 2+2?" }],
  // @ts-ignore - BazaarLink extension
  reasoning: { max_tokens: 2000, exclude: true },
});

Membaca isi pemikiran

Model reasoning dapat mengembalikan isi pemikirannya bersama jawaban. Untuk model yang tercantum di bawah, berpikir aktif secara default: permintaan tanpa parameter reasoning dijalankan dengan berpikir aktif, mengembalikan isi pemikiran, dan ditagih sesuai token pemikiran yang benar-benar dipakai. Kirim reasoning: { exclude: true } atau include_reasoning: false untuk mematikannya. Semua model lain hanya mengembalikan isi pemikiran jika Anda memintanya: kirim reasoning_effort, objek reasoning, include_reasoning: true, thinking atau enable_thinking.

Model yang berpikir secara default: gemini-4-argon, deepseek-v4.1-flash, deepseek-v4.1-flash-1017

Cara memintanya

Kirim salah satu dari ini dalam permintaan: reasoning_effort (low, medium atau high), objek reasoning (effort, max_tokens), include_reasoning: true, thinking: { type: "enabled" } atau enable_thinking: true. Kirim reasoning.exclude: true atau include_reasoning: false untuk mematikan isi pemikiran (model tetap bernalar).

BidangLokasiArti
reasoningchoices[].message.reasoningIsi pemikiran (string)
reasoning_detailschoices[].message.reasoning_detailsIsi pemikiran sebagai daftar item, setiap item hanya berisi type dan text
reasoningchoices[].delta.reasoningStreaming: isi pemikiran datang sepotong-sepotong (delta.reasoning dan delta.reasoning_details), sebelum teks jawaban di delta.content
Note
Tanpa parameter: model yang tercantum di atas berpikir secara default, jadi Anda menerima isi pemikiran dan membayar token pemikiran (usage.completion_tokens_details.reasoning_tokens). Untuk semua model lain, tanpa parameter berarti tanpa isi pemikiran: Anda hanya menerima jawaban (message.content), persis seperti sebelumnya. Untuk mematikan pemikiran pada model yang tercantum, kirim reasoning.exclude: true atau include_reasoning: false: tidak ada pemikiran yang dijalankan dan tidak ada token pemikiran yang ditagih. Pada model reasoning lain, exclude hanya menyembunyikan teks; token reasoning-nya tetap dihitung.

Periksa tingkat yang didukung tiap model dengan GET /v1/models: setiap model reasoning mencantumkan reasoning.supported_efforts, reasoning.default_effort dan reasoning.mandatory (misalnya gemini-4-argon mendukung high, medium dan low).

Contoh: gemini-4-argon

response = client.chat.completions.create(
    model="gemini-4-argon",
    messages=[{"role": "user", "content": "Which is larger, 9.11 or 9.9?"}],
    reasoning_effort="high",  # or: extra_body={"include_reasoning": True}
)

message = response.choices[0].message
print(message.reasoning)          # the thinking text (only returned because we asked)
print(message.content)            # the answer
const stream = await client.chat.completions.create({
  model: "gemini-4-argon",
  messages: [{ role: "user", content: "Which is larger, 9.11 or 9.9?" }],
  stream: true,
  // @ts-ignore - BazaarLink extension
  reasoning: { effort: "high" },
});

for await (const chunk of stream) {
  const delta: any = chunk.choices[0]?.delta;
  if (delta?.reasoning) process.stdout.write(delta.reasoning); // thinking text
  if (delta?.content) process.stdout.write(delta.content);     // answer
}

Di /v1/responses, minta dengan reasoning: { effort, summary: "auto" }; isi pemikiran dikembalikan pada item reasoning di array output. Di /v1/messages, kirim thinking: { type: "enabled", budget_tokens } untuk menerima blok thinking.

Harga
Token penalaran ditagih sebagai token completion. Beberapa penyedia mengenakan tarif lebih tinggi untuk mode berpikir — Qwen3 biayanya 2x harga standar saat berpikir aktif. BazaarLink default-kan Qwen3 ke enable_thinking=false untuk menghindari biaya tak terduga.

Latensi & Performa

Mengoptimalkan latensi respons API AI sangat penting untuk pengalaman pengguna. Di bawah ini adalah faktor-faktor utama yang mempengaruhi latensi dalam arsitektur BazaarLink dan praktik terbaik untuk optimasi.

Note
BazaarLink mencatat `duration_ms` (latensi end-to-end) dan `throughput` (token/detik) untuk setiap permintaan — cek via GET /v1/generation?id=..., atau di CSV Activity Export.

Faktor yang Mempengaruhi Latensi

  • Ukuran model: model lebih besar (70B+) umumnya lebih lambat menghasilkan
  • Beban penyedia: bervariasi antar penyedia dan waktu dalam sehari
  • Jumlah token: max_tokens lebih tinggi berarti waktu completion lebih lama
  • Streaming vs. non-streaming: stream: true mengirimkan token pertama lebih cepat
  • Panjang konteks: konteks sangat panjang meningkatkan waktu pra-pemrosesan

Tips Optimasi

  • Lebih suka streaming (stream: true) untuk meningkatkan latensi yang dirasakan
  • Pilih model lebih kecil (flash/mini/haiku) untuk skenario sensitif latensi
  • Aktifkan prompt caching untuk mengurangi latensi permintaan berulang
import time

# Measure time to first token with streaming
start = time.time()
first_token_time = None

stream = client.chat.completions.create(
    model="google/gemini-3.5-flash",  # Fast model
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content and not first_token_time:
        first_token_time = time.time() - start

print(f"Time to first token: {first_token_time:.3f}s")
# Look up per-request latency and throughput after the fact, using the
# generation ID from the response (or the final streamed chunk).
curl "https://api.bazaarlink.ai/v1/generation?id=BAZAARLINK_REQUEST_ID" \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

# Response
{
  "data": {
    "id": "85e6f35c71a31f19-SJC",
    "model": "google/gemini-3.5-flash",
    "duration_ms": 842,
    "throughput": 61.2,
    "usage": { "prompt_tokens": 12, "completion_tokens": 48, "total_tokens": 60 }
  }
}

Optimasi Uptime

Setelah upstream error, permintaan dapat mencoba sumber lain yang tersedia. Jika tidak ada sumber yang dapat menangani permintaan, error akan dikembalikan. Circuit breaker membatasi percobaan berulang dan status penyedia dipantau.

Note
BazaarLink melacak ketersediaan untuk semua penyedia upstream. Ketika tingkat error penyedia melebihi ambang batas, circuit breaker otomatis aktif dan mengarahkan permintaan ke penyedia berikutnya yang tersedia.

Mekanisme Ketersediaan

  • Circuit breaker: otomatis mendeteksi dan mengisolasi penyedia yang gagal
  • Jika sumber upstream bermasalah, permintaan dapat mencoba sumber lain yang tersedia. Jika tidak ada yang tersedia, permintaan menghasilkan error.
  • Pemantauan kesehatan penyedia: terus melacak tingkat error dan latensi per penyedia
  • Logika percobaan ulang: error sementara (5xx) otomatis dicoba ulang

Pemutus Sirkuit

# If an upstream source returns an error, the request can try another available source.
# Requests handled by a platform model are billed at that model's catalog price.

response = client.chat.completions.create(
    model="openai/gpt-4o",       # Primary model
    messages=[{"role": "user", "content": "Hello!"}],
    extra_body={
        "models": [              # Local fallback chain, tried in order
            "openai/gpt-4o",
            "anthropic/claude-sonnet-4.6",
            "google/gemini-3.5-flash",
        ],
    },
)

# Check whether another source handled the request (in usage logs)
# "is_failover": true indicates the primary provider was bypassed
Pemantauan kesehatan penyedia hanya untuk tim ops internal
GET /api/admin/provider-health adalah endpoint internal untuk dasbor ops, dilindungi otentikasi admin. Endpoint ini mengembalikan data operasional lengkap (volume permintaan, tingkat error, persentil latensi, statistik failover per penyedia, dan lainnya) — bukan API publik untuk pelanggan umum, jadi kami tidak mereproduksi field sebenarnya di sini.

Pagar Pembatas

Tambahkan mekanisme keamanan konten ke permintaan API Anda untuk memfilter konten berbahaya dan menegakkan kebijakan kepatuhan. BazaarLink saat ini hanya menyediakan guardrail penyaringan konten yang dapat disesuaikan di tingkat organisasi; kunci API pribadi (non-organisasi) tidak memiliki pengaturan setara — keamanan konten sepenuhnya bergantung pada sistem keamanan bawaan masing-masing penyedia model upstream.

Cakupan Saat Ini
Kunci API pribadi tidak memiliki guardrail kustom bawaan — keamanan konten sepenuhnya bergantung pada sistem keamanan penyedia upstream itu sendiri. Jika Anda memerlukan aturan penyaringan konten yang dapat disesuaikan (blokir/redaksi/tandai, aturan kata kunci dan regex, template PII bawaan), buat organisasi dan gunakan kunci API organisasi — dikonfigurasi di bawah "Content Filter Guardrails."

Fitur yang Direncanakan (belum tersedia untuk kunci pribadi maupun organisasi)

Pagar Pembatas Pesan yang kompatibel dengan
Deskripsi
Deteksi PIIDeteksi dan redaksi informasi yang dapat mengidentifikasi pribadi
Pembatasan topikBatasi respons model hanya pada topik yang disetujui
Validasi outputValidasi output model terhadap aturan kustom sebelum dikembalikan

Perilaku Saat Ini

Kunci API pribadi: semua penyedia upstream memiliki sistem keamanan konten mereka sendiri — respons model yang memicu filter konten dikembalikan dengan finish_reason: "content_filter", dan BazaarLink tidak menerapkan penyaringan tambahan. Kunci API organisasi: org_admin dapat mengonfigurasi aturan kustom (blokir/redaksi/tandai) di bawah "Content Filter Guardrails," diterapkan sebelum teks mencapai model.

Kursor IDE

Gunakan BazaarLink sebagai Override URL OpenAI Cursor. Setup plug-and-play dengan konversi otomatis Responses API, normalisasi format tool, dan konvensi prefix bz- untuk model Claude.

Pengaturan cepat

Di Cursor, buka Settings → Models, lalu:

  1. Atur Override OpenAI Base URL ke https://api.bazaarlink.ai/v1
  2. Atur Override OpenAI API Key ke kunci BazaarLink sk-bl-... Anda
  3. Tambahkan nama model yang diinginkan — lihat di bawah untuk Claude (prefix bz-).
Kompatibilitas mundur
Endpoint kompatibilitas /cursor yang lama masih berfungsi, di kedua host (https://api.bazaarlink.ai/v1/cursor dan https://bazaarlink.ai/api/v1/cursor). Ini hanya re-export tipis dari /v1/chat/completions — setup baru sebaiknya memakai base URL di atas.

Prefix bz- (untuk model Claude)

Validasi client-side Cursor merutekan setiap nama model yang dimulai dengan claude- melalui integrasi Anthropic milik Cursor sendiri, melewati Override URL Anda. Agar Cursor mengirim permintaan ke BazaarLink, beri awalan bz- pada nama model. Server menghapus prefix dan menyelesaikan sisanya melalui alias map.

Ketik di CursorMenjadi
bz-claude-sonnet-4.6anthropic/claude-sonnet-4.6
bz-claude-opus-4.7anthropic/claude-opus-4.7
gpt-4oopenai/gpt-4o
gemini-3.5-flashgoogle/gemini-3.5-flash

Variasi titik vs tanda hubung dinormalisasi: bz-claude-sonnet-4.6 dan bz-claude-sonnet-4-6 keduanya menjadi model yang sama.

Env var CURSOR_MODEL_MAP (override operator)

Untuk deployment BazaarLink self-hosted, setel env var ini untuk memetakan ulang nama model sisi Cursor ke canonical id katalog:

CURSOR_MODEL_MAP=gpt-claude-sonnet:anthropic/claude-sonnet-4.6,gpt-opus:anthropic/claude-opus-4.7

Sekarang gpt-claude-sonnet yang diketik di Cursor dipetakan ke anthropic/claude-sonnet-4.6 di sisi server. Berguna ketika Anda ingin Cursor mengira sebuah model adalah keluarga GPT (agar dirutekan via Override URL) sementara Anda sebenarnya menyajikan Claude.

Apa yang terjadi secara otomatis

Ketika sebuah permintaan mencapai /v1/chat/completions, BazaarLink menerapkan transformasi kompatibilitas berikut secara transparan — Anda tidak perlu melakukan apa pun di sisi client:

  • Mendeteksi otomatis body Responses API — jika body memiliki input alih-alih messages, ia dikonversi ke bentuk Chat Completions (Cursor mengirim format Responses API untuk model keluarga GPT).
  • Membungkus definisi tool datar — Cursor Agent mengirim { name, description, parameters } tanpa pembungkus function. Kami membungkusnya agar upstream tidak menolak sebagai Tool '' not found in provided tools.
  • Mengoreksi tool_choice yang salah bentuk — Cursor mengirim { type: "auto" } (bentuk objek, tanpa function). Spesifikasi OpenAI memerlukan bentuk string untuk auto/none/required, jadi kami mengoreksinya.
  • Menghapus field khusus penyedia saat upstream tidak mendukungnya — parallel_tool_calls, logprobs, top_logprobs, logit_bias, service_tier, user dihapus sebelum diteruskan (jika tidak, upstream mengembalikan 400).
  • Memetakan max_output_tokens → max_tokens dan menghapus field khusus Responses-API (previous_response_id, truncation, background, store). Field reasoning dipertahankan untuk body Chat-Completions native.

Mode Cursor Agent

Pemanggilan tool bekerja melalui alur tool-call Chat Completions standar. Cursor mengirim tools (Shell, Read, Write, Grep, dll.) dengan tool_choice: "auto"; BazaarLink meneruskan ke penyedia model pilihan Anda, yang memutuskan memanggil tool atau tidak. Pemanggilan tool dikembalikan sebagai delta tool_calls OpenAI standar; Cursor mengeksekusi secara lokal dan melanjutkan percakapan. Bekerja sama baik Anda memilih gpt-4o (OpenAI native) atau bz-claude-sonnet-4.6.

Debug penolakan upstream
Jika Anda melihat error provider 4xx, periksa panel admin Provider Health. Setiap respons 4xx disimpan dengan body error upstream lengkap dan ringkasan body permintaan yang kami teruskan — klik baris 🔴 mana pun untuk memperluas JSON.

Routing Model

BazaarLink menggunakan format provider/model-name untuk mengarahkan permintaan ke penyedia upstream yang tepat. Ini memberi Anda akses ke semua model utama melalui satu endpoint API.

Format ID Model

{provider}/{model-name}

# Examples
openai/gpt-5.4-mini
anthropic/claude-sonnet-4.6
google/gemini-3-flash-preview
deepseek/deepseek-v4.1-flash

Prioritas Routing

Saat Anda mengirim permintaan, BazaarLink menyelesaikan penyedia upstream dalam urutan ini:

  1. Pencocokan tepat — mencari route model yang cocok dengan ID model lengkap
  2. Wildcard penyedia — fallback ke route provider/* (mis. openai/*)
  3. Wildcard global — fallback ke route wildcard *
  4. Kunci penyedia default — hanya untuk model katalog yang dikenal, memakai kunci aktif yang ditandai default

Jelajahi semua model yang tersedia di halaman Model.

Router Otomatis

Auto Router v3 menilai permintaan ke salah satu dari 14 tier tugas, lalu memakai primary dan rantai fallback yang saat ini dikonfigurasi untuk tier tersebut. Tabel berbayar dan gratis dikelola terpisah di admin.

  • auto — memakai tabel routing berbayar; model aktual yang berhasil ditagih sesuai harga publiknya.
  • auto:free — memakai tabel routing gratis; biaya USD 0 selama kuota gratis. Setelah kuota habis, akun dengan saldo dapat berpindah ke auto berbayar kecuali fallback berbayar dinonaktifkan.

Cara Menggunakan

Atur model ke "auto" (berbayar) atau "auto:free" (gratis) untuk mengaktifkan routing otomatis:

curl https://api.bazaarlink.ai/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Review this TypeScript function"}]}'

Cara v3 memilih tier

Tier umum: simple, standard, complex, reasoning. Tier khusus: coding, vision, image, video, data, search, social, email, calendar, trading. Hasil batas berkepercayaan rendah dinaikkan satu tingkat.

  • Penilaian tier: messages, tools, panjang, kata kunci, dan sinyal struktur memilih satu dari 14 tier
  • Aturan keras: gambar, penalaran formal, dan tugas khusus dapat memilih tier langsung
  • Pencarian route: membaca primary dan maksimal lima fallback; tier nonaktif mengembalikan 503
  • Eksekusi: mencoba primary lalu fallback sesuai urutan konfigurasi
  • Pelacakan respons: model yang dipilih dikembalikan dalam body respons dan header X-Auto-Resolved-Model

Tabel model saat ini

Tabel berikut dibaca dari konfigurasi live yang sama dengan inference dan admin. Primary, urutan fallback, dan status tiap tier dapat diubah tanpa deployment.

auto

Tier
Primary
Fallbacks
State
simpleopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-haiku-4.5
enabled
standardgoogle/gemini-3-flash-preview
openai/gpt-5.4-minianthropic/claude-haiku-4.5
enabled
complexgoogle/gemini-3.1-pro-preview
anthropic/claude-sonnet-4.6openai/gpt-5.4-pro
enabled
reasoninganthropic/claude-opus-4.7
openai/gpt-5.4-progoogle/gemini-3.1-pro-preview
enabled
codingopenai/gpt-5.3-codex
anthropic/claude-sonnet-4.6openai/gpt-5.4-pro
enabled
visionopenai/gpt-5.4-image-2
—
enabled
imageopenai/gpt-5.4-image-2
—
enabled
videobytedance/seedance-2.0-fast
bytedance/seedance-2.0anthropic/claude-sonnet-4.6
enabled
dataopenai/gpt-5.4-pro
anthropic/claude-sonnet-4.6google/gemini-3.1-pro-preview
enabled
searchperplexity/sonar-pro
perplexity/sonar-reasoning-proopenai/gpt-5.4-pro
enabled
socialopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-haiku-4.5
enabled
emailopenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-previewanthropic/claude-sonnet-4.6
enabled
calendaropenai/gpt-5.4-nano
google/gemini-3.1-flash-lite-preview
enabled
tradinganthropic/claude-opus-4.7
openai/gpt-5.4-progoogle/gemini-3.1-pro-preview
enabled

auto:free

Tier
Primary
Fallbacks
State
simpledeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
standarddeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
complexdeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
reasoningdeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
codingdeepseek/deepseek-v4-flash-0731free
reflection/beamnvidia/nemotron-3.5-lightning-free
enabled
visionopenai/gpt-5.4-image-2
—
disabled
imageopenai/gpt-5.4-image-2
—
disabled
videogoogle/gemini-2.5-flash-lite
—
disabled
datadeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
searchdeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
socialdeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
emaildeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
calendardeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled
tradingdeepseek/deepseek-v4-flash-0731free
nvidia/nemotron-3.5-lightning-freereflection/beam
enabled

Model tertentu menawarkan tier gratis dengan batas laju. Kelayakan gratis diberikan per model oleh platform — panggil model dengan ID regulernya; sufiks :free adalah alias opsional (menambahkannya ke model berbayar tidak membuatnya gratis).

Setelah kuota gratis habis
Setelah kuota gratis habis, permintaan tambahan ditagihkan dengan tarif berbayar model jika akun memiliki saldo. Untuk menerima 429, kirim `X-Free-Fallback: false` atau nonaktifkan peralihan ke tingkat berbayar di pengaturan kunci. Tanpa saldo, permintaan yang melebihi kuota mengembalikan 429. Saat permintaan benar-benar di-downgrade dengan cara ini, respons membawa header x-bl-free-fallback: daily atau x-bl-free-fallback: rpm yang menyebutkan batas mana yang terpicu, sehingga Anda bisa mendeteksi peralihan itu saat permintaan dibuat, bukan hanya dari tagihan. Header ini tidak ada pada permintaan yang tidak di-downgrade.
X-Auto-Resolved-Model
Model aktual yang dipilih dikembalikan dalam header X-Auto-Resolved-Model dan field model pada respons.

Varian Model

Kolom perutean pelanggan diabaikan
provider (seluruh objek), transforms, route, service_tier tingkat teratas, dan preset dihapus sebelum permintaan diteruskan sehingga tidak dapat memilih upstream atau tingkat harga. Pada endpoint Chat Completions dan Responses, array models didukung sebagai daftar fallback lokal: BazaarLink merutekan setiap model sendiri dan mengenakan harga pelanggan untuk model tersebut; daftar ini tidak diteruskan ke upstream. Akhiran :nitro, :floor, dan :exacto yang dikirim pelanggan diabaikan. :eco tetap menjadi tier ekonomi BazaarLink dan dipetakan secara internal ke BazaarLink :floor. :free tetap menjadi varian model katalog tersendiri.

ID Model Independen

Varian katalog seperti :free, :extended, dan :thinking dapat menandai entri dengan kemampuan atau harga katalog yang berbeda. Rute upstream dan harga pelanggan ditentukan oleh katalog serta aturan sisi server BazaarLink.

:free
:extended
:thinking
:nitro
:floor
:exacto
Biaya tambahan pencarian web
Perilaku pencarian web yang diminta melalui plugins, :online, atau web_search_options tetap sama dan dapat menimbulkan biaya tambahan upstream. Biaya dibebankan ke kunci yang digunakan untuk permintaan: kunci platform BazaarLink atau kunci BYOK Anda.
:online

Model Gratis

Model tertentu menawarkan tier gratis dengan batas laju. Kelayakan gratis diberikan per model oleh platform — panggil model dengan ID regulernya; sufiks :free adalah alias opsional (menambahkannya ke model berbayar tidak membuatnya gratis).

  • Panggil ID model reguler (mis. deepseek/deepseek-v4-flash). Permintaan dalam kuota gratis otomatis dilayani tanpa biaya.
  • Penggunaan gratis dibatasi per pengguna berdasarkan permintaan per menit dan batas harian. Batas menyesuaikan tingkat akun (tanpa kredit / berkredit).
  • Saat kuota gratis terlampaui dan Anda punya kredit, permintaan otomatis berlanjut di tier berbayar dengan harga tercantum. Kirim X-Free-Fallback: false untuk menonaktifkan fallback otomatis dan menerima 429. Tanpa kredit, permintaan melebihi kuota mengembalikan 429.
  • GET /v1/models mencantumkan entri :free untuk setiap model dengan tier gratis; auto:free selalu diarahkan ke model gratis.

Model dengan kuota gratis saat ini

Panggil ID model ini secara langsung untuk memakai kuota gratis. Daftarnya berubah seiring waktu — ambil versi terbaru lewat API.

qwen/qwen3.7-flash
reflection/beam-free
stealth/glyph-cluster
nvidia/nemotron-3.5-lightning-free
inclusionai/ling-3.1-flash-1019
deepseek/deepseek-v4-flash-0731free

Batas kuota gratis

Item
Nilai
Permintaan per menit (RPM)10 / min
Anggaran permintaan harian60 / day
Pengali tingkat akun — tanpa saldo× 1
Pengali tingkat akun — bersaldo× 2

Anggaran harian = anggaran permintaan harian di atas × pengali tingkat akun, dihitung terpisah untuk tiap model gratis. auto:free juga menerapkan batas paralel per-IP. Model tertentu bisa diberi batas lebih ketat atau lebih longgar oleh platform; nilai efektifnya ditampilkan di blok "Kuota gratis" pada halaman model. Kuota gratis dihitung dalam "unit", bukan sekadar jumlah permintaan: unit yang dikonsumsi satu permintaan bertambah seiring panjang context prompt. Dengan kuota harian yang sama, permintaan ber-context panjang menghasilkan jauh lebih sedikit penggunaan dibanding prompt pendek.

Setelah kuota gratis habis

Setelah kuota gratis habis, permintaan tambahan ditagihkan dengan tarif berbayar model jika akun memiliki saldo. Untuk menerima 429, kirim `X-Free-Fallback: false` atau nonaktifkan peralihan ke tingkat berbayar di pengaturan kunci. Tanpa saldo, permintaan yang melebihi kuota mengembalikan 429.

Saat permintaan benar-benar di-downgrade dengan cara ini, respons membawa header x-bl-free-fallback: daily atau x-bl-free-fallback: rpm yang menyebutkan batas mana yang terpicu, sehingga Anda bisa mendeteksi peralihan itu saat permintaan dibuat, bukan hanya dari tagihan. Header ini tidak ada pada permintaan yang tidak di-downgrade.

# Return 429 instead of switching to paid routing
-H "X-Free-Fallback: false"

Manajemen Organisasi

Organisasi BazaarLink menggunakan arsitektur tiga tingkat: Organisasi → Tim → Anggota. Kredit disimpan di tingkat organisasi; setiap Tim dan anggota dapat memiliki batas pengeluaran bulanan. Permintaan API memeriksa anggota → tim → kredit org secara berurutan.

Kelola organisasi Anda
Untuk menambah tim, mengundang anggota, atau mengubah pengaturan, buka Pengaturan dan pilih organisasi

Sistem Anggaran Tiga Tingkat

Pada setiap permintaan API, tiga lapisan anggaran diperiksa secara berurutan. Melebihi lapisan mana pun mengembalikan HTTP 429:

  1. Anggaran bulanan anggota (OrgMember.monthlyBudget)
  2. Anggaran bulanan tim (Team.monthlyBudget)
  3. Saldo kredit organisasi (Organization.credits)

Laporan Penggunaan

Halaman Laporan di portal organisasi menyediakan analitik pengeluaran bulanan di empat dimensi:

  • Ikhtisar: total pengeluaran, tingkat margin, grafik tren harian
  • Per Tim: pengeluaran per tim, bagian %, rincian model, pemanfaatan anggaran
  • Per Model: pengeluaran per model, harga rata-rata ($/1M token)
  • Per Anggota: pengeluaran per anggota — hanya org_admin

Semua tampilan mendukung ekspor CSV dengan prefiks BOM untuk kompatibilitas Excel langsung.

Buat & Kelola Organisasi

  1. Buka Pengaturan → Organisasi → Buat Organisasi Baru
  2. Buat Tim di portal organisasi (opsional: kode pusat biaya dan anggaran bulanan)
  3. Undang anggota melalui email, tetapkan peran dan Tim
  4. Terbitkan kunci API untuk anggota — penggunaan otomatis ditandai ke Tim / anggota yang benar
  5. Lihat halaman Laporan untuk pengeluaran bulanan dirinci berdasarkan Tim, Model, atau Anggota
  6. Lihat halaman Laporan untuk pembelanjaan bulanan yang dikelompokkan berdasarkan Tim, Model, atau Anggota

Peran Anggota

org_adminKontrol penuh: anggota, tim, tagihan, pengaturan
billing_viewerAkses baca-saja ke laporan keuangan (tidak dapat melihat detail per anggota)
tim_adminKelola anggota dan anggaran dalam tim mereka sendiri
anggotaGunakan API, tunduk pada batas anggaran tim dan organisasi

Apa lagi yang bisa dikelola organisasi?

Di luar anggota dan tim, area manajemen organisasi menyediakan:

  • API keys and model restrictions
  • Content filtering before text reaches a model
  • Allowed Models by organization, team, member, or key
  • Monthly budgets and spend emergency brakes
  • Reports and billing
  • Change logs and security logs

Pemfilteran konten

Organization-owned rules inspect text before it reaches a model. An org_admin can enable, edit, and test them in Settings.

  • block: reject with HTTP 403
  • redact: replace matches with [REDACTED]
  • flag: send unchanged and record an audit event
  • Built-in sensitive-data and prompt-injection templates plus custom keyword or regex rules
  • Up to 100 safety-checked rules with a test preview
Saat ini terbatas pada input teks
Images, audio, video, some structured or multimodal content, and model output are not inspected.

API Manajemen (v1)

Endpoint /v1/orgs/ menerima kunci manajemen Bearer (sk-bl-...) dan cookie sesi, memungkinkan manajemen organisasi server-ke-server tanpa sesi browser.

Autentikasi
Semua endpoint /v1/orgs/ memerlukan peran org_admin. Kirim Authorization: Bearer sk-bl-<key> atau cookie sesi. Kunci manajemen dapat dibuat dari Pengaturan → Kunci API.

Organisasi

GET/v1/orgs

Menampilkan daftar semua organisasi tempat caller tergabung, beserta role dan joinedAt.

GET/v1/orgs/:orgId

Mengambil detail org termasuk jumlah team dan member.

curl https://api.bazaarlink.ai/v1/orgs \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

Tim

GET/v1/orgs/:orgId/teams

Menampilkan daftar team beserta jumlah member, diurutkan berdasarkan name.

POST/v1/orgs/:orgId/teams
namewajib
string
Nama tampilan team (harus unik dalam org)
costCenterCode
string
Kode cost center akuntansi
monthlyBudget
number | null
Batas pengeluaran bulanan team dalam USD
PATCH/v1/orgs/:orgId/teams/:teamId

Update parsial — sertakan hanya field yang ingin diubah.

DELETE/v1/orgs/:orgId/teams/:teamId
# Create a team
curl https://api.bazaarlink.ai/v1/orgs/{orgId}/teams \
  -X POST \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Engineering", "costCenterCode": "ENG-001", "monthlyBudget": 500}'

Anggota

GET/v1/orgs/:orgId/members

Menampilkan daftar semua member dengan informasi user (id/name/email) dan team yang ter-nested.

POST/v1/orgs/:orgId/members
emailwajib
string
Email user BazaarLink yang sudah terdaftar
role
string
org_admin | penagihan_viewer | tim_admin | anggota (default: anggota)
teamId
string
Tugaskan ke sebuah team (wajib jika role adalah team_admin)
monthlyBudget
number | null
Batas pengeluaran bulanan per-member dalam USD

404 jika alamat email tidak memiliki akun BazaarLink. 409 jika sudah menjadi anggota. Peran default: member.

PATCH/v1/orgs/:orgId/members/:memberId

Update parsial untuk role, teamId, atau monthlyBudget.

DELETE/v1/orgs/:orgId/members/:memberId

Mengembalikan 400 jika target adalah org_admin terakhir.

# Add a member
curl https://api.bazaarlink.ai/v1/orgs/{orgId}/members \
  -X POST \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "alice@example.com", "role": "member", "monthlyBudget": 50}'

# Remove a member
curl https://api.bazaarlink.ai/v1/orgs/{orgId}/members/{memberId} \
  -X DELETE \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

API Laporan

Kueri data pengeluaran bulanan secara programatik. Dapat diakses oleh org_admin dan billing_viewer. Menerima sesi web dan kunci manajemen Bearer.

Parameter kueri: year (default tahun ini), month (default bulan ini, 1–12).

Titik Akhir
Deskripsi
GET /api/orgs/:orgId/reports/overviewTotal pengeluaran, margin rate, tren harian
GET /api/orgs/:orgId/reports/by-teamPengeluaran per-team, share %, breakdown model, utilisasi budget
GET /api/orgs/:orgId/reports/by-modelPengeluaran per-model, harga rata-rata ($/1M tokens)
GET /api/orgs/:orgId/reports/by-memberPengeluaran per-member — hanya org_admin
GET /api/orgs/:orgId/reports/exportDownload CSV; tambahkan ?view=overview|by-team|by-model|by-member
# Monthly overview via management key
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/overview?year=2026&month=3" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

# By-team breakdown
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/by-team?year=2026&month=3" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY"

# Export CSV (downloads file)
curl "https://bazaarlink.ai/api/orgs/{orgId}/reports/export?year=2026&month=3&view=by-team" \
  -H "Authorization: Bearer sk-bl-YOUR_MANAGEMENT_KEY" \
  -o report.csv

Referensi Respons Error

401API key tidak valid atau dicabut
403Penolakan RBAC (role tidak cukup) atau model tidak ada di whitelist Allowed Models
402Salah satu dari tiga lapis budget terlampaui; body respons berisi scope (member / team / org) dan reset time
429Spend Circuit Breaker terpicu; header Retry-After menunjukkan waktu pemulihan dalam detik
503Platform menggunakan rem darurat atau pemadaman layanan sementara

AModel yang Diizinkan (Daftar Putih)

Batasi model mana yang dapat dipanggil oleh organisasi, tim, atau anggota individu Anda. Berguna untuk memblokir model yang mahal atau belum tervalidasi, menegakkan standar model, atau membatasi tim ke satu provider tertentu.

Cara kerjanya

  • Tiga lapis independen — Organisasi, Tim, Anggota — masing-masing memiliki daftarnya sendiri (String[] di database).
  • Ketika ketiga lapis kosong, semua model diizinkan (perilaku default).
  • Ketika satu atau lebih lapis tidak kosong, daftar efektif adalah irisan dari lapis-lapis yang tidak kosong — sebuah model harus diizinkan di setiap lapis yang dibatasi agar lolos.
  • Perubahan berlaku dalam beberapa detik (cache in-memory 60s + Redis 5min; keduanya dibersihkan saat update).

Format pola

  • Pencocokan tepat — mis. openai/gpt-4o (hanya model spesifik ini).
  • Wildcard provider — mis. openai/* (semua model di bawah prefix openai/).
  • Hanya huruf kecil. Maks 200 entri per daftar, 100 karakter per entri.

Tempat mengelola

Org Portal → Allowed Models. org_admin dapat mengedit daftar org / team / member; team_admin dapat mengedit timnya sendiri dan anggota di dalamnya.

Respons error saat diblokir

Panggilan ke model yang tidak diizinkan mengembalikan HTTP 403 dengan body berikut:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": {
    "message": "Model is not allowed for this account",
    "code": "model_not_allowed"
  }
}

Manajemen API

Semua endpoint menerima Web Session atau Bearer Management Key (sk-bl-...). PATCH menggantikan seluruh daftar; kirim [] untuk mengosongkan.

# Org-level list
GET    /api/orgs/:orgId/allowed-models
PATCH  /api/orgs/:orgId/allowed-models

# Team-level list
GET    /api/orgs/:orgId/teams/:teamId/allowed-models
PATCH  /api/orgs/:orgId/teams/:teamId/allowed-models

# Member-level list
GET    /api/orgs/:orgId/members/:memberId/allowed-models
PATCH  /api/orgs/:orgId/members/:memberId/allowed-models

# Example: restrict an org to OpenAI + a specific Anthropic model
curl -X PATCH https://bazaarlink.ai/api/orgs/$ORG_ID/allowed-models \
  -H "Authorization: Bearer sk-bl-..." \
  -H "Content-Type: application/json" \
  -d '{"allowedModels": ["openai/*", "anthropic/claude-sonnet-4.6"]}'

Pemutus Sirkuit (Saklar Pemutus Pembelanjaan)

Batas pengeluaran dua jendela yang memblokir permintaan lanjutan ketika biaya upstream melonjak. Dirancang untuk membendung skrip yang lepas kendali, infinite loop, atau penyalahgunaan kunci yang dicuri sebelum mereka memakan biaya nyata.

Cara kerjanya

  • Dua jendela tetap dilacak di Redis per scope: biaya upstream 1 menit dan 1 jam (USD).
  • Jika pengeluaran salah satu jendela mencapai threshold, semua permintaan berikutnya pada scope tersebut ditolak sampai jendela direset.
  • Default: $5 / menit, $20 / jam. Nonaktif secara default — perlu diaktifkan sendiri.
  • Counter berada di Redis dengan TTL — pemulihan otomatis, tidak perlu reset manual untuk trip pada org/team/member.

Scope (member menimpa team menimpa org)

Setiap lapis dapat menetapkan thresholdnya sendiri. Urutan resolusi adalah member → team → org → default platform — nilai non-null pertama menang per field (cbEnabled, cbMinuteUsd, cbHourlyUsd).

  • Level Org — berlaku untuk semua kunci di bawah organisasi. Atur di Org Portal → Circuit Breaker.
  • Level Team — berlaku untuk semua kunci yang ditandai ke tim tersebut. Menimpa org untuk kunci-kunci tersebut.
  • Level Member — berlaku hanya untuk kunci yang ditandai ke anggota tersebut. Menimpa team dan org.

Perilaku trip

Saat trip, permintaan gagal cepat (tidak ada panggilan upstream yang dilakukan). Responsnya adalah HTTP 429 dengan body berikut:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{
  "error": {
    "message": "Spend circuit breaker tripped at member scope (minute window: $5.2341 ≥ $5.00). Try again later or contact your organization owner."
  }
}
Global vs cakupan
Sebuah circuit breaker global di seluruh platform yang terpisah (dikendalikan operator, tidak terlihat di org portal) mengembalikan HTTP 503 dengan header Retry-After. Operator menetapkannya untuk melindungi platform dari penyalahgunaan multi-tenant — tidak dapat di-override dari pengaturan org Anda.

Alog Audit

Setiap event trip dan setiap perubahan konfigurasi dicatat:

  • Event trip — action org.cb.tripped / team.cb.tripped / org_member.cb.tripped. Dideduplikasi menjadi satu entri per scope+window per jam, sehingga trip yang berkelanjutan tidak membanjiri log.
  • Perubahan konfigurasi — action org.cb.update / team.cb.update / org_member.cb.update. Mencatat nilai before/after beserta aktor.

Manajemen API

Org admin dapat membaca dan memperbarui pengaturan via API. Semua endpoint menerima Web Session atau Bearer Management Key (sk-bl-...). Kirim subset field apa pun di body PATCH; null mengosongkan field dan kembali ke lapis induk.

# Org-level config
GET    /api/orgs/:orgId/circuit-breaker
PATCH  /api/orgs/:orgId/circuit-breaker

# Team-level config
GET    /api/orgs/:orgId/teams/:teamId/circuit-breaker
PATCH  /api/orgs/:orgId/teams/:teamId/circuit-breaker

# Member-level config
GET    /api/orgs/:orgId/members/:memberId/circuit-breaker
PATCH  /api/orgs/:orgId/members/:memberId/circuit-breaker

# Example: tighten the org-level cap to $2/min, $10/hr
curl -X PATCH https://bazaarlink.ai/api/orgs/$ORG_ID/circuit-breaker \
  -H "Authorization: Bearer sk-bl-..." \
  -H "Content-Type: application/json" \
  -d '{"cbMinuteUsd": 2, "cbHourlyUsd": 10, "cbEnabled": true}'

# GET response (org scope)
{
  "settings":         { "cbEnabled": true, "cbMinuteUsd": 2,  "cbHourlyUsd": 10  },
  "resolvedSettings": { "cbEnabled": true, "cbMinuteUsd": 2,  "cbHourlyUsd": 10  },
  "liveSpend":        { "minuteSpend": 0.4123, "hourSpend": 3.8721 }
}

Rotasi Kunci API

Mengganti kunci API secara berkala merupakan praktik keamanan. Buat kunci baru, perbarui dan uji integrasi Anda, lalu cabut kunci lama. Proses ini tidak menjamin tanpa downtime.

Catatan
Kunci API dapat dicabut kapan saja dari dasbor atau melalui API manajemen. Pencabutan bersifat segera — semua permintaan menggunakan kunci tersebut akan langsung gagal.

Langkah Rotasi

  1. Buat kunci API baru
  2. Perbarui aplikasi atau variabel lingkungan Anda untuk menggunakan kunci baru
  3. Verifikasi kunci baru berfungsi dengan benar
  4. Nonaktifkan atau hapus kunci lama
# Key CRUD via Bearer auth requires a MANAGEMENT key (keyType: "management").
# Standard keys get 403 on /v1/keys — create a management key first,
# or rotate keys from the dashboard UI instead.

# Step 1: Create new key (management key auth)
POST https://api.bazaarlink.ai/v1/keys
Authorization: Bearer $BL_MANAGEMENT_KEY
{"name": "Production v2"}
# → saves new key: sk-bl-NEW_KEY_VALUE

# Step 2: Update your application
# export BAZAARLINK_API_KEY=sk-bl-NEW_KEY_VALUE

# Step 3: Verify new key works
curl https://api.bazaarlink.ai/v1/models \
  -H "Authorization: Bearer sk-bl-NEW_KEY_VALUE"

# Step 4: Revoke old key (management key auth again)
DELETE https://api.bazaarlink.ai/v1/keys/:old_key_id
Authorization: Bearer $BL_MANAGEMENT_KEY

Ekspor Aktivitas

Unduh riwayat penggunaan API lengkap Anda sebagai CSV untuk audit keuangan, analisis biaya, atau pelaporan kepatuhan.

Ekspor CSV

Masuk dan buka halaman Log. Klik tombol Ekspor CSV di sudut kanan atas untuk mengunduh riwayat lengkap Anda sebagai file CSV. Tidak perlu panggilan API.

Kolom CSV

Column
Description
dateISO 8601 timestamp (UTC)
modelModel ID (e.g. openai/gpt-4o)
prompt_tokensInput token count
completion_tokensOutput token count
total_tokensTotal tokens (prompt + completion)
reasoning_tokensReasoning tokens (o-series / thinking models)
cached_tokensPrompt cache hit tokens
cost_ntdJumlah tagihan dalam dolar Taiwan
duration_msEnd-to-end latency in milliseconds
finish_reasonstop / length / content_filter / error
statusKode status respons BazaarLink
app_nameX-Title header value (app attribution)

API Penggunaan JSON

Untuk akses programatik, kueri statistik teragregasi yang dikelompokkan berdasarkan periode, model, atau kunci:

# Query usage data (grouped / aggregated)
GET https://api.bazaarlink.ai/v1/usage
Authorization: Bearer sk-bl-YOUR_KEY

# With period filtering (day | week | month | year)
GET https://api.bazaarlink.ai/v1/usage?period=month

# Response
{
  "period": "month",
  "since": "2025-01-01T00:00:00.000Z",
  "credits": 10.5000,
  "totals": {
    "spend": 0.1812,
    "requests": 309,
    "tokens": 161200,
    "promptTokens": 95000,
    "completionTokens": 66200
  },
  "byModel": [{ "model": "openai/gpt-4o", "spend": 0.0028, "tokens": 1200, "requests": 5 }],
  "byKey":   [{ "keyName": "My Agent", "spend": 0.0028, "tokens": 1200, "requests": 5 }],
  "byApp":   [{ "appName": "MyApp", "spend": 0.0015, "tokens": 600, "requests": 3 }],
  "timeSeries": [{ "date": "2025-01-15", "model": "openai/gpt-4o", "cost": 0.0012, "tokens": 500, "requests": 2 }]
}

Akuntansi Penggunaan

Kueri statistik penggunaan terperinci melalui API, termasuk konsumsi token, analisis biaya, dan riwayat permintaan.

Catatan
Data penggunaan ditagih dalam USD. Catatan permintaan individual tersedia di halaman Log atau melalui ekspor CSV. Statistik teragregasi (berdasarkan periode, model, atau kunci) tersedia melalui endpoint `/v1/usage` dengan autentikasi Bearer token.

Referensi Field Respons

FieldTypeDescription
modelstringModel ID used (e.g., openai/gpt-4o)
providerstringNilai tetap BazaarLink: bazaarlink
prompt_tokensnumberInput tokens consumed
completion_tokensnumberOutput tokens generated
total_tokensnumberTotal tokens (prompt + completion)
reasoning_tokensnumberReasoning tokens (for thinking models)
cached_tokensnumberPrompt tokens served from cache
costnumberJumlah USD yang ditagihkan kepada pelanggan untuk permintaan ini
duration_msnumberEnd-to-end latency in milliseconds
throughputnumberGeneration speed in tokens/sec
finish_reasonstringstop | length | content_filter | error
statusnumberKode status respons BazaarLink
app_namestring | nullApplication name (X-Title header)
key_namestringAPI key name used for the request
import httpx

# Aggregated stats (Bearer token — period: day | week | month | year)
response = httpx.get(
    "https://api.bazaarlink.ai/v1/usage",
    headers={"Authorization": "Bearer sk-bl-YOUR_KEY"},
    params={"period": "month"},
)

data = response.json()
totals = data["totals"]
print("This month: US$%.4f  (%d requests)" % (totals["spend"], totals["requests"]))

# Cost breakdown by model
for m in data["byModel"]:
    print("  %s: US$%.4f  (%d reqs, %d tokens)" % (m["model"], m["spend"], m["requests"], m["tokens"]))

Laporkan Masukan

Bantu kami meningkatkan BazaarLink dengan melaporkan masalah, bug, atau saran. Kami secara aktif memantau semua saluran umpan balik.

Cara Melaporkan

Saluran
Terbaik Untuk
Waktu Respons
Halaman KontakUmpan balik umum, permintaan fitur1-2 hari kerja
EmailLaporan bug, masalah teknisDalam 24 jam
Header Respons APIError dan metrik yang dilaporkan otomatisOtomatis

Yang Harus Disertakan

  • ID Permintaan (dari field id respons)
  • Model yang digunakan dan parameter yang dikirim
  • Perilaku yang diharapkan vs aktual
  • Stempel waktu dan frekuensi masalah
  • Pesan error atau kode status HTTP

Kunjungi halaman Kontak kami untuk mengirim umpan balik.

FAQ

Apa perbedaan BazaarLink dengan memanggil OpenAI secara langsung?
BazaarLink menyediakan tagihan USD dengan harga kutipan NTD, faktur terpadu, dukungan Mandarin, dan satu API untuk semua model utama. Anda dapat mengakses OpenAI, Anthropic, Google, dan lainnya dengan kode yang sama.
Apakah saya perlu mengubah kode yang ada?
Cukup ubah base URL dan kunci API. Semua pengaturan lainnya (kecuali ID model) tetap tidak berubah.
Apakah BazaarLink menyimpan pesan saya?
Untuk permintaan biasa yang berhasil, kami tidak menyimpan konten pesan; kami hanya menyimpan catatan penggunaan yang diperlukan untuk tagihan dan operasional (seperti model, jumlah token, waktu, dan biaya). Permintaan yang gagal, mekanisme keamanan konten, tugas video dan lainnya, serta fitur yang Anda aktifkan adalah pengecualian yang dijelaskan dalam Kebijakan Privasi; mode kunci ZDR menyediakan zero data retention yang lebih ketat.
Bagaimana cara mendapatkan faktur terpadu (統一發票)?
Faktur terpadu diterbitkan secara otomatis pada akhir bulan untuk paket Business ke atas. Hubungi dukungan untuk penerbitan segera.
Metode pembayaran apa yang didukung?
Semua kartu kredit utama diterima (Visa, Mastercard, American Express).
Fitur OpenAI SDK mana yang didukung?
Chat completions, streaming, tool calling, output terstruktur (response_format), dan assistant prefill semuanya berfungsi. Fitur diteruskan ke penyedia upstream.
Bisakah saya menggunakan BazaarLink dengan framework agen seperti LangChain atau CrewAI?
Ya! Framework apa pun yang mendukung OpenAI API berfungsi dengan BazaarLink. Cukup atur base URL dan gunakan kunci API BazaarLink Anda. Lihat bagian Penggunaan Agentik untuk contoh.
Support
Support
Hi! How can we help you?
Send a message and we'll get back to you soon.