se-hari.com se-hari.com

Menangani error

Semua error memakai satu amplop yang sama. Cara membacanya, mana yang layak diulang, dan mana yang tidak akan pernah berhasil.

2 menit baca Diperbarui 16 Agustus 2026 Lihat sebagai Markdown

Setiap kegagalan di Se-Hari API memakai amplop yang sama, apa pun endpoint dan status HTTP-nya:

json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Kredit tidak cukup. Dibutuhkan 3 kredit, tersisa 1.",
    "docs_url": "https://se-hari.com/docs/error/insufficient-credits",
    "request_id": "req_a1b2c3d4e5f6",
    "details": { "required": 3, "available": 1 }
  }
}

#Cabangkan pada code, bukan message

code adalah kontrak publik. Ia hanya berubah lewat versi API baru, jadi aman dipakai sebagai dasar percabangan logika.

message ditujukan untuk manusia dan bisa kami perbaiki kapan saja — memperjelas kalimat, menambahkan angka, menyesuaikan nada. Kode yang mencocokkan teks pesan akan rusak pada perbaikan pertama, dan rusaknya tanpa peringatan.

javascript
// BENAR
if (error.code === 'insufficient_credits') { … }

// SALAH — akan rusak begitu pesannya diperbaiki
if (error.message.includes('Kredit tidak cukup')) { … }

details berisi konteks yang bisa dibaca mesin dan bentuknya berbeda per kode: field mana yang ditolak, berapa kredit yang kurang, id data yang sudah ada. Ia sering memuat jawaban yang sebenarnya Anda cari — terutama pada 409 conflict, di mana details menunjuk data yang sudah menempati posisi itu.

#request_id

Setiap respons membawa request_id, baik di body error maupun di header X-Request-Id pada respons yang berhasil. Ini satu-satunya cara kami menemukan kembali request Anda di log.

Catat dia. Laporan "API-nya error kemarin siang" nyaris tidak bisa ditindaklanjuti; laporan dengan request_id bisa ditelusuri dalam hitungan menit.

Anda juga boleh mengirim X-Request-Id sendiri, dan kami akan memakainya alih-alih membuat baru — berguna kalau sistem Anda sudah punya id korelasi sendiri.

javascript
const res = await fetch(url, {
	headers: {
		Authorization: `Bearer ${process.env.SEHARI_API_KEY}`,
		'X-Request-Id': idKorelasiAnda
	}
});

#Mana yang layak diulang

Ini pembedaan paling penting dalam menangani error, dan yang paling sering diabaikan. Retry yang salah sasaran menghabiskan kuota rate limit sambil menyembunyikan masalah yang sebenarnya butuh perhatian.

Jangan pernah diulang tanpa perubahan — request yang sama akan ditolak dengan cara yang sama:

400 semua varian, 401, 403, 404, 405, 409, 410, 413, 415, 422.

Diulang setelah menunggu:

429 — tunggu selama Retry-After, tidak kurang.

Diulang dengan Idempotency-Key yang sama:

500, 502, 503. Ketiganya mungkin meninggalkan pekerjaan setengah jadi, dan key yang sama adalah satu-satunya cara memastikan percobaan berikutnya tidak menghasilkan duplikat.

javascript
const PERCUMA_DIULANG = new Set([400, 401, 403, 404, 405, 409, 410, 413, 415, 422]);

async function panggilDenganRetry(url, opsi, maks = 3) {
	const key = opsi.idempotencyKey ?? crypto.randomUUID();

	for (let i = 0; i < maks; i++) {
		const res = await fetch(url, {
			...opsi,
			headers: {
				Authorization: `Bearer ${process.env.SEHARI_API_KEY}`,
				'Idempotency-Key': key,
				...opsi.headers
			}
		});

		if (res.ok) return res.json();

		const { error } = await res.json();
		if (PERCUMA_DIULANG.has(res.status)) {
			throw new Error(`${error.code}: ${error.message} (${error.request_id})`);
		}

		const tunggu = res.status === 429
			? Number(res.headers.get('retry-after') ?? 60) * 1000
			: 2 ** i * 1000;
		await new Promise((r) => setTimeout(r, tunggu));
	}

	throw new Error('Gagal setelah beberapa percobaan');
}

#Mencatat error dengan berguna

Log yang hanya menuliskan "request gagal" tidak akan pernah membantu siapa pun. Empat hal yang wajib ikut tercatat, dan semuanya sudah tersedia di setiap respons: code, message, request_id, dan details — ditambah endpoint mana yang dipanggil.

request_id adalah yang paling penting dan yang paling sering hilang. Ia satu-satunya titik temu antara laporan Anda dan log kami; tanpanya, penelusuran berubah menjadi tebak-tebakan tentang waktu dan endpoint.

Yang tidak boleh ikut tercatat: isi header Authorization. API key di dalam log adalah kebocoran yang menunggu waktu, terutama karena log sering dikirim ke layanan pihak ketiga dan disimpan jauh lebih lama daripada yang siapa pun sadari. Kalau pustaka HTTP Anda mencatat seluruh header secara bawaan, matikan atau saring lebih dulu.

#Kegagalan asinkron

Notulen diproses di belakang layar, jadi kegagalannya tidak muncul sebagai status HTTP. Ia muncul sebagai status: "failed" pada notulen, dan sebagai event webhook note.failed.

Payload event itu memuat retryable. Bacalah field itu sebelum memutuskan mengulang: notulen yang gagal karena kredit habis akan berhasil segera setelah top up, sedangkan yang gagal karena rekamannya tidak punya audio tidak akan pernah berhasil berapa kali pun diulang.

#Daftar lengkap

Ada 22 kode error, masing-masing punya halamannya sendiri dengan penyebab dan perbaikannya: semua kode error.

docs_url di dalam setiap amplop menunjuk langsung ke halaman yang relevan, jadi Anda bisa mencetaknya di log dan menyusulnya nanti.

#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