rate_limited adalah kode error HTTP 429 pada Se-Hari API. Anda melewati batas jumlah request dalam satu jendela waktu. Batas dihitung per API key, bukan per alamat IP — di Indonesia banyak pengguna berbagi IP lewat CGNAT operator, sehingga batas per-IP akan menghukum orang yang tidak melakukan apa-apa.
#Bentuk responsnya
Semua error Se-Hari memakai amplop yang sama. Yang perlu dicabang di kode Anda adalah code, bukan message — teks pesan bisa kami perbaiki sewaktu-waktu, sedangkan code adalah kontrak publik yang hanya berubah lewat versi API baru.
{
"error": {
"code": "rate_limited",
"message": "Contoh pesan untuk rate_limited.",
"docs_url": "https://se-hari.com/docs/error/rate-limited",
"request_id": "req_a1b2c3d4e5f6",
"details": {
"limit": 120,
"window_seconds": 60
}
}
}#Kapan ini muncul
Batas dihitung per API key, bukan per alamat IP. Keputusan itu penting di Indonesia: operator seluler besar menempatkan ribuan pelanggan di balik satu alamat IP lewat CGNAT, sehingga batas per-IP akan menghukum orang yang tidak melakukan apa-apa dan sekaligus gagal membatasi penyalahguna yang berganti IP.
#Kenapa ini terjadi
- Polling status terlalu sering, alih-alih memakai webhook
- Perulangan tanpa jeda atas ratusan item
- Beberapa proses berbagi satu key dan saling menghabiskan kuota
#Cara memperbaikinya
Baca header Retry-After dan tunggu selama itu — mencoba lebih cepat hanya memperpanjang masa tunggu. Header X-RateLimit-Remaining pada setiap respons memberi tahu sisa kuota Anda sebelum menyentuh batas, jadi Anda bisa melambat sebelum ditolak, bukan sesudahnya.
#Yang memicu error
# Polling tiap detik
while true; do
curl -s "https://se-hari.com/api/v1/notes/<id>" -H "Authorization: Bearer $SEHARI_API_KEY"
done#Yang seharusnya
# Hormati Retry-After
res=$(curl -s -D /tmp/h -o /tmp/b -w '%{http_code}' \
"https://se-hari.com/api/v1/notes" -H "Authorization: Bearer $SEHARI_API_KEY")
if [ "$res" = "429" ]; then
tunggu=$(grep -i '^retry-after:' /tmp/h | tr -d 'A-Za-z-: \r')
echo "menunggu $tunggu detik"
sleep "$tunggu"
fi#Aman diulang?
Ya, setelah menunggu. Tunggu selama yang disebutkan Retry-After, tidak kurang. Mengulang lebih cepat memperpanjang masa tunggu pada sebagian besar implementasi jendela tetap, termasuk yang kami pakai.
#Jangan tertukar dengan
Kode ini soal frekuensi, bukan soal kuota kredit. insufficient_credits dan credit_cap_exceeded membatasi berapa banyak pekerjaan yang boleh Anda bayar; kode ini membatasi seberapa cepat Anda boleh bertanya. Sebuah key bisa menyentuh 429 tanpa memakai satu kredit pun, misalnya karena polling terus-menerus ke endpoint baca.
#Mencegahnya terulang
Sebagian besar kasus 429 pada integrasi Se-Hari berasal dari polling. Notulen butuh beberapa menit untuk diproses, dan menanyakan statusnya setiap detik menghasilkan ratusan request yang semuanya menjawab hal yang sama. Daftarkan webhook note.completed sekali, lalu berhenti bertanya. Kalau polling memang tidak terhindarkan, pakai jeda yang membesar dan baca X-RateLimit-Remaining untuk melambat sebelum ditolak.
#Menangani ini di kode
Cabangkan pada error.code, dan bedakan kegagalan yang layak diulang dari yang tidak. Mengulang kegagalan yang tidak akan pernah berhasil hanya menghabiskan kuota rate limit — dan menyembunyikan kegagalan yang sebenarnya butuh perhatian Anda.
const res = await fetch('https://se-hari.com/api/v1/me', {
headers: { Authorization: `Bearer ${process.env.SEHARI_API_KEY}` }
});
if (!res.ok) {
const { error } = await res.json();
if (error.code === 'rate_limited') {
// Baca header `Retry-After` dan tunggu selama itu — mencoba lebih cepat hanya…
console.error(error.message, error.details);
}
// request_id adalah satu-satunya cara kami menemukan request ini di log.
console.error(`request_id: ${error.request_id}`);
}#Selanjutnya
- Semua kode error — daftar lengkap
- Autentikasi — scope dan siklus hidup API key
- Referensi API — error apa saja yang mungkin muncul di tiap endpoint