forbidden adalah kode error HTTP 403 pada Se-Hari API. Anda punya izin secara scope, tapi operasinya tidak sah pada kondisi data saat ini. Berbeda dari insufficient_scope, yang bisa diperbaiki dengan key baru — ini hanya bisa diperbaiki dengan mengubah situasinya.
#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": "forbidden",
"message": "Contoh pesan untuk forbidden.",
"docs_url": "https://se-hari.com/docs/error/forbidden",
"request_id": "req_a1b2c3d4e5f6",
"details": {}
}
}#Kapan ini muncul
Kode ini menandai batas antara izin dan keadaan. Scope Anda cukup, key Anda sah, dan data yang dituju memang milik Anda — tapi operasinya tidak masuk akal untuk dilakukan sekarang. Karena itu tidak ada key baru yang bisa memperbaikinya, dan tidak ada gunanya mengulang request yang sama beberapa detik kemudian.
#Kenapa ini terjadi
- Membatalkan meeting yang sudah berjalan atau sudah selesai
- Mengubah data yang statusnya sudah final
- Meminta aset dari rekaman yang belum selesai diunggah
#Cara memperbaikinya
Ambil data terkait dan periksa status-nya lebih dulu. Kebanyakan kasus 403 di sini berarti langkah sebelumnya di workflow Anda belum selesai, bukan bahwa permintaannya salah.
#Yang memicu error
curl -X DELETE "https://se-hari.com/api/v1/meetings/c0ffee00-1111-2222-3333-444455556666" \
-H "Authorization: Bearer $SEHARI_API_KEY"#Yang seharusnya
# Periksa status dulu
curl "https://se-hari.com/api/v1/meetings/c0ffee00-1111-2222-3333-444455556666" \
-H "Authorization: Bearer $SEHARI_API_KEY" | jq '.status'
# "pending" ← masih bisa dibatalkan
# "active" ← sudah berjalan, tidak bisa#Aman diulang?
Percuma tanpa perubahan keadaan. Kalau statusnya berubah nanti (misalnya meeting selesai), operasi yang sama bisa jadi sah. Tapi mengulang beberapa detik kemudian hampir tidak pernah membantu; picu dari event, bukan dari timer.
#Jangan tertukar dengan
Kode ini dan insufficient_scope sama-sama 403, tapi penyebabnya berlawanan. insufficient_scope bisa diperbaiki dengan membuat key baru; kode ini tidak bisa, karena yang menghalangi adalah keadaan datanya. Kalau details menyebut status entitas, itu petunjuk paling langsung tentang apa yang perlu berubah.
#Mencegahnya terulang
Baca status entitas sebelum bertindak atasnya, terutama di workflow otomatis yang berjalan tanpa pengawasan. Satu request GET tambahan jauh lebih murah daripada workflow yang berhenti karena mencoba membatalkan meeting yang sedang berlangsung. Kalau Anda memakai webhook, gunakan event untuk memicu tindakan pada saat yang tepat, alih-alih menjadwalkannya dan berharap keadaannya masih sama.
#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 === 'forbidden') {
// Ambil data terkait dan periksa `status`-nya lebih dulu. Kebanyakan kasus 403 di sini…
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