Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

API Harga Pangan Indonesia

⚠️ Disclaimer: API ini adalah agregator tidak resmi yang membungkus data harga pangan dari PIHPS Bank Indonesia menjadi API JSON. Bukan produk resmi Bank Indonesia atau Badan Pangan Nasional. Lihat bagian Disclaimer.

API read-only, gratis, dan open source untuk mengambil data harga pangan strategis Indonesia (beras, cabai, bawang, daging, minyak goreng, gula, telur, dll) per provinsi dan kabupaten/kota. Data diperbarui otomatis setiap hari oleh scraper internal.

Fitur

  • Data harga eceran Pasar Tradisional (sesuai sumber PIHPS BI)
  • Cakupan: 21 komoditas, 34 provinsi, 110+ kabupaten/kota
  • Riwayat hingga 90 hari
  • Tanpa autentikasi — semua endpoint publik, dilindungi rate limit berbasis IP
  • Dokumentasi OpenAPI interaktif (Swagger UI)

Daftar Isi

Base URL

Environment URL
Produksi https://harga-pangan.fly.dev
Lokal http://localhost:8080

Dokumentasi interaktif: GET /docs (Swagger UI) · GET /openapi.json (spek raw).

Format Response

Setiap respons selalu memuat field berikut agar konsumen API tahu asal & umur data:

{
  "sumber": "PIHPS Bank Indonesia",   // dari mana data ini
  "tanggal_update": "2026-08-16T07:30:00Z", // kapan terakhir diperbarui di server
  "disclaimer": "Agregator tidak resmi — ...", // atribusi & batasan
  "data": [ ... ]                     // isi sesuai endpoint
}

Error memakai HTTP status standar dan pesan dalam Bahasa Indonesia:

{
  "sumber": "PIHPS Bank Indonesia",
  "error": "Parameter tidak valid.",
  "issues": ["hari: Number must be less than or equal to 90"]
}

Endpoint

GET /komoditas

Daftar komoditas yang tersedia (referensi). id (com_*) adalah id internal sumber data (PIHPS BI) — dipakai sebagai filter komoditas=.

{
  "data": [
    { "id": "com_1", "nama": "Beras Kualitas Bawah I", "satuan": "kg", "urutan": 1, "kategori": "Beras" }
  ]
}

GET /wilayah

Daftar provinsi & kabupaten/kota.

Query Tipe Keterangan
level str Filter level: provinsi atau kabupaten_kota
provinsi str Filter nama provinsi (mendukung sebagian kata)

GET /harga/terbaru

Snapshot harga terbaru semua komoditas (opsional filter). Respons dikelompokkan per komoditas, dengan tanggal data di level atas.

Query Tipe Keterangan
komoditas str Nama/id komoditas (sebagian kata, mis. beras)
provinsi str Nama provinsi
kota str Nama kabupaten/kota (mis. surabaya)
{
  "tanggal": "2026-08-14",
  "data": [
    {
      "komoditas": { "id": "com_1", "nama": "Beras Kualitas Bawah I", "satuan": "kg" },
      "harga": [
        { "wilayah": { "level": "provinsi", "nama": "Jawa Timur", "provinsi": null }, "harga": 13550 },
        { "wilayah": { "level": "kabupaten_kota", "nama": "Kota Surabaya", "provinsi": "Jawa Timur" }, "harga": 15150 }
      ]
    }
  ]
}

GET /harga

Sama format & param seperti /harga/terbaru, tetapi wajib minimal satu filter (komoditas, provinsi, atau kota) — 400 jika kosong.

GET /harga/historis

Riwayat harga N hari terakhir, dikelompokkan per komoditas × wilayah.

Query Tipe Wajib Keterangan
komoditas str ya Nama/id komoditas
kota str ya* Nama kabupaten/kota (atau gunakan provinsi)
provinsi str ya* Nama provinsi (alternatif kota)
hari int tidak Jumlah hari riwayat, default 30, maks 90

*Wajib salah satu dari kota atau provinsi.

{
  "data": [
    {
      "komoditas": { "id": "com_1", "nama": "Beras Kualitas Bawah I", "satuan": "kg" },
      "wilayah": { "level": "kabupaten_kota", "nama": "Kota Surabaya", "provinsi": "Jawa Timur" },
      "riwayat": [
        { "tanggal": "2026-08-12", "harga": 15000 },
        { "tanggal": "2026-08-13", "harga": 15100 },
        { "tanggal": "2026-08-14", "harga": 15150 }
      ]
    }
  ]
}

