Menghitung berapa kredit yang akan terpakai untuk sebuah operasi TANPA menjalankannya. Untuk notulen, biayanya dihitung dari durasi rekaman memakai tarif yang tersimpan di konfigurasi (saat ini 1 kredit per 20 menit, dibulatkan ke atas, minimum 1 kredit). Angka yang dikembalikan untuk notulen adalah PERKIRAAN berdasarkan durasi yang Anda sebutkan; yang benar-benar ditagih nanti adalah durasi asli hasil transkripsi. Untuk meeting, biayanya pasti karena diambil dari paket harga yang dipilih, ditambah biaya rekaman kalau diaktifkan. Endpoint ini tidak punya efek samping.
#Endpoint
POST https://se-hari.com/api/v1/credits/estimateButuh scope credits:read. Scope ditetapkan saat key dibuat dan tidak bisa ditambahkan belakangan — kalau key Anda kurang izin, buat key baru lalu cabut yang lama. Kekakuan ini disengaja: scope yang bisa dinaikkan diam-diam berarti key yang bocor hari ini bisa menjadi lebih berbahaya besok. Beri setiap integrasi key sendiri dengan scope sesempit mungkin, supaya mencabut satu integrasi tidak pernah berarti mematikan yang lain.
Kirim header Idempotency-Key berisi nilai unik milik Anda sendiri; UUID sudah cukup. Kalau request diulang dengan key yang sama — karena timeout jaringan, retry otomatis n8n, atau tombol yang terklik dua kali — kami mengembalikan hasil yang pertama alih-alih mengerjakannya lagi. Key yang sama dengan body berbeda ditolak idempotency_key_reused, karena itu hampir selalu berarti bug di sisi pemanggil, bukan permintaan yang sah.
Operasi ini tidak memotong kredit saat dipanggil. Kalau ia mengantre pekerjaan notulen, penagihan terjadi setelah pemrosesan selesai dan dihitung dari durasi asli rekaman — bukan dari durasi yang Anda perkirakan. Perbedaan ini penting saat membaca saldo di langkah berikutnya sebuah workflow.
#Contoh
curl -X POST "https://se-hari.com/api/v1/credits/estimate" \
-H "Authorization: Bearer $SEHARI_API_KEY"const res = await fetch('https://se-hari.com/api/v1/credits/estimate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SEHARI_API_KEY}`,
}
});
if (!res.ok) {
const { error } = await res.json();
// error.code stabil dan bisa dicabang; error.message untuk manusia.
throw new Error(`${error.code}: ${error.message}`);
}
const data = await res.json();import os, requests
res = requests.post(
"https://se-hari.com/api/v1/credits/estimate",
headers={"Authorization": f"Bearer {os.environ['SEHARI_API_KEY']}"},
timeout=30,
)
if not res.ok:
err = res.json()["error"]
raise RuntimeError(f"{err['code']}: {err['message']}")
data = res.json()#Respons 200
{
"credits_required": 3,
"credits_available": 47,
"sufficient": true,
"is_estimate": true,
"breakdown": {
"minutes_per_credit": 20,
"duration_minutes": 60
}
}#Field respons
| Field | Tipe | Keterangan |
|---|---|---|
credits_required | integer | — |
credits_available | integer | — |
sufficient | boolean | — |
is_estimate | boolean | — |
breakdown | object | — |
#Kalau gagal
Setiap kegagalan memakai amplop yang sama, dan code di dalamnya stabil — cabangkan logika Anda ke sana, jangan ke message yang teksnya bisa diperbaiki sewaktu-waktu.
{
"error": {
"code": "invalid_request",
"message": "Penjelasan untuk manusia.",
"docs_url": "https://se-hari.com/docs/error/invalid-request",
"request_id": "req_a1b2c3d4e5f6",
"details": {}
}
}| Status | Kode | Artinya di endpoint ini |
|---|---|---|
| 400 | invalid_request | Body tidak lolos validasi. Field yang bermasalah disebut di details. |
| 401 | invalid_api_key | Key salah, sudah dicabut, atau kedaluwarsa. |
| 403 | insufficient_scope | Key valid, tapi tidak punya scope yang dibutuhkan endpoint ini. |
| 404 | not_found | Data tidak ada, atau ada tapi milik akun lain — keduanya dijawab sama. |
| 429 | rate_limited | Terlalu banyak request. Hormati header Retry-After. |
| 500 | internal_error | Kesalahan di sisi kami. Sertakan request_id saat melapor. |
| 503 | service_unavailable | Layanan sedang tidak tersedia sementara. |
Simpan request_id dari setiap respons gagal. Itu satu-satunya cara kami menemukan kembali request Anda di log ketika Anda melapor, dan ia juga ada di header X-Request-Id pada respons yang berhasil. |
#Alur khas
Kredit adalah satuan penagihan Se-Hari. Ia dibeli sekali pakai, punya masa berlaku, dan dipotong dengan urutan paling cepat hangus lebih dulu — sehingga saldo total saja tidak cukup untuk merencanakan pemakaian sebulan ke depan.
GET /credits— saldo total beserta rincian per paket dan tanggal hangusnyaPOST /credits/estimate— hitung biaya sebuah operasi sebelum menjalankannyaGET /credits/usage— telusuri ke mana kredit terpakai
Estimasi untuk notulen adalah perkiraan, bukan angka final: yang ditagih nanti adalah durasi asli hasil transkripsi, yang bisa berbeda dari durasi yang Anda sebutkan. Estimasi untuk meeting bersifat pasti, karena diambil dari paket harga yang sudah tetap.
#Yang sering keliru
- Key disalin sebagian. API key Se-Hari panjangnya tetap:
sh_live_diikuti 43 karakter. Kalau panjangnya berbeda, yang salah adalah proses penyalinannya, bukan key-nya — dan pesan 401 tidak akan mengatakan itu. - Scope kurang, bukan key salah. 403 di sini berarti key-nya dikenali. Periksa scope-nya lewat
GET /me, lalu buat key baru kalau memang kurang; scope tidak bisa ditambahkan ke key yang sudah jadi. - 404 tidak selalu berarti data tidak ada. Data milik akun lain juga dijawab 404, bukan 403 — kami tidak mengonfirmasi keberadaan id milik orang lain. Kalau Anda yakin id-nya benar, periksa apakah key yang dipakai milik akun yang sama.
- Hormati
Retry-After. Mencoba lagi lebih cepat dari yang disebutkan hanya memperpanjang masa tunggu. Kalau Anda sering menyentuhnya, kemungkinan besar Anda sedang polling sesuatu yang seharusnya ditangani webhook.
#Selanjutnya
- Autentikasi dan API key — cara membuat key dan memilih scope
- Kode error — arti setiap kode dan cara memperbaikinya
- Idempotency — kenapa retry aman kalau dilakukan dengan benar
- Spesifikasi OpenAPI — kontrak mesin, cocok untuk men-generate klien