se-hari.com se-hari.com

Rate limit

Batas frekuensi request dihitung per API key, bukan per IP. Cara membaca headernya dan cara melambat sebelum ditolak.

3 menit baca Diperbarui 16 Agustus 2026 Lihat sebagai Markdown

Se-Hari membatasi berapa banyak request yang boleh dikirim satu API key dalam satu jendela waktu. Melewatinya menghasilkan 429 beserta header yang memberi tahu kapan boleh mencoba lagi.

#Batas dihitung per key, bukan per IP

Ini keputusan yang berdampak nyata di Indonesia. Operator seluler besar menempatkan ribuan pelanggan di balik satu alamat IP lewat CGNAT. Batas per-IP akan menghukum orang yang tidak melakukan apa-apa hanya karena kebetulan satu operator dengan seseorang yang sedang menjalankan skrip, dan pada saat yang sama gagal membatasi penyalahguna yang tinggal berganti IP.

Batas per key juga berarti Anda bisa mengatur sendiri isolasinya: memberi setiap integrasi key sendiri mencegah satu skrip yang berisik menghabiskan kuota skrip lain.

#Membaca headernya

Setiap respons — berhasil maupun tidak — membawa tiga header:

HeaderArtinya
X-RateLimit-LimitJatah maksimum dalam jendela ini
X-RateLimit-RemainingSisa jatah sekarang
X-RateLimit-ResetKapan jendela berikutnya dimulai (unix timestamp)

Saat ditolak, ada satu header tambahan: Retry-After, berisi jumlah detik yang harus ditunggu.

bash
curl -i "https://se-hari.com/api/v1/notes?limit=1" \
  -H "Authorization: Bearer $SEHARI_API_KEY" | grep -i ratelimit

X-RateLimit-Remaining adalah yang paling berguna dan paling jarang dipakai orang: ia memungkinkan Anda melambat sebelum ditolak, bukan sesudahnya. Sebuah worker yang membaca angka ini dan menyisipkan jeda saat sisanya menipis tidak akan pernah menyentuh 429 sama sekali.

#Jendelanya mengikuti jam, bukan request pertama Anda

Jatah dihitung per menit dinding: jendela berganti pada detik ke-00 setiap menit, bukan 60 detik setelah request pertama Anda. X-RateLimit-Reset selalu berisi batas menit berikutnya, dan itulah angka yang dipakai Retry-After.

Ada satu akibat yang layak diketahui sebelum Anda menemukannya sendiri: karena jendelanya tetap dan bukan bergulir, rentetan di sekitar pergantian menit bisa meloloskan hampir dua kali lipat jatah dalam waktu singkat — jatah penuh di ujung satu menit, lalu jatah penuh lagi di awal menit berikutnya. Itu bukan celah yang perlu Anda manfaatkan; ia disebutkan supaya angka yang Anda ukur sendiri masuk akal.

Yang lebih sering menggigit justru kebalikannya. Kalau Anda mengukur batas dengan mengirim, katakanlah, 130 request berurutan dan rentetan itu memakan lebih dari beberapa puluh detik, ia bisa melintasi pergantian menit dan hitungannya ternol-kan di tengah jalan. Hasil pengukuran Anda lalu menunjukkan batas yang jauh lebih longgar daripada yang sebenarnya berlaku.

#Menangani 429

Aturan tunggalnya: hormati Retry-After. Percobaan yang ditolak tetap dihitung, jadi menembak lebih cepat hanya membakar jatah jendela berikutnya — walau tidak memperpanjang masa tunggu jendela yang sedang berjalan.

javascript
async function panggil(url, opsi = {}, percobaan = 0) {
	const res = await fetch(url, {
		...opsi,
		headers: {
			Authorization: `Bearer ${process.env.SEHARI_API_KEY}`,
			...opsi.headers
		}
	});

	if (res.status === 429 && percobaan < 3) {
		const tunggu = Number(res.headers.get('retry-after') ?? 60);
		console.warn(`kena rate limit, menunggu ${tunggu} detik`);
		await new Promise((r) => setTimeout(r, tunggu * 1000));
		return panggil(url, opsi, percobaan + 1);
	}

	return res;
}

Batasi jumlah percobaannya. Retry tak terbatas mengubah gangguan sementara menjadi antrean yang tidak pernah habis.

#Kenapa Anda menyentuh batas

Pada integrasi Se-Hari, penyebab paling umum sejauh ini adalah polling. Notulen butuh beberapa menit untuk diproses, dan kode yang menanyakan statusnya setiap detik menghasilkan ratusan request yang semuanya menjawab hal yang sama: "masih diproses".

Perbaikannya bukan menaikkan batas, melainkan berhenti bertanya. Daftarkan webhook note.completed sekali, dan Se-Hari yang akan memanggil Anda saat hasilnya siap. Satu request menggantikan ratusan.

Penyebab kedua adalah perulangan tanpa jeda atas ratusan item. Kalau Anda memproses semua rekaman lama, sisipkan jeda — worker notulen mengerjakan satu pekerjaan pada satu waktu, jadi mengirim 300 permintaan sekaligus tidak mempercepat apa pun. Ia hanya membuat antrean yang lebih sulit dipantau.

#Batas berbeda per jenis operasi

Tidak semua request dihitung dengan jatah yang sama. Operasi baca punya jatah paling longgar, operasi yang memakai kredit paling ketat, dan panggilan tool MCP punya jatahnya sendiri.

Alasannya praktis. Endpoint baca murah dan sering dipanggil dari antarmuka; membatasinya seketat operasi tulis hanya akan mengganggu pemakaian yang wajar. Sebaliknya, operasi yang memotong kredit patut dibatasi lebih ketat justru demi Anda — sebuah perulangan yang salah tulis akan berhenti karena rate limit jauh sebelum menghabiskan saldo.

Angka pastinya bisa berubah seiring kapasitas, jadi jangan menuliskannya ke dalam kode. Baca X-RateLimit-Limit pada respons kalau Anda perlu tahu jatah yang sedang berlaku; nilainya selalu mencerminkan batas yang benar-benar diterapkan pada key Anda saat itu.

Kalau integrasi Anda menjalankan beberapa jenis pekerjaan sekaligus, memberi masing-masing API key sendiri juga memisahkan jatahnya. Skrip arsip yang berjalan semalaman tidak akan menghabiskan jatah dashboard internal tim Anda.

#Rate limit bukan kuota kredit

Dua hal yang sering tertukar:

  • Rate limit membatasi seberapa cepat Anda boleh bertanya. Endpoint baca yang tidak memakai kredit pun bisa menyentuhnya.
  • Kredit membatasi seberapa banyak pekerjaan yang bisa Anda bayar.

Sebuah key bisa menyentuh 429 tanpa memakai satu kredit pun, dan sebaliknya bisa kehabisan kredit tanpa pernah mendekati rate limit.

#Selanjutnya

Siap mencoba?

Buat API key gratis di dashboard — tidak ada biaya berlangganan, kredit terpakai hanya saat Anda benar-benar memproses rekaman atau membuat meeting.

Buat API Key