Contoh Pemakaian

curl

# Semua komoditas
curl "https://harga-pangan.fly.dev/komoditas"

# Harga terbaru beras di Surabaya
curl "https://harga-pangan.fly.dev/harga?komoditas=beras&kota=surabaya"

# Snapshot semua harga di Jawa Timur
curl "https://harga-pangan.fly.dev/harga/terbaru?provinsi=jawa%20timur"

# Riwayat 30 hari cabai di Surabaya
curl "https://harga-pangan.fly.dev/harga/historis?komoditas=cabai&kota=surabaya&hari=30"

Pakai http://localhost:8080 kalau menjalankan lokal (lihat Menjalankan Lokal).

Fetch (JavaScript)

const BASE = "https://harga-pangan.fly.dev";

const { data: komoditas } = await fetch(`${BASE}/komoditas`).then((r) => r.json());
console.log(komoditas.map((k) => `${k.nama} (${k.id})`));

const { data: beras } = await fetch(
  `${BASE}/harga/historis?komoditas=beras&kota=surabaya&hari=30`,
).then((r) => r.json());
for (const seri of beras) {
  console.log(`${seri.komoditas.nama} @ ${seri.wilayah.nama}:`);
  for (const { tanggal, harga } of seri.riwayat) {
    console.log(`  ${tanggal}: Rp ${harga}`);
  }
}

Rate Limit

Tanpa autentikasi, semua permintaan dibatasi 120 request/menit per IP (jendela tetap). Ketika terlampaui, respons 429 dengan header Retry-After. Atur ulang lewat env RATE_LIMIT_MAX. Endpoint /health dikecualikan dari penghitungan kuota.

Header HTTP

  • CORS: semua endpoint mengizinkan cross-origin (Access-Control-Allow-Origin: *), termasuk preflight OPTIONS.
  • Cache: respons sudah diset untuk caching oleh CDN/proxy/browser — Cache-Control berbeda per tipe data:
    Endpoint Cache-Control
    /komoditas, /wilayah public, max-age=3600
    /harga* public, max-age=300
    error (4xx/5xx), /health no-store
    /, /docs, /openapi.json no-cache
  • Semua respons JSON menyertakan X-Content-Type-Options: nosniff.

Menjalankan Lokal

Prasyarat: Bun ≥ 1.3.

bun install
bun run dev        # scheduler + API (http://localhost:8080)
bun run scrape     # jalankan scraper sekali (mode full)
bun run test       # unit test
bun run typecheck  # type check

Mode lain: bun src/index.ts api (hanya API), bun src/index.ts full, bun src/index.ts smoke.

Konfigurasi via env:

Env Default Keterangan
PORT 8080 Port API
DB_PATH data/harga-pangan.db Lokasi database SQLite
RATE_LIMIT_MAX 120 Maks request per menit per IP
API_PUBLIC_URL http://localhost:8080 Base URL yang ditampilkan di OpenAPI
TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID Notifikasi scraper ke Telegram (opsional)

Pengembangan

Struktur:

src/
  scraper/     # fetcher + parsing + deteksi anomali + scheduler
  db/          # skema & query SQLite
  routes/      # endpoint API (Hono + zod-openapi)
  middleware/  # rate limit
  notify/      # notifikasi Telegram
  util/

Stack: Bun · TypeScript · Hono (@hono/zod-openapi) · SQLite (bun:sqlite) · Zod. Skema Zod dipakai untuk validasi input sekaligus generate dokumentasi OpenAPI.

Lisensi

MIT

Disclaimer

API ini bukan produk resmi Bank Indonesia maupun Badan Pangan Nasional, dan tidak berafiliasi dengan keduanya. Data diambil dari situs PIHPS (bi.go.id/hargapangan) lewat endpoint internal yang tidak terdokumentasi secara resmi, sehingga:

  • struktur data sumber bisa berubah sewaktu-waktu tanpa pemberitahuan;
  • keakuratan tidak dijamin; gunakan dengan pertimbangan Anda sendiri;
  • periksa ketentuan penggunaan data masing-masing sumber sebelum memakai API ini secara komersial.

Atribusi sumber wajib dipertahankan di aplikasi yang memakai API ini.

About

API gratis & read-only untuk data harga pangan Indonesia (beras, cabai, bawang, telur, daging, dll) per provinsi & kabupaten/kota. Data dari PIHPS Bank Indonesia (agregator tidak resmi). 21 komoditas, 34 provinsi, 110+ kabupaten/kota. Dibangun dengan Bun, Hono, SQLite.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages