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.
  • • Kartu kredit: berlaku biaya tetap tambahan sebesar US$0.60; tanda terima dikeluarkan.
  • • saluran TWD: 5% Taiwan VAT ditambahkan dan faktur terpadu elektronik Taiwan diterbitkan.
  • • Transfer bank: untuk isi ulang skala besar atau perusahaan, hubungi kami untuk mengatur transfer kawat dan pembuatan faktur khusus.
  • Faktur: faktur terpadu elektronik didukung untuk alur kerja pengeluaran Taiwan; perusahaan yang membutuhkan pengadaan atau penagihan bulanan dapat mengatur persyaratan perusahaan (Net-30, dapat dinegosiasikan).
Contoh
Untuk isi ulang US$10.00: saluran TWD = $10.00 + biaya 10% US$1.00 + 5% VAT US$0.55 = US$11.55 (faktur terpadu diterbitkan); Kartu kredit = $10.00 + biaya US$1.00+ biaya tetap US$0.60 = US$11.60. Setelah isi ulang, saldo US$10.00 Anda dibelanjakan pada harga resmi tanpa markup lebih lanjut.

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

Jika permintaan selesai normal dan penyedia mengembalikan usage yang valid, BazaarLink akan menagih penggunaan tersebut. Jangan menentukan gratis hanya dari token output: respons dengan 0 token output masih dapat ditagih untuk token input atau biaya upstream valid yang dilaporkan. Periksa usage.cost atau catatan Aktivitas untuk tagihan 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

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

Base URL

https://bazaarlink.ai/api/v1

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://bazaarlink.ai/api/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-.
Format ID Model — gunakan format provider/model-name
Selalu gunakan format lengkap provider/model (mis. openai/gpt-4.1). Keluarga umum (gpt-*, claude-*) otomatis diberi prefiks di setiap endpoint, dan chat/completions juga menyelesaikan nama polos apa pun yang tidak ambigu dari katalog — tetapi nama yang tidak dapat diselesaikan mengembalikan error 400, jadi bentuk lengkap adalah satu-satunya yang dijamin.
✓ openai/gpt-4o   anthropic/claude-sonnet-4.6   google/gemini-2.5-flash
✗ gpt-4.1   claude-sonnet-4.6   gemini-2.5-flash

Bawa Kunci Sendiri (BYOK)

Kaitkan kunci API penyedia upstream milik Anda sendiri (antarmuka kompatibel OpenAI atau Anthropic) ke akun pribadi atau organisasi — permintaan yang memenuhi syarat akan langsung ke upstream lewat kunci Anda, dengan mode fallback seamless atau strict. Kunci pribadi diatur di tab BYOK pada halaman kunci; organisasi mengelolanya 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 →

Migrasi dari OpenRouter

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

  1. Basis URL: https://openrouter.ai/api/v1 → https://bazaarlink.ai/api/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 /api/v1/models
  4. Fallback models[], preferensi routing penyedia, 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://bazaarlink.ai/api/v1",
+     api_key="sk-bl-...",
  )
Note
Penagihan dalam USD dengan e-faktur Taiwan tersedia. Untuk fitur khusus OpenRouter (mis. pengurutan penyedia :nitro), lihat bagian Varian Model dan Pemilihan Penyedia di halaman Referensi API untuk perilaku yang setara.

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. Ketersediaan Tinggi

Failover otomatis berarti jika penyedia mengalami gangguan, permintaan Anda dialihkan dengan mulus. Tanpa perubahan kode, tanpa downtime.

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-5.3-codexanthropic/claude-opus-4.6google/gemini-2.5-flash-lite+142 lainnya
File / PDFDokumen via data URI base64 (`data:application/pdf;base64,...`)openai/gpt-5.3-codexanthropic/claude-opus-4.6google/gemini-2.5-flash-lite+70 lainnya
AudioRaw base64 — tanpa dukungan URL. Memerlukan field `format`google/gemini-2.5-flash-litexiaomi/mimo-v2.5google/gemini-3.1-pro-preview+13 lainnya
VideoURL (CDN) atau data URI base64google/gemini-2.5-flash-liteqwen/qwen3.5-plus-02-15minimax/minimax-m3+37 lainnya

