Lewati ke konten
kenari.

Batas laju

kenari membatasi seberapa cepat kamu memanggil API di beberapa tempat. Halaman ini mendaftar setiap batas, error yang dikembalikan, dan cara mencoba ulang. Untuk format error dan kode lainnya, lihat Error.

StatusKodeRetry-AfterYang perlu dilakukan
429rate_limit_exceededTidak, kecuali untuk musikTunggu beberapa detik lalu coba lagi. Beri jarak antar request.
429free_quota_rpmYaTunggu selama jumlah detik yang tercantum di Retry-After, lalu coba lagi.
429free_quota_dailyYa, sampai 00:00 UTCJangan coba lagi hari ini. Pakai model berbayar, top up, atau tunggu reset.
429plan_limit_reachedTidakJangan coba ulang dalam loop. Aktifkan PAYG atau fallback gratis, atau tunggu jendela kuota direset.
429upstream_errorTidakProvider sedang membatasi laju. Tunggu lalu coba lagi.
503all_providers_failedYa, saat provider dijeda atau penuhTunggu selama jumlah detik yang tercantum di Retry-After, lalu coba lagi.

Header Retry-After berisi jumlah detik. Kalau response tidak punya Retry-After, pakai exponential backoff.

Kode di tabel ini adalah kode error format OpenAI, yang dikembalikan Chat completions, Responses, dan endpoint lain. Error Messages tidak punya field code. Error itu membawa error.type, dan beberapa batas di atas muncul di sana sebagai rate_limit_error. Di Messages, tentukan penanganan dari status HTTP dan header Retry-After. Lihat Error.

Setiap akun punya batas request per menit untuk model berbayar. Batas ini dipakai bersama oleh Chat completions, Messages, dan Responses. Kalau melewati batas, request gagal dengan 429 dan rate_limit_exceeded, tanpa header Retry-After. Batasnya diatur per akun, jadi bisa berbeda antar akun. Request ke model :free dihitung terhadap batas model gratis di bawah, dan endpoint lain tidak dihitung terhadap batas ini.

Ketiga endpoint Pemakaian berbagi batas 60 request per menit untuk tiap akun. Kalau melewati batas, request gagal dengan 429 dan rate_limit_exceeded, tanpa header Retry-After. Batas ini dihitung terpisah dari batas akun di atas.

Setiap key login bisa membuat 20 key per tool per menit. Kalau melewati batas, request gagal dengan 429 dan rate_limit_exceeded, tanpa header Retry-After. Melihat dan mencabut key tidak dibatasi.

Setiap akun punya batas per menit dan kuota harian untuk model :free. Nilainya bergantung pada tier akunmu. Model gratis mendaftar tier-tiernya, dan GET /api/public/pricing mengembalikan angka terkini.

  • Per menit. Kalau melewati batas, request gagal dengan 429 dan free_quota_rpm, dan Retry-After menyebut sisa detik sampai jendela batas direset.
  • Per hari. Kuota harian menghitung request yang berhasil dan direset pukul 00:00 UTC. Kalau kuota habis, request gagal dengan 429 dan free_quota_daily, dan Retry-After berisi jumlah detik sampai reset. Top up atau berlangganan menaikkan kuota.
  • Lonjakan. Request gratis yang datang berdekatan diberi jarak dan dilayani satu per satu, bukan ditolak. Lonjakan yang terus-menerus ditolak dengan 429 dan rate_limit_exceeded.
  • Anggaran token. Model gratis bisa punya anggaran total token. Kalau sudah habis, model itu mengembalikan 429 dan rate_limit_exceeded sampai jendela anggaran direset.

Response model gratis yang berhasil membawa X-RateLimit-Limit, X-RateLimit-Remaining, dan X-RateLimit-Reset kalau model itu punya batas per menit. X-RateLimit-Reset adalah Unix timestamp dalam detik.

Langganan mencakup model-modelnya lewat jendela kuota. Saat sebuah jendela habis dan PAYG maupun fallback gratis tidak aktif, request ke model yang tercakup gagal dengan 429 dan plan_limit_reached, tanpa header Retry-After. message pada error ini ditulis dalam bahasa Indonesia, jadi gunakan code untuk menentukan penanganan error (di Messages, gunakan status dan error.type). Aktifkan PAYG atau fallback gratis di pengaturan langgananmu, atau tunggu jendela direset. Lihat Langganan.

Setiap akun bisa menjalankan dua pembuatan musik sekaligus. Request ketiga gagal dengan 429 dan rate_limit_exceeded, dan Retry-After diatur 60 detik. Coba lagi setelah salah satu proses pembuatan musik selesai. Lihat Musik.

Saat provider sebuah model membatasi laju kenari, kamu mendapat 429 dan upstream_error, tanpa header Retry-After. Saat provider timeout atau gagal, kamu mendapat 503 dan upstream_error. Saat semua provider untuk sebuah model sedang dijeda sementara atau penuh, kamu mendapat 503 dan all_providers_failed, dengan header Retry-After. Rute atau fallback BYOK bisa memindahkan request ke provider lain sebelum kamu melihat salah satu dari error ini. Lihat Routing & rute dan BYOK.

API key dibagikan dibatasi lajunya sebagai satu kesatuan, jadi orang-orang yang memakai sebuah share tidak bisa menghabiskan batas akun pemiliknya. Setiap alamat IP klien juga dibatasi 30 request per menit pada satu API key dibagikan, baik di /v1 maupun di server MCP. Kalau melewati batas itu, response-nya 429 dengan body teks biasa too many requests, try again shortly, bukan JSON. Lihat Autentikasi & API key.

Di Messages, terapkan aturan yang sama berdasarkan status HTTP, karena tidak ada code. Coba ulang hanya error yang bisa pulih sendiri: 429 dengan rate_limit_exceeded, free_quota_rpm, atau upstream_error, serta 503. Jangan coba ulang free_quota_daily, plan_limit_reached, atau 402 apa pun, karena kondisinya tetap sama sampai kamu mengubah sesuatu.

  1. Kalau response punya header Retry-After, tunggu selama jumlah detik itu.
  2. Kalau tidak, tunggu dengan exponential backoff dan jitter, misalnya 1, 2, 4, dan 8 detik, masing-masing ditambah pecahan detik acak.
  3. Berhenti setelah beberapa percobaan dan tampilkan error-nya.

SDK resmi OpenAI dan Anthropic sudah mencoba ulang response 429 dan 5xx beberapa kali secara bawaan dan mengikuti Retry-After. Naikkan jumlah percobaannya dengan max_retries kalau itu cukup. Contoh ini menunjukkan logikanya kalau kamu ingin mengendalikannya sendiri.

import os
import random
import time
from openai import APIStatusError, OpenAI
client = OpenAI(
base_url="https://kenari.id/v1",
api_key=os.environ["KENARI_API_KEY"],
max_retries=0,
)
RETRYABLE = {"rate_limit_exceeded", "free_quota_rpm", "upstream_error", "all_providers_failed"}
def chat(messages, model="step-3-7-flash:free", attempts=5):
for attempt in range(attempts):
try:
return client.chat.completions.create(model=model, messages=messages)
except APIStatusError as error:
retryable = error.status_code in (429, 503) and error.code in RETRYABLE
if not retryable or attempt == attempts - 1:
raise
retry_after = error.response.headers.get("retry-after")
delay = float(retry_after) if retry_after else min(30, 2**attempt)
time.sleep(delay + random.random())
reply = chat([{"role": "user", "content": "Halo!"}])
print(reply.choices[0].message.content)

Jangan melanjutkan request yang gagal di tengah stream. Kirim ulang sebagai request baru.