Dashboard personal untuk memeriksa API key AI β apakah aktif/valid, model apa saja yang tersedia, sisa kuota, dan tes model tertentu bisa dipakai atau tidak.
Dibuat dengan Next.js 16 + TypeScript + Tailwind CSS.
cek-api/
βββ src/
β βββ app/
β β βββ page.tsx β Halaman dashboard utama
β β βββ layout.tsx β Kerangka halaman (font, background)
β β βββ globals.css β Styling global (dark theme)
β β βββ api/
β β βββ keys/route.ts β API: kelola API key (tambah/hapus/list)
β β βββ check/route.ts β API: cek semua key (aktif/saldo/model)
β β βββ test-model/route.ts β API: tes 1 model tertentu
β β βββ detect/route.ts β API: π deteksi provider dari key tak dikenal
β βββ components/
β β βββ AddKeyForm.tsx β Form tambah API key baru
β β βββ KeyCard.tsx β Kartu status 1 key + fitur tes model
β βββ lib/
β βββ types.ts β Definisi semua tipe data
β βββ providers.ts β Daftar provider AI + endpoint
β βββ store.ts β Penyimpanan key (file JSON + obfuscation)
β βββ checkers.ts β Logika cek key & tes model
β βββ cache.ts β Cache hasil cek (hemat request)
βββ data/ β (dibuat otomatis) isi: keys.json, cache.json
βββ README.md β Dokumentasi ini
Gunanya: Halaman yang kamu lihat di http://localhost:3000.
| Bagian | Fungsi |
|---|---|
loadKeys() |
Ambil daftar key dari /api/keys saat halaman dibuka |
runCheck() |
Panggil /api/check buat cek semua key (aktif/tidak + saldo) |
| Auto-refresh | Otomatis cek ulang tiap 10 menit |
| Statistik | Total key, Aktif, Invalid, Error |
| Render kartu | Tampilkan KeyCard untuk setiap key yang tersimpan |
Gunanya: Input API key baru.
- Default provider = "Custom / Auto-detect" β semua API bisa masuk
- Kolom Base URL (contoh:
https://vibe.madewgn.dev/v1) - Auto-detect prefix key:
pt-β Puter,sk-or-β OpenRouter,sk-ant-β Anthropic,gsk_β Groq,pplx-β Perplexity,AIzaβ Gemini - Tombol π Deteksi β buat key tanpa prefix (mis.
I1sMj6UH.yYUE...): app coba key ke semua provider secara paralel, yang jawab "valid" = provider & base URL-nya - Tombol Simpan Key β POST ke
/api/keys
Gunanya: Menampilkan status & detail 1 API key.
| Fitur | Fungsi |
|---|---|
| Badge status | π’ Aktif / π΄ Invalid / π Error |
| Sisa saldo | Tampil jika provider mendukung (OpenRouter, OpenAI) |
| List model | Model yang tersedia di API (bisa diklik β keisi kolom tes) |
| Tes Model | Input nama model β cek bisa dipakai atau tidak via /api/test-model |
| Tombol hapus | Hapus key dari penyimpanan |
| Method | Fungsi |
|---|---|
GET /api/keys |
List semua key (key di-mask: sk-abcβ’β’β’β’β’β’β’β’xyz) + hasil cache |
POST /api/keys |
Simpan key baru (body: providerId, label, key, baseUrl) |
DELETE /api/keys?id=xxx |
Hapus key berdasarkan id |
| Method | Fungsi |
|---|---|
GET /api/check |
Cek semua key (pakai cache 5 menit biar hemat) |
GET /api/check?refresh=1 |
Paksa cek ulang (abaikan cache) |
| Method | Fungsi |
|---|---|
POST /api/test-model |
Tes apakah model bisa dipakai (body: keyId, model) |
POST /api/detect |
Tebak provider & base URL dari key tak dikenal (body: key) |
| Method | Fungsi |
|---|---|
POST /api/detect |
Tebak provider & base URL dari key yang tidak diketahui (body: key) |
Gunanya: Semua definisi tipe TypeScript yang dipakai di seluruh project.
| Tipe | Fungsi |
|---|---|
ProviderId |
ID provider (openrouter, openai, custom, dll) |
ApiKeyEntry |
Data 1 API key yang tersimpan |
CheckResult |
Hasil cek 1 key (status, saldo, model, pesan) |
ModelTestResult |
Hasil tes 1 model (bisa dipakai atau tidak) |
Gunanya: Registri semua provider AI yang didukung.
- Berisi base URL default, header auth, endpoint cek saldo
- Custom = base URL bebas (untuk API apapun)
- Mau tambah provider baru? Cukup tambah 1 entry di array
PROVIDERS
Gunanya: Simpan & baca API key dari file lokal.
| Fungsi | Kegunaan |
|---|---|
listKeys() |
List key (key di-mask, aman dikirim ke browser) |
getRawKey(id) |
Ambil key asli (hanya dipakai di server) |
addKey() |
Simpan key baru (di-obfuscate dulu) |
deleteKey(id) |
Hapus key |
π Keamanan: Key disimpan di
data/keys.jsondalam keadaan ter-enkripsi (AES-256-GCM). Folderdata/sudah di-gitignoresupaya tidak ke-commit. Key lama (format XOR) otomatis di-migrasi saat pertama kali dibaca.
Gunanya: Otak dari project β yang melakukan pengecekan ke API provider.
| Fungsi | Kegunaan |
|---|---|
checkKey() |
Cek 1 key: valid? saldo? model apa aja? |
checkAllKeys() |
Cek banyak key sekaligus (paralel, 1 gagal tidak ganggu lain) |
testModel() |
Kirim chat kecil ("Say pong") untuk buktikan model bisa dipakai |
detectProvider() |
Coba key ke semua provider β ketahui provider & base URL |
probeModels() |
π¬ Auto-probe: coba model populer (kimi-k3, gpt-4o-mini, dll) β lapor mana yang valid |
quickProbeModel() |
β‘ Probe 1 model cepat (untuk model dari /models) |
probeModelList() |
π¬ Probe banyak model paralel (concurrency 4) β urutkan aktif dulu |
Robustness logic:
- Fallback path
/v1β kalaubaseUrl/models404, otomatis cobabaseUrl/v1/models(panel gateway kayak 9router/New API butuh/v1) - Fallback chat test β kalau endpoint
/modelsnggak ada (404/405/501), validasi lewat chat kecil - π¬ Auto-probe model β kalau
/modelsgagal, app otomatis tes model populer dan nampilin di kartu mana yang β Valid / β Gagal (termasukmoonshotai/kimi-k3) - π Model aktif duluan β kalau
/modelssukses, model-modelnya di-probe & diurutkan: yang β aktif tampil duluan, yang β gagal di belakang - Retry
max_tokensβ kalau model nolakmax_tokenskecil (mis. Kimi K3), retry 64 β 256 β tanpamax_tokens - Multi-model fallback β untuk provider custom, coba beberapa model umum sampai ada yang berhasil
Gunanya: Simpan hasil cek ke data/cache.json supaya tidak spam API provider.
- TTL default: 5 menit
- Setiap refresh dalam 5 menit β pakai hasil lama (cepat)
- Tombol "Cek Sekarang" β paksa cek baru
- Cache versioning β kalau logika cek diubah, versi cache dinaikkan otomatis β hasil lama yang error tidak dipakai lagi
Salin .env.example jadi .env, lalu isi:
copy .env.example .envIsi variabel di .env:
| Variabel | Wajib? | Fungsi |
|---|---|---|
AUTH_PASSWORD |
β | Password login dashboard (min 4 karakter) |
AUTH_SECRET |
β | Kunci session + enkripsi key (min 16 karakter random) |
APP_URL |
β | URL publik (dipakai script reset password), default http://localhost:3000 |
Generate AUTH_SECRET random:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"cd d:\laragon\www\cek-api
npm install # sekali saja
npm run dev # mode developmentBuka http://localhost:3000 β login dengan AUTH_PASSWORD.
- Login β masukkan password dari
.env - Tambah key β isi API key + base URL β Simpan
- Cek otomatis β app cek key-nya valid/tidak, tampilkan saldo, model tersedia, & base URL yang dipakai
- Tes model β ketik/klik nama model β tahu bisa dipakai atau tidak
- Refresh β tombol "Cek Sekarang" untuk cek ulang paksa
- JANGAN commit folder
data/(sudah di-gitignore) β isinya API key kamu - Key hanya diproses di server (route handler), browser hanya lihat versi mask
- Key di-enkripsi AES-256-GCM at-rest (kunci turunan dari
AUTH_SECRET) - Login wajib β semua halaman & API diproteksi (session cookie httpOnly)
- Rate limit per IP di semua API route (anti spam/brute-force)
Supaya bisa diakses dari mana saja:
- Set env vars di server:
AUTH_PASSWORD,AUTH_SECRET(kuat & unik!),APP_URL - Build & start:
npm run build
npm start # atau pakai pm2: npx pm2 start npm --name cek-api -- start- HTTPS β wajib pakai reverse proxy (Nginx/Caddy) + SSL cert supaya cookie session aman (cookie
secureotomatis aktif di production) - Lupa password? Di server:
npm run reset-passwordβ muncul link sekali pakai (valid 10 menit) β buka di browser β set password baru β langsung berlaku tanpa restart
Warning
Jangan pernah commit .env β isinya rahasia (AUTH_SECRET dipakai buat enkripsi key; kalau bocor, semua key bisa didekripsi).
Edit src/lib/providers.ts, tambah entry baru di array PROVIDERS:
{
id: "nama-provider",
name: "Nama Provider",
baseUrl: "https://api.provider.com/v1",
balanceType: "none", // atau "usd" kalau ada endpoint saldo
authHeader: "Authorization",
authScheme: "Bearer",
}