Contoh:

# Image — URL or base64 data URI
curl https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.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://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.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://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.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://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.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://bazaarlink.ai/api/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

Setiap response yang sukses menyertakan header rate limit untuk pelacakan di sisi client:

X-RateLimit-Limit: 200        # Max requests per minute for your tier
X-RateLimit-Remaining: 198    # Remaining requests in current window
X-RateLimit-Reset: 1740000060 # Unix timestamp when the window resets
X-Request-Id: chatcmpl-abc123 # Unique request ID for debugging

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.

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

Pembuatan Gambar

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

curl -N https://bazaarlink.ai/api/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://bazaarlink.ai/api/v1/videos \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"alibaba/wan2.7-t2v","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-2.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 →

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://bazaarlink.ai/api/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://bazaarlink.ai/api/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://bazaarlink.ai/api/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://bazaarlink.ai/api/v1/keys/:id
Authorization: Bearer sk-bl-YOUR_MGMT_KEY

# Returns 204 No Content on success

Kueri Saldo

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

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

Kueri Penggunaan

GET https://bazaarlink.ai/api/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://bazaarlink.ai/api/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

Endpoint inferensi model mengembalikan amplop kesalahan yang kompatibel dengan OpenAI. Kolom type dapat berbeda atau tidak disertakan; gunakan status HTTP dan error.code untuk logika program, bukan mengurai pesan.

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

HTTP status dan kode kesalahan

Before streaming, the HTTP status identifies the broad failure class. error.code is either that number or a stable string for a specific remedy. Prefer the string code when present, otherwise use the HTTP status.

Kode
Nama
Deskripsi
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
500Kesalahan ServerError internal BazaarLink
502Gerbang BurukSemua penyedia upstream gagal; failover telah dicoba
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
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.

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
upstream_unavailable502/503

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 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.

Compatibility note: rate-limit and emergency-brake paths currently emit numeric error.code values. Use HTTP status, Retry-After, and the documented response message.

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://bazaarlink.ai/api/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-4.1",
            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 di tengah jalan, BazaarLink mengirim event SSE terakhir dengan objek error tingkat atas, diikuti data: [DONE]. Chunk yang diteruskan apa adanya dari beberapa upstream mungkin justru membawa error pada choice (choices[0].finish_reason === "error") — tangani keduanya.

// If the stream fails mid-flight, BazaarLink emits a final SSE event
// with a top-level "error" object, followed by data: [DONE]
data: {"error":{"message":"Upstream stream interrupted. The response is incomplete.","type":"upstream_error","code":502}}

data: [DONE]

// Chunks relayed verbatim from some upstreams may instead carry the error
// inline on the choice: choices[0].finish_reason === "error" with an
// "error" object ({ code, message }) on the choice — handle both shapes.
// 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://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1",
    "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-4.1",
        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-4.1",
    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-4.1",
        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://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4.1",
    "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://bazaarlink.ai/api/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

Otomatis transformasi pesan agar sesuai dengan batas konteks model. Ketika pesan Anda melebihi jendela konteks model, transformasi secara cerdas memadatkan percakapan dengan menghapus pesan dari tengah.

Auto
Model dengan jendela konteks 8.192 token atau kurang menerapkan middle-out secara otomatis secara default. Untuk keluar, kirim `transforms: []`. Untuk mengaktifkan pada model mana pun, kirim `transforms: ["middle-out"]`.

Penggunaan

// Enable middle-out on any model
{
  "model": "openai/gpt-4.1",
  "transforms": ["middle-out"],
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    ... // long conversation — middle will be trimmed to fit context
  ]
}

// Disable auto-trimming for small-context models
{ "transforms": [] }

Tipe Transformasi

Transformasi
Deskripsi
middle-outMenghapus pesan dari tengah lebih dulu, menjaga awal (prompt sistem, konteks) dan akhir (pesan terbaru)

Perilaku Default

Model dengan konteks <=8k memiliki middle-out yang diaktifkan secara otomatis. Untuk model konteks lebih besar, aktifkan secara eksplisit. Model Anthropic Claude juga otomatis memberlakukan batas 1.000 pesan terlepas dari pengaturan transforms.

Tanpa Penyimpanan Data

BazaarLink tidak menyimpan konten pesan Anda secara default. Halaman ini menjelaskan bagaimana data Anda ditangani. Cocok untuk aplikasi yang memproses data sensitif.

Penanganan Data Saat Ini

  • Konten pesan: tidak disimpan secara default, dihapus dari memori setelah pemrosesan
  • Metadata tagihan: jumlah token, stempel waktu, ID model
  • Log penggunaan: hanya statistik permintaan, 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-4.1",
    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/o3-mini",
  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/o1, o3, o4-minireasoning_effort: "low" | "medium" | "high"medium
deepseek/deepseek-r1Selalu aktif (tidak dapat dinonaktifkan)
# Qwen3: explicitly enable thinking mode
response = client.chat.completions.create(
    model="qwen/qwen3-32b",
    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 o3 — specify effort level
const response2 = await client.chat.completions.create({
  model: "openai/o3",
  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 },
});
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 /api/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
  • Gunakan varian :nitro untuk memilih penyedia throughput tinggi
  • Pilih model lebih kecil (flash/mini/haiku) untuk skenario sensitif latensi
  • Gunakan provider.sort: "latency" untuk otomatis memilih penyedia latensi terendah
  • 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-2.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://bazaarlink.ai/api/v1/generation?id=chatcmpl-abc123" \
  -H "Authorization: Bearer $BAZAARLINK_API_KEY"

# Response
{
  "data": {
    "id": "chatcmpl-abc123",
    "model": "google/gemini-2.5-flash",
    "duration_ms": 842,
    "throughput": 61.2,
    "usage": { "prompt_tokens": 12, "completion_tokens": 48, "total_tokens": 60 }
  }
}
# Use provider.sort for automatic latency optimization
response = client.chat.completions.create(
    model="openai/gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    extra_body={
        "provider": {
            "sort": "latency",  # Always pick lowest-latency provider
        }
    },
)

Optimasi Uptime

BazaarLink memaksimalkan ketersediaan API melalui beberapa lapisan: failover otomatis, circuit breaker, dan pemantauan kesehatan penyedia.

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
  • Failover otomatis: beralih mulus ke penyedia cadangan — tanpa perubahan kode
  • Pemantauan kesehatan penyedia: terus melacak tingkat error dan latensi per penyedia
  • Logika percobaan ulang: error sementara (5xx) otomatis dicoba ulang

Pemutus Sirkuit

# BazaarLink handles failover automatically — no code changes needed.
# Configure fallback models for maximum resilience:

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

