se-hari.com se-hari.com

Idempotency

Cara mengulang request yang gagal tanpa risiko membuat meeting ganda atau membayar dua kali untuk pekerjaan yang sama.

4 menit baca Diperbarui 16 Agustus 2026 Lihat sebagai Markdown

Jaringan gagal di tempat yang paling merepotkan: setelah request Anda sampai dan dikerjakan, tapi sebelum responsnya kembali. Dari sisi Anda, kedua kemungkinan itu terlihat sama persis — timeout. Mengulang berarti berisiko mengerjakan hal yang sama dua kali; tidak mengulang berarti berisiko kehilangan pekerjaan.

Idempotency-Key menyelesaikan itu.

#Cara kerjanya

Kirim header Idempotency-Key berisi nilai unik pada request yang mengubah keadaan:

bash
curl -X POST "https://se-hari.com/api/v1/meetings" \
  -H "Authorization: Bearer $SEHARI_API_KEY" \
  -H "Idempotency-Key: 7f3a9c21-4b8e-4d6f-a1c2-9e8b7a6d5c4f" \
  -H "Content-Type: application/json" \
  -d '{"title":"Rapat mingguan","date":"2026-09-01","start_time":"09:00","pricing_tier_id":"..."}'

Kalau request dengan key yang sama datang lagi, kami tidak mengerjakannya lagi. Kami mengembalikan respons yang pertama, dengan status yang sama seperti aslinya. Meeting hanya terbuat sekali, kredit hanya terpotong sekali.

Key disimpan 24 jam. Setelah itu key yang sama dianggap baru.

#Membangun key yang benar

Kuncinya: key harus berkorespondensi satu-satu dengan pekerjaan, bukan dengan waktu.

javascript
// BENAR — satu key per item pekerjaan
const key = `arsip-harian-${tanggal}-${recording.id}`;

// BENAR — di n8n, mengikuti identitas eksekusi
// {{$workflow.id}}-{{$execution.id}}-{{$itemIndex}}

// SALAH — key konstan untuk isi yang berubah-ubah
const key = 'arsip-harian';

// SALAH — presisi kasar, dua pekerjaan berbeda bisa bertabrakan
const key = `arsip-${Math.floor(Date.now() / 60000)}`;

Yang penting, key harus tetap sama saat Anda mengulang. Membangkitkan UUID baru di setiap percobaan menghilangkan seluruh manfaatnya — dan itulah cara paling umum menciptakan meeting ganda yang kreditnya terpotong dua kali.

javascript
// Key dibuat SEKALI, di luar perulangan retry.
const key = crypto.randomUUID();

for (let percobaan = 0; percobaan < 3; percobaan++) {
	const res = await fetch('https://se-hari.com/api/v1/meetings', {
		method: 'POST',
		headers: {
			Authorization: `Bearer ${process.env.SEHARI_API_KEY}`,
			'Idempotency-Key': key,
			'Content-Type': 'application/json'
		},
		body: JSON.stringify(payload)
	});

	if (res.status < 500) return res;
	await new Promise((r) => setTimeout(r, 2 ** percobaan * 1000));
}

#Key yang sama, body yang berbeda

Kalau Anda mengirim key yang sudah dipakai tapi dengan body yang berbeda, kami menolaknya dengan idempotency_key_reused — bukan mengembalikan hasil yang lama.

Ini melindungi Anda dari kesalahan yang tanpanya tidak akan pernah Anda sadari. Kalau kami diam-diam mengembalikan hasil yang pertama, workflow Anda akan menganggap item kedua sudah dikerjakan padahal tidak, dan hasilnya adalah pekerjaan yang hilang tanpa satu pun error.

#Kapan wajib dipakai

Idempotency paling penting justru pada kegagalan yang paling membingungkan:

  • 500 internal_error — request mungkin sudah sebagian dikerjakan. Ini kasus utamanya.
  • 502 upstream_error — Zoom mungkin sudah membuat meeting sebelum langkah kami gagal.
  • Timeout jaringan — Anda tidak tahu apa-apa tentang apa yang terjadi di sisi kami.

