Dokumentasi

Gambaran umum

Indonesia Region API menerbitkan kode dan nama wilayah administrasi pemerintahan Indonesia sebagai file JSON statis. Tidak ada server, database, maupun API key: setiap endpoint adalah file di CDN, sehingga bisa dipakai oleh klien HTTP apa pun dalam bahasa pemrograman apa pun.

Ini adalah proyek independen yang menyediakan data siap-mesin yang diturunkan dari dokumen regulasi pemerintah Indonesia yang tersedia untuk publik. Ini bukan API resmi pemerintah, dan Kementerian Dalam Negeri (Kemendagri) tidak mendukungnya. Untuk keperluan hukum, gunakan dokumen resminya.

Apa itu “kodifikasi wilayah”

Kode dan data wilayah administrasi pemerintahan adalah penomoran nasional wilayah administrasi pemerintahan yang dikelola Kementerian Dalam Negeri. Setiap provinsi, kabupaten, kota, kecamatan, kelurahan, dan desa memiliki kode angka yang dipakai di berbagai sistem pemerintahan (kependudukan, pemilu, statistik, anggaran). Aturan pemberian kode ditetapkan dalam Permendagri 58/2021. Tabel kode lengkapnya diterbitkan, dan diperbarui secara berkala, dalam bentuk Keputusan Menteri Dalam Negeri. Yang berlaku saat ini adalah Kepmendagri 300.2.2-2138/2025.

Tingkat wilayah

Tingkat (API)Bahasa IndonesiaKodeJumlahKeterangan
provinceProvinsi3138Termasuk daerah khusus/istimewa (Aceh, DKI Jakarta, DI Yogyakarta, provinsi-provinsi di Papua).
regency, type kabupatenKabupaten32.04416Kode 01–69.
regency, type kotaKota32.7398Kode 71–99. Kota bukan kabupaten: “Kabupaten Bandung” (32.04) dan “Kota Bandung” (32.73) adalah dua wilayah berbeda.
districtKecamatan (distrik di Papua)32.73.017.285
village, type kelurahanKelurahan32.73.01.10018.496Wilayah kerja lurah sebagai perangkat kecamatan. Kode diawali angka 1.
village, type desaDesa (gampong, nagari, kampung, …)11.01.01.200175.252Kesatuan masyarakat hukum yang mengatur urusannya sendiri. Kode diawali angka 2.
village, type desa_adatDesa adat91.03.01.300714Kode diawali angka 3. Rekapitulasi resmi menghitungnya sebagai desa (total 75.266).

Hierarkinya ketat: setiap kabupaten/kota berada di satu provinsi, setiap kecamatan di satu kabupaten/kota, dan setiap kelurahan/desa di satu kecamatan.

Provinsi                31              Daerah Khusus Ibukota Jakarta
└── Kabupaten/Kota      31.71           Kota Administrasi Jakarta Pusat
    └── Kecamatan       31.71.01        Gambir
        └── Kelurahan   31.71.01.1001   Gambir

Format kode

Berdasarkan Permendagri 58/2021, Pasal 4–6:

Kode adalah string. Simpan sebagai teks, jangan sebagai angka. Angka nol di depan itu penting ("11.01"), dan titik adalah bagian dari kode yang diterbitkan. Untuk mendapatkan bentuk 10 digit yang dipakai sebagian sistem, hapus titiknya (3171011001).

Endpoint

EndpointIsi
/api/v1/meta.jsonVersi dataset, tanggal berlaku, sumber, jumlah data, catatan temuan, daftar endpoint.
/api/v1/provinces.jsonArray semua provinsi.
/api/v1/regencies.jsonArray semua kabupaten dan kota.
/api/v1/districts.jsonArray semua kecamatan (≈750 KB).
/api/v1/villages.jsonUsang (tetap tersedia tanpa perubahan di v1): semua kelurahan/desa dalam satu file (≈24 MB, ≈3,1 MB terkompresi), mendekati batas 25 MiB per file di hosting. Pakai file per provinsi atau per kecamatan.
/api/v1/provinces/{province}.jsonSatu provinsi, beserta jumlah anak dan sumbernya.
/api/v1/provinces/{province}/regencies.jsonKabupaten/kota dalam satu provinsi.
/api/v1/provinces/{province}/villages.jsonSemua kelurahan/desa dalam satu provinsi (data yang sama dengan villages.json; paling besar ≈2,5 MB, ≈0,3 MB terkompresi).
/api/v1/regencies/{regency}/villages.jsonSemua kelurahan/desa dalam satu kabupaten/kota (paling besar ≈240 KB).
/api/v1/regencies/{regency}.jsonSatu kabupaten/kota, beserta provinsinya, jumlah anak, dan sumbernya.
/api/v1/regencies/{regency}/districts.jsonKecamatan dalam satu kabupaten/kota.
/api/v1/districts/{district}.jsonSatu kecamatan, beserta kabupaten/kota, provinsi, jumlah anak, dan sumbernya.
/api/v1/districts/{district}/villages.jsonKelurahan/desa dalam satu kecamatan. Ini juga cara mencari satu kelurahan/desa: ambil 8 karakter pertama kodenya sebagai kode kecamatan.
/api/v1/changes.jsonIndeks daftar perubahan antar-dokumen sumber.
/api/v1/export/indonesia-regions.{csv|json|xml|sql|xlsx|pdf}Seluruh dataset sebagai satu file unduhan per format.
/api/v1/postal-codes/{3 digit pertama}.jsonPencarian kode pos: semua kelurahan/desa dengan kode pos tertentu (lihat Kode pos).
/api/v1/csv/{provinces|regencies|districts|villages}.csvData yang sama dalam format CSV, untuk spreadsheet dan impor massal.

Kode yang tidak dikenal menghasilkan HTTP 404. Tidak ada file per kelurahan/desa, karena 83.762 file tambahan akan melampaui batas jumlah file Cloudflare.

Nama field dan path API sengaja memakai bahasa Inggris (province, regency, district, village) agar konsisten di semua bahasa pemrograman; isinya tetap nama resmi dalam bahasa Indonesia.

GET /api/v1/provinces.json

[
  {"code":"11","name":"Aceh","source_page":31,"latitude":4.2…,"longitude":96.9…,"spatial_status":"available","bbox":[95.0…,2.0…,98.3…,6.1…]},
  {"code":"12","name":"Sumatera Utara","source_page":320,"latitude":…,"longitude":…,"spatial_status":"available","bbox":[…]},
  ...
]

GET /api/v1/provinces/31/regencies.json

[
  {"code":"31.01","name":"Kabupaten Administrasi Kepulauan Seribu","type":"kabupaten","province_code":"31","source_page":1334},
  {"code":"31.71","name":"Kota Administrasi Jakarta Pusat","type":"kota","province_code":"31","source_page":1335},
  ...
]

GET /api/v1/districts/31.71.01.json

{
  "code": "31.71.01",
  "name": "Gambir",
  "level": "district",
  "regency": { "code": "31.71", "name": "Kota Administrasi Jakarta Pusat", "type": "kota" },
  "province": { "code": "31", "name": "Daerah Khusus Ibukota Jakarta" },
  "counts": { "villages": 6, "kelurahan": 6, "desa": 0, "desa_adat": 0 },
  "source": { "document": "KEPMENDAGRI-300-2-2-2138-2025.pdf", "page": 1335 },
  "latitude": -6.17…,
  "longitude": 106.82…,
  "spatial_status": "available",
  "bbox": [106.80…, -6.19…, 106.84…, -6.16…],
  "links": {
    "self": "/api/v1/districts/31.71.01.json",
    "villages": "/api/v1/districts/31.71.01/villages.json",
    "regency": "/api/v1/regencies/31.71.json",
    "province": "/api/v1/provinces/31.json",
    "boundary": "/api/v1/boundaries/regencies/31.71/districts.geojson"
  },
  "geometry": {"type":"Polygon","coordinates":[[[106.81…,-6.16…], …]]}
}

GET /api/v1/districts/31.71.01/villages.json

[
  {"code":"31.71.01.1001","name":"Gambir","type":"kelurahan","district_code":"31.71.01","regency_code":"31.71","province_code":"31","source_page":1335},
  ...
]

Field data

Endpoint daftar mengembalikan array berisi data datar. Bentuk data selalu sama, baik dari daftar lengkap maupun dari daftar hierarki.

FieldTingkatKeterangan
codesemuaKode resmi, string, bertitik.
namesemuaNama persis seperti tercetak di dokumen sumber (lihat normalisasi). Nama kabupaten/kota menyertakan jenisnya: “Kabupaten …” atau “Kota …”.
typekabupaten/kota, kelurahan/desakabupaten atau kota; kelurahan, desa, atau desa_adat. Diturunkan dari kode dan dicocokkan dengan kolom tabel tempat nama itu tercetak.
province_codekabupaten/kota, kecamatan, kelurahan/desaProvinsi induk.
regency_codekecamatan, kelurahan/desaKabupaten/kota induk.
district_codekelurahan/desaKecamatan induk.
source_pagesemuaHalaman PDF sumber (meta.json → source.base_document.file), dihitung dari 1, tempat data itu tercantum di tabel rincian. Ini adalah urutan halaman PDF, bukan nomor yang tercetak di halaman.
latitude, longitudesemuaTitik representatif poligon batas wilayah BIG, dalam derajat desimal: titik yang dijamin berada di dalam poligon (lihat Batas wilayah administrasi). null jika BIG tidak memiliki poligon untuk kode tersebut.
spatial_statussemuaavailable (poligon BIG tergabung lewat kode) atau not_available.
postal_codekelurahan/desaKode pos Pos Indonesia, string 5 digit, atau null jika tidak ada kecocokan persis (lihat Kode pos).
bboxsemuaKotak batas poligon, [min_longitude, min_latitude, max_longitude, max_latitude], atau null. Berguna untuk menyesuaikan tampilan peta.

Endpoint detail (/provinces/{code}.json, /regencies/{code}.json, /districts/{code}.json) menambahkan level, objek induk, counts (jumlah anak), source (document dan page), serta links ke endpoint terkait. Endpoint detail juga memuat poligon wilayah: geometry (GeoJSON Polygon/MultiPolygon, atau null) dan links.boundary (berkas batas wilayah asalnya). Kelurahan/desa tidak memiliki endpoint detail; poligonnya ada di /api/v1/boundaries/regencies/{regency}/villages.geojson dan unduhan GeoJSON. Endpoint detail juga memuat postal_codes: daftar kode pos kelurahan/desa di wilayah itu, terurut.

Pulau dan koordinat

Tabel pulau di keputusan (Lampiran D.c) memuat 17.374 pulau bernama. Setiap pulau memiliki kode (NN.NN.4NNNN), nama, koordinat titik, luas (jika tercantum), dan status berpenduduk (BP) atau tidak berpenduduk (TBP). Total rekapitulasi 17.380 juga menghitung 6 pulau besar (Sumatera, Jawa, Kalimantan, Sulawesi, Timor, Papua) yang tidak memiliki baris. Pulau yang melintasi beberapa kabupaten/kota (misalnya Pulau Nias) memakai kode tingkat provinsi NN.00.4NNNN dan regency_code: null.

Titik pulau ini adalah satu-satunya koordinat di dokumen sumber. Keputusan tersebut tidak memuat batas maupun titik pusat provinsi, kabupaten/kota, kecamatan, atau kelurahan/desa. Keduanya berasal dari BIG, sebagai dataset terpisah dengan atribusinya sendiri (lihat Batas wilayah administrasi).

EndpointIsi
/api/v1/islands.jsonSemua pulau (≈5,7 MB).
/api/v1/islands.geojsonPulau yang sama dalam bentuk GeoJSON FeatureCollection berupa titik, untuk peta dan aplikasi GIS (≈0,4 MB terkompresi).
/api/v1/provinces/{province}/islands.jsonPulau dalam satu provinsi, termasuk pulau tingkat provinsi.
/api/v1/regencies/{regency}/islands.jsonPulau dalam satu kabupaten/kota (array kosong jika tidak ada).