# Check if failover was used (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://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
URL lama https://bazaarlink.ai/v1/cursor masih bekerja — sekarang merupakan re-export tipis dari /v1/chat/completions. Setup baru sebaiknya menggunakan /v1 langsung.

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-2.5-flashgoogle/gemini-2.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 /api/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 Anthropic 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 OpenAI saat merutekan ke penyedia non-OpenAI — parallel_tool_calls, logprobs, top_logprobs, logit_bias, service_tier, user dihapus sebelum diteruskan (jika tidak, Anthropic 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 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-v3.2

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://bazaarlink.ai/api/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
enabled
standarddeepseek/deepseek-v4-flash
enabled
complexminimax/minimax-m2.5
enabled
reasoningminimax/minimax-m2.5
enabled
codingdeepseek/deepseek-v4-flash
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
enabled
searchminimax/minimax-m2.5
enabled
socialdeepseek/deepseek-v4-flash
enabled
emaildeepseek/deepseek-v4-flash
enabled
calendardeepseek/deepseek-v4-flash
enabled
tradingdeepseek/deepseek-v4-flash
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
Begitu kuota habis, permintaan otomatis berlanjut dengan harga berbayar model tersebut selama akun punya saldo — layanan tidak terputus dan ditagih persis seperti panggilan berbayar biasa. Jika Anda lebih memilih gagal daripada ditagih, kirim header X-Free-Fallback: false atau matikan fallback otomatis di pengaturan kunci; Anda akan menerima 429. Tanpa saldo, permintaan melebihi kuota selalu mengembalikan 429.
X-Auto-Resolved-Model
Model aktual yang dipilih dikembalikan dalam header X-Auto-Resolved-Model dan field model pada respons.

Varian Model

Tambahkan sufiks ke ID model mana pun untuk mengubah perilaku routing. BazaarLink mendukung 7 tipe varian.

Tipe Varian
Ada dua kategori varian: ID Model Independen (model bersufiks adalah endpoint berbeda) dan Pintasan Routing (sufiks mengubah cara BazaarLink memilih penyedia tanpa mengubah model itu sendiri).

ID Model Independen

Varian ini ada sebagai model terpisah dengan harga dan kemampuan tersendiri. BazaarLink mencoba ID model lengkap (dengan sufiks) lebih dulu, lalu fallback ke model dasar.

:free
:extended
:thinking
:exacto

Pintasan Routing

Sufiks ini memodifikasi pemilihan penyedia tanpa mengubah identitas model. Sufiks dihapus sebelum mencocokkan route.

:floor   # lowest listed input price first
:nitro   # throughput-oriented shortcut
:online  # enable web-search routing

Perilaku Multi-Penyedia

Untuk upstream yang mendukung varian, sufiks diteruskan apa adanya. Untuk penyedia langsung (mis. OpenAI langsung, Fireworks), sufiks dihapus dan BazaarLink menangani routing secara lokal.

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 /api/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.

deepseek/deepseek-v4-flash

Batas kuota gratis

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

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.

Setelah kuota gratis habis

Begitu kuota habis, permintaan otomatis berlanjut dengan harga berbayar model tersebut selama akun punya saldo — layanan tidak terputus dan ditagih persis seperti panggilan berbayar biasa. Jika Anda lebih memilih gagal daripada ditagih, kirim header X-Free-Fallback: false atau matikan fallback otomatis di pengaturan kunci; Anda akan menerima 429. Tanpa saldo, permintaan melebihi kuota selalu mengembalikan 429.

# 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, billing, change logs, and security logs
  • Education sessions and quotas for eligible organizations
  • Rencana institusi: organisasi pendidikan juga dapat mengelola sesi dan kuota siswa

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 /api/v1/orgs/ menerima kunci manajemen Bearer (sk-bl-...) dan cookie sesi, memungkinkan manajemen organisasi server-ke-server tanpa sesi browser.

Autentikasi
Semua endpoint /api/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/api/v1/orgs

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

GET/api/v1/orgs/:orgId

Mengambil detail org termasuk jumlah team dan member.

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

Tim

GET/api/v1/orgs/:orgId/teams

Menampilkan daftar team beserta jumlah member, diurutkan berdasarkan name.

POST/api/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/api/v1/orgs/:orgId/teams/:teamId

Update parsial — sertakan hanya field yang ingin diubah.

DELETE/api/v1/orgs/:orgId/teams/:teamId
# Create a team
curl https://bazaarlink.ai/api/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/api/v1/orgs/:orgId/members

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

POST/api/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/api/v1/orgs/:orgId/members/:memberId

Update parsial untuk role, teamId, atau monthlyBudget.

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

Mengembalikan 400 jika target adalah org_admin terakhir.

# Add a member
curl https://bazaarlink.ai/api/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://bazaarlink.ai/api/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, aktif secara default.
  • 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

Merotasi kunci API secara teratur adalah praktik keamanan terbaik. BazaarLink mendukung rotasi kunci tanpa downtime — buat kunci baru lebih dulu, lalu migrasi, lalu cabut yang lama.

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 /api/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://bazaarlink.ai/api/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://bazaarlink.ai/api/v1/models \
  -H "Authorization: Bearer sk-bl-NEW_KEY_VALUE"

# Step 4: Revoke old key (management key auth again)
DELETE https://bazaarlink.ai/api/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)
providerUpstream provider name
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_usdCost in USD credits
duration_msEnd-to-end latency in milliseconds
finish_reasonstop / length / content_filter / error
statusHTTP status code from upstream
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://bazaarlink.ai/api/v1/usage
Authorization: Bearer sk-bl-YOUR_KEY

# With period filtering (day | week | month | year)
GET https://bazaarlink.ai/api/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 `/api/v1/usage` dengan autentikasi Bearer token.

Referensi Field Respons

FieldTypeDescription
modelstringModel ID used (e.g., openai/gpt-4o)
providerstringUpstream provider name
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
costnumberTotal cost in USD credits
duration_msnumberEnd-to-end latency in milliseconds
throughputnumberGeneration speed in tokens/sec
finish_reasonstringstop | length | content_filter | error
statusnumberHTTP status code from upstream
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://bazaarlink.ai/api/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"]))

Rencana Institusi

Institution Plan memungkinkan institusi mana pun (sekolah, perusahaan, konferensi, pemerintah, dll.) menerbitkan token sesi berumur pendek untuk anggotanya dari satu kunci tingkat organisasi. Anggota tidak perlu membuat akun platform. Organisasi mengontrol anggota mana yang dapat meminta token berdasarkan domain email (misalnya nthu.edu.tw); semua penggunaan ditagih ke akun organisasi. Halaman ini menggunakan skenario pendidikan sebagai contoh — mekanisme yang sama bekerja untuk institusi mana pun yang membutuhkan akses sementara jangka pendek untuk banyak pengguna.

Untuk siapa ini
Sekolah dan institusi pendidikan yang ingin memberikan satu kelas penuh akses ke AI API tanpa membuat akun siswa individu dan tanpa menyerahkan kunci API berumur panjang kepada anak di bawah umur.

Ikhtisar arsitektur

  • Kunci InstitusiDiawali dengan sk-edu-. Dibuat oleh org_admin di halaman kunci organisasi. Tidak dapat digunakan langsung sebagai Bearer token untuk memanggil API — panggilan langsung akan mengembalikan 403.
  • Token Sesi AnggotaDiawali dengan edu-sess-. Siswa memperolehnya setelah verifikasi email. Masa berlaku default adalah 24 jam; dapat dicabut oleh admin organisasi.
  • ADomain yang DiizinkanOrganisasi mengonfigurasi domain email mana (kecocokan persis, tanpa bypass suffix) yang boleh meminta sesi.
  • Atribusi penggunaanSemua permintaan siswa ditagih ke akun organisasi. Penggunaan dapat dilihat per sesi dan per email di dasbor organisasi.

Langkah 1 — Admin platform mengatur tipe organisasi ke Education

Dari sales@bazaarlink.ai / support@bazaarlink.ai, temukan organisasi target, beralih ke tab "Org Type", pilih Education, dan tetapkan domain email yang diizinkan:

{
  "orgType": "education",
  "eduConfig": {
    "allowedDomains": ["nthu.edu.tw", "student.nthu.edu.tw"],
    "sessionTtlSeconds": 86400,
    "verificationTtlSeconds": 900,
    "maxSessionsPerEmailPerKey": 5
  }
}
Pencocokan domain bersifat persis
nthu.edu.tw hanya mencocokkan @nthu.edu.tw — tidak akan mencocokkan @nthu.edu.attacker.com. Subdomain harus dicantumkan secara eksplisit (misalnya student.nthu.edu.tw).

Langkah 2 — Admin organisasi membuat Institution Key

Di halaman API Keys organisasi, pilih "Education" sebagai tipe kunci saat membuat kunci baru. Sistem menghasilkan kunci sk-edu-... dan menampilkannya SEKALI — simpan dan distribusikan melalui saluran resmi Anda kepada siswa di organisasi tersebut.

Langkah 3 — Siswa meminta kode verifikasi

Siswa membuka /access dan memasukkan edu key + email sekolah mereka; atau memanggil API langsung:

POST/api/edu/request-code
curl -X POST https://bazaarlink.ai/api/edu/request-code \
  -H "Content-Type: application/json" \
  -d '{
    "key": "sk-edu-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "email": "alice@nthu.edu.tw"
  }'