Untuk 400 dan 403, idempotency tidak diperlukan: tidak ada yang sempat dikerjakan, jadi tidak ada yang bisa terduplikasi.

#Operasi yang mendukungnya

Semua endpoint yang mengubah keadaan menerima Idempotency-Key. Yang paling penting adalah dua yang menyentuh uang:

  • POST /meetings — memotong kredit saat itu juga
  • POST /notes — mengantre pekerjaan yang nanti ditagih

Endpoint GET tidak membutuhkannya. Ia sudah idempoten menurut definisi HTTP: memanggilnya sepuluh kali sama saja dengan sekali.

#Kalau request pertama masih berjalan

Ada satu kasus yang layak diketahui: dua request dengan Idempotency-Key yang sama dikirim nyaris bersamaan, dan yang pertama belum selesai saat yang kedua tiba.

Request kedua ditolak 409 conflict dengan pesan bahwa key tersebut sedang diproses. Ia tidak menunggu, dan tidak mengerjakan apa pun — yang penting, ia juga tidak menghasilkan pekerjaan kedua.

json
{
  "error": {
    "code": "conflict",
    "message": "Request dengan Idempotency-Key ini sedang diproses. Tunggu sampai selesai, lalu ambil hasilnya lewat endpoint baca."
  }
}

Menahan request kedua sampai yang pertama selesai akan terasa lebih ramah, tapi artinya koneksi Anda menggantung selama pekerjaan berjalan — dan pembuatan meeting Zoom bisa memakan belasan detik. Menolak cepat dengan pesan yang jelas lebih mudah ditangani daripada timeout yang tidak menjelaskan apa-apa.

Yang perlu dilakukan saat menemuinya: tunggu sebentar, lalu ambil hasilnya lewat endpoint baca alih-alih mengirim ulang. Pekerjaannya sedang dikerjakan; mengirim ulang tidak mempercepatnya.

Perlu dibedakan dari kasus setelah selesai: begitu request pertama selesai, key yang sama mengembalikan hasilnya seketika — itulah putar-ulang yang sesungguhnya. Dan kalau request pertama gagal, key-nya dibebaskan sehingga percobaan berikutnya benar-benar dikerjakan; kegagalan tidak pernah dicatat sebagai "sudah pernah dilakukan".

Ada satu kasus ketiga yang jarang tapi nyata: proses yang mengerjakan request pertama mati di tengah jalan — server di-restart saat deploy, misalnya. Tidak ada yang sempat menandai selesai maupun gagal. Kalau key itu dibiarkan menggantung, ia akan menolak setiap percobaan ulang selama 24 jam berikutnya, padahal tidak ada apa pun yang sedang berjalan.

Karena itu key yang berstatus "sedang diproses" lebih dari lima menit dianggap ditinggalkan, dan percobaan berikutnya dengan isi yang sama mengambil alih tempatnya. Lima menit jauh di atas operasi terlama kami, jadi request yang benar-benar masih berjalan tidak akan pernah terganggu. Isi yang berbeda tetap ditolak — pengambilalihan hanya sah untuk pengulangan request yang sama.

Konsekuensinya untuk sistem dengan beberapa worker: kalau dua worker tanpa sengaja mengambil pekerjaan yang sama, salah satunya mendapat 409 dan berhenti — bukan menghasilkan meeting kedua. Itu hasil yang diinginkan, meski bentuknya sebuah error.

#Perlindungan bawaan lain

Beberapa operasi punya pengaman tambahan yang tidak bergantung pada header ini. Satu rekaman hanya boleh punya satu notulen, jadi POST /notes untuk rekaman yang sudah diproses dijawab 409 conflict beserta id notulen yang sudah ada — bahkan tanpa Idempotency-Key sama sekali.

Anggap itu jaring pengaman, bukan pengganti. Ia melindungi dari duplikasi jenis tertentu, sementara Idempotency-Key melindungi dari duplikasi jenis apa pun.

#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