Tidak ada daftar pulau per kecamatan: keputusan menetapkan pulau ke kabupaten/kota (atau, untuk pulau yang melintasi beberapa kabupaten/kota, ke provinsi), tidak pernah ke kecamatan. Menurunkannya dari batas wilayah BIG juga tidak memadai, karena hanya sekitar sepertiga titik pulau yang jatuh di dalam batas kecamatan; sebagian besar adalah pulau kecil yang titiknya berada di perairan atau di daratan yang terlalu kecil untuk poligon yang disederhanakan.

{"code":"11.10.40082","name":"Pulau Mangkir Gadang","regency_code":"11.10","province_code":"11",
 "latitude":2.146942,"longitude":98.124719,"latitude_dms":"02°08'48.99\" U","longitude_dms":"098°07'28.99\" T",
 "area_km2":0.0748,"inhabited":false,"remark":"Berita Acara Kesepakatan Bersama ...",
 "source_document":"KEPMENDAGRI-300-2-2-2430-2025.pdf","source_page":14}

Peta pulau menampilkan seluruh pulau di atas peta dasar OpenFreeMap, dengan filter provinsi, kabupaten/kota, dan status.

Batas wilayah administrasi

Poligon batas provinsi, kabupaten/kota, kecamatan, dan kelurahan/desa berasal dari Badan Informasi Geospasial (BIG). Poligon tersebut digabungkan dengan data Kemendagri di API ini berdasarkan kode yang persis sama (field KDPPUM, KDPKAB, KDCPUM, dan KDEPUM milik BIG). Nama tidak pernah dicocokkan, dan nama, kode, serta hierarki selalu berasal dari API ini. Setiap data tetap ada di file batas. Data tanpa poligon BIG memiliki "geometry": null dan "spatial_status": "not_available", sedangkan fitur BIG yang kodenya tidak ada di dataset terkini tidak disertakan dan dicatat di laporan.

TingkatDengan batas / jumlah dataLayer sumber BIG
Provinsi— / —gis/rest/services/STIG/Batas_Provinsi/MapServer/0
Kabupaten/Kota— / —gis/rest/services/DISIGT/BatasWilayah/FeatureServer/0
Kecamatan— / —rbi/rest/services/BATASWILAYAH/BATAS_KECAMATAN_AR/MapServer/0
Kelurahan/Desa— / —rbi/rest/services/BATASWILAYAH/BATAS_DESAKEL_AR/MapServer/0
EndpointIsi
/api/v1/boundaries/provinces.geojsonSemua provinsi (muatan awal peta, ≈0,14 MB terkompresi).
/api/v1/boundaries/provinces/{province}/regencies.geojsonKabupaten/kota dalam satu provinsi.
/api/v1/boundaries/regencies/{regency}/districts.geojsonKecamatan dalam satu kabupaten/kota.
/api/v1/boundaries/regencies/{regency}/villages.geojsonKelurahan/desa dalam satu kabupaten/kota. Dikelompokkan per kabupaten/kota, bukan per kecamatan, agar jumlah file tetap di bawah batas Cloudflare. Saring dengan district_code.
{"type":"Feature","id":"31.71.01.1001","properties":{"code":"31.71.01.1001","name":"Gambir","level":"village",
  "type":"kelurahan","district_code":"31.71.01","regency_code":"31.71","province_code":"31",
  "latitude":-6.17…,"longitude":106.82…,"spatial_status":"available"},"geometry":{"type":"Polygon","coordinates":[…]}}

Jelajahi batas wilayah di peta, dari provinsi hingga kelurahan/desa.

Kode pos

Kode pos berasal dari Pos Indonesia (kodepos.posindonesia.co.id), diambil —. — dari — kelurahan/desa memiliki kode pos (— kode berbeda). Keputusan Mendagri tidak memuat kode pos.

EndpointIsi
/api/v1/postal-codes/{3 digit pertama}.jsonSemua kelurahan/desa per kode pos, dikelompokkan menurut tiga digit pertama (satu file per kode akan melebihi batas jumlah file hosting).
GET /api/v1/postal-codes/101.json
{"10110":[{"code":"31.71.01.1001","name":"Gambir","district_code":"31.71.01","regency_code":"31.71","province_code":"31"}], …}

Contoh klien

curl

curl -s https://indonesia-region.caturseptian.site/api/v1/regencies/32.73/districts.json

JavaScript / TypeScript

type Village = {
  code: string; name: string; type: "kelurahan" | "desa" | "desa_adat";
  district_code: string; regency_code: string; province_code: string; source_page: number;
};

const BASE = "https://indonesia-region.caturseptian.site/api/v1";

export async function villagesOf(districtCode: string): Promise<Village[]> {
  const res = await fetch(`${BASE}/districts/${districtCode}/villages.json`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

// Cari satu kelurahan/desa berdasarkan kode: datanya dikelompokkan per kecamatan.
export async function village(code: string) {
  return (await villagesOf(code.slice(0, 8))).find((v) => v.code === code) ?? null;
}

Python

import requests

BASE = "https://indonesia-region.caturseptian.site/api/v1"
meta = requests.get(f"{BASE}/meta.json", timeout=30).json()
print(meta["dataset_version"], meta["counts"]["villages"])

regencies = requests.get(f"{BASE}/provinces/34/regencies.json", timeout=30).json()
print([r["name"] for r in regencies])

Go

type Regency struct {
	Code         string `json:"code"`
	Name         string `json:"name"`
	Type         string `json:"type"`
	ProvinceCode string `json:"province_code"`
	SourcePage   int    `json:"source_page"`
}

resp, err := http.Get("https://indonesia-region.caturseptian.site/api/v1/provinces/32/regencies.json")
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
var regencies []Regency
if err := json.NewDecoder(resp.Body).Decode(&regencies); err != nil { log.Fatal(err) }

PHP

$json = file_get_contents('https://indonesia-region.caturseptian.site/api/v1/regencies/35.78/districts.json');
$districts = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
foreach ($districts as $d) {
    echo $d['code'], ' ', $d['name'], PHP_EOL;
}

Java

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(
    URI.create("https://indonesia-region.caturseptian.site/api/v1/provinces.json")).build();
String body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
// parse dengan Jackson, Gson, ... ; simpan "code" sebagai String

Contoh-contoh ini memakai deployment resmi, https://indonesia-region.caturseptian.site. Jika halaman ini disajikan dari preview, alamat itulah yang ditampilkan.

Ukuran dan performa

Telusuri hierarkinya alih-alih mengunduh daftar lengkap. Pemilih berjenjang provinsi → kabupaten/kota → kecamatan → kelurahan/desa cukup memakai paling banyak empat request kecil:

FileTanpa kompresigzip
provinces.json2 KB0,6 KB
regencies.json54 KB7 KB
districts.json753 KB73 KB
villages.json (usang)24 MB3,1 MB
satu provinces/{code}/villages.json≤ 2,5 MB≤ 0,3 MB
search/villages.json (kode, nama, jenis semua kelurahan/desa)3,3 MB0,6 MB
satu districts/{code}/villages.json≤ 16 KB≤ 2 KB

Cloudflare mengompresi respons dan menyajikannya dari cache edge.

Unduhan

Seluruh dataset dalam satu file, dibuat dari data tervalidasi yang sama di setiap deploy. Ukuran dan checksum SHA-256 tercantum di meta.json → downloads.

FormatFileUkuranIsi
CSVindonesia-regions.csv—Semua tingkat dalam satu tabel (satu baris per wilayah: level, kode, nama, jenis, kode induk, halaman sumber, latitude, longitude, status spasial).
JSONindonesia-regions.json—Satu objek berisi array provinces, regencies, districts, villages beserta metadata dataset.
XMLindonesia-regions.xml—<indonesia-regions> dengan satu elemen per wilayah; field disimpan sebagai atribut.
SQLindonesia-regions.sql—CREATE TABLE + INSERT untuk empat tabel dengan primary key dan foreign key. Portabel: SQLite, PostgreSQL, MySQL/MariaDB.
Excel (XLSX)indonesia-regions.xlsx—Workbook berisi sheet About dan satu sheet per tingkat; kode disimpan sebagai teks, baris judul dibekukan dengan filter.
PDFindonesia-regions.pdf—Daftar seluruh wilayah siap cetak ukuran A4 (sekitar 1.270 halaman).

JSON dan XML hanya memuat tingkat wilayah; data pulau ada di indonesia-islands.json dan indonesia-islands.xml, karena satu file akan melebihi batas 25 MiB per file di hosting. CSV hanya memuat wilayah; SQL, XLSX, dan PDF memuat keduanya. Kelurahan/desa memuat postal_code di semua format.

Setiap format tabel memuat titik representatif dan status setiap wilayah (latitude, longitude, spatial_status; kosong jika BIG tidak memiliki poligon). Poligon tidak muat di sel tabel, sehingga tersedia sebagai GeoJSON:

TingkatFileIsi
Provinsiexport/boundaries/provinces.geojsonSeluruh 38 provinsi.
Kabupaten/Kotaexport/boundaries/regencies.geojsonSeluruh 514 kabupaten/kota.
Kecamatanexport/boundaries/districts-{province}.geojsonKecamatan, satu file per provinsi (mis. districts-31.geojson).
Kelurahan/Desaexport/boundaries/villages-{province}.geojsonKelurahan/desa, satu file per provinsi (mis. villages-31.geojson).

Kecamatan dan kelurahan/desa dipecah per provinsi karena satu file nasional akan melebihi batas 25 MiB per file di hosting. Jumlah fitur, ukuran, dan checksum SHA-256 ada di meta.json → boundaries.downloads. Fiturnya sama dengan yang ada di /api/v1/boundaries/.

Untuk mengekspor sebagian data saja (satu provinsi, satu kecamatan, …), buka penjelajah API, pilih wilayah, lalu gunakan Unduh respons ini. Keenam format yang sama dibuat langsung di browser dari respons yang sedang ditampilkan, ditambah GeoJSON berisi poligon wilayah yang ditampilkan. Kode tetap berupa teks di semua format.

Tidak ada endpoint pencarian di sisi server, karena situs statis tidak bisa menjalankan query. Untuk pencarian, unduh daftar yang dibutuhkan lalu saring di sisi klien. regencies.json dan districts.json cukup kecil untuk fitur ketik-langsung-cari (seperti di penjelajah API). Untuk kelurahan/desa, persempit dulu ke satu kecamatan, atau muat search/villages.json sekali ({"fields":["code","name","type"],"rows":[…]}, 0,6 MB terkompresi; peta melakukannya) lalu indeks secara lokal.

Versi

Jika aplikasi Anda perlu mengunci dataset tertentu, periksa dataset_version di meta.json.

Data historis

Dua tabel kode sebelumnya diekstrak dengan pipeline yang sama dan disimpan sebagai snapshot internal:

/api/v1/changes.json berisi perbedaan antar-dokumen yang berurutan. Kode yang ada di kedua dokumen tetapi namanya berbeda dicatat sebagai renamed (ganti nama); kode yang hanya ada di salah satunya dicatat sebagai added (ditambahkan) atau removed (dihapus). Perbedaan huruf besar/kecil, spasi, atau singkatan “KAB.” diabaikan. Jika sebuah wilayah pindah induk, kodenya ikut berubah (misalnya kabupaten yang pindah ke Papua Barat Daya, 92.xx → 96.xx pada 2022–2025). Perpindahan seperti ini tampil sebagai removed + added dan tidak pernah ditebak. API saat ini hanya menyajikan dataset terkini; snapshot historis adalah file data dan tidak mengubah endpoint /api/v1.

Asal-usul data

Setiap nilai bisa ditelusuri ke satu halaman dokumen resmi.

PDF resmi (sources/pdf, tidak di-deploy)
  → extract    koordinat kata via poppler pdftotext -bbox, baris tabel per halaman
  → normalize  hierarki, jenis, pencocokan silang, rekonsiliasi dengan angka tercetak
  → validate   format, keunikan, induk, jumlah, file hasil generate
  → build      JSON statis di public/api/v1 → Cloudflare

Dokumen sumber

DokumenDitetapkanPeran
Kepmendagri 300.2.2-2138 Tahun 20252025-04-25Tabel kode yang berlaku. Sumber semua data.
Kepmendagri 300.2.2-2430 Tahun 20252025-06-23Mengubah 2138/2025 khusus data pulau: 4 pulau berpindah dari Sumatera Utara ke Kabupaten Aceh Singkil. Tidak ada perubahan kode maupun nama wilayah. PDF berupa gambar, diperiksa secara visual.
Permendagri 58 Tahun 20212021-12-13Aturan format dan pemberian kode. Tanpa tabel kode.
Kepmendagri 100.1.1-6117 Tahun 20222022-11-09Tabel kode sebelumnya (dicabut). Snapshot historis.
Permendagri 137 Tahun 20172017-12-27Tabel kode lama (diganti). Snapshot historis.
PP 72 Tahun 20192019-10-14Perubahan PP 18/2016 tentang Perangkat Daerah. Hanya konteks hukum; tidak memuat kode.

Cara data saat ini diperiksa

Normalisasi

Nama disimpan persis seperti tercetak, termasuk penggunaan " sebagai tanda apostrof di dokumen (misalnya Ra"as). Satu-satunya pengecualian adalah nama kabupaten yang dicetak dengan singkatan “Kab” (53.02 Timor Tengah Selatan dan 95.02 Pegunungan Bintang), yang ditulis lengkap menjadi “Kabupaten” seperti 414 kabupaten lainnya. Keduanya dicatat di meta.json → provenance.normalizations.

Proses pembaruan

  1. Saat keputusan atau perubahan baru terbit, dokumen itu dicatat beserta tanggal penetapan dan checksum-nya. Jika dokumen itu menggantikan tabel kode, dokumen tersebut menjadi dokumen dasar, dan total yang diharapkan diambil dari rekapitulasinya.
  2. Tabel diekstrak ulang dari PDF, lalu dinormalisasi dan divalidasi. Pembaruan ditolak jika total, induk, jenis, atau jumlah tercetak tidak cocok.
  3. Temuan yang memerlukan keputusan manusia diperiksa terhadap halaman PDF dan dipublikasikan di meta.json → known_issues. Tidak ada koreksi diam-diam.
  4. Daftar perubahan terhadap dokumen sebelumnya dibuat otomatis (/api/v1/changes.json), dan setiap pembaruan ditinjau sebagai diff lengkap data.

Batasan dan temuan

CORS dan cache

API mengirim Access-Control-Allow-Origin: *, sehingga aplikasi browser di domain mana pun bisa memanggilnya. Request berupa GET sederhana dan tidak memerlukan preflight; jangan menambahkan header request khusus. Pengaturannya ada di public/_headers:

/api/*
  Access-Control-Allow-Origin: *
  Access-Control-Allow-Methods: GET, HEAD, OPTIONS
  Access-Control-Max-Age: 86400
  Cache-Control: public, max-age=3600, stale-while-revalidate=86400

Browser boleh menyimpan respons di cache selama satu jam, dan Cloudflare memvalidasinya ulang dengan ETag. JSON disajikan sebagai application/json. Halaman HTML mendapat header keamanan (CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy).

Laporkan koreksi

Koreksi harus didukung dokumen resmi. Jika Anda menemukan nama atau kode yang berbeda dari keputusan, kirim email ke hello@caturseptian.site dengan menyertakan kode, dokumen, dan halaman PDF-nya.

Atribusi data