# Success (incl. unknown key/email — enumeration defence) → {"ok":true,"sent":true}
# Rate limit / resend cooldown → 429 {"error":"rate_limited"} or {"error":"cooldown"}
# Sends a 6-digit verification code to the email; default 15-minute lifetime
Anti-enumerasi
request-code selalu mengembalikan 202 terlepas dari apakah kunci ada atau apakah domain email diizinkan, mencegah penyerang menyelidiki edu key mana yang ada. Upaya yang gagal dicatat dalam log audit organisasi.

Langkah 4 — Siswa mengirimkan kode untuk ditukar dengan token sesi

POST/api/edu/verify
curl -X POST https://bazaarlink.ai/api/edu/verify \
  -H "Content-Type: application/json" \
  -d '{
    "key":   "sk-edu-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "email": "alice@nthu.edu.tw",
    "code":  "646291"
  }'

# Success → 200
{
  "token":     "edu-sess-827d11a1ec67d175cfd4f67f929261f4",
  "expiresAt": "2026-05-04T11:16:00.163Z",
  "organization": { "id": "...", "name": "NTHU AI Lab" }
}

# Wrong code → 400 {"error":"invalid"}
# 5 wrong attempts → 429 {"error":"too_many_attempts"} (code invalidated; re-request)

Langkah 5 — Gunakan token sesi untuk memanggil API

Gunakan token edu-sess-... sebagai Bearer token terhadap endpoint chat / completions / embeddings mana pun:

curl -X POST https://bazaarlink.ai/api/v1/chat/completions \
  -H "Authorization: Bearer edu-sess-827d11a1ec67d175cfd4f67f929261f4" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
Kunci sk-edu- tidak dapat digunakan langsung
Mengirim sk-edu-... langsung sebagai Bearer token ke endpoint chat akan mengembalikan:
403 — Education keys cannot be used directly. Visit /access to exchange for a session.
Ini adalah gerbang balik yang disengaja — mencegah sekolah membocorkan kunci berumur panjang kepada siswa individu.

Dasbor organisasi — pemantauan dan pencabutan

Organisasi tipe Education mendapatkan tab Education di nav samping, yang menyediakan:

  • PengaturanSesuaikan domain yang diizinkan, TTL, sesi maksimum per email per kunci, dan kuota request / token / USD per sesi.
  • SesiDaftarkan semua sesi aktif / kedaluwarsa / dicabut; filter berdasarkan email; cabut sesi individual.
  • Statistik penggunaanJumlah panggilan per sesi, konsumsi token, dan biaya akumulasi.

Keamanan dan batasan

ItemDefaultDeskripsi
Sesi TTL24 jamMasa berlaku token sesi; sesi yang kedaluwarsa memerlukan verifikasi ulang.
Kode verifikasi TTL15 menitMasa berlaku kode verifikasi email.
Panjang kode verifikasi6 digitDisimpan sebagai hash HMAC-SHA256 di Redis, tidak pernah dalam plaintext.
Tebak batasnya5 percobaanMelebihi ini kode akan langsung dibatalkan.
cooldown kode permintaan60 detikInterval minimum antara permintaan berulang untuk (key, email) yang sama.
Batas kecepatan Per-IP10 / 15 mntAnti-spam.
Batas kecepatan per kunci100 / jamMencegah pengiriman email massal.
Sesi maksimal per email Propagasi5Dapat dikonfigurasi di eduConfig; mencegah satu kotak masuk menimbun token.
Revocation≤ 60 detikTTL cache L1/L2; setelah pencabutan DB butuh hingga 60 detik untuk menyebar ke semua node.

Penagihan dan atribusi penggunaan

Semua permintaan yang dibuat melalui token sesi ditagih 100% ke organisasi yang memiliki edu key, sejalan dengan cara provider hulu (OpenAI / Anthropic / dll.) menagih (per-token). Dasbor organisasi mendukung drill-down berdasarkan sesi, berdasarkan email, dan berdasarkan kunci.

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?
Secara default, kami tidak menyimpan konten pesan. Kami hanya mencatat jumlah token dan stempel waktu untuk keperluan tagihan.
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.