{"openapi":"3.0.3","info":{"title":"API Jadwal Salat — SIHAT","version":"1.0.0","description":"Layanan data jadwal salat resmi Direktorat Jenderal Bimbingan Masyarakat Islam, Kementerian Agama RI.\n\n## Cara memperoleh akses\n\nAjukan melalui https://sihat.kemenag.dev/pengembang/ajukan. Setelah disetujui, Anda menerima **token** yang disertakan pada setiap permintaan.\n\n## Menyertakan token\n\nSalah satu dari dua cara berikut:\n\n```\nAuthorization: Bearer sihat_xxxxxxxx…\nX-API-Key: sihat_xxxxxxxx…\n```\n\n## Daftar alamat IP\n\nBila pengelola mendaftarkan alamat IP pada token Anda, permintaan dari alamat lain ditolak `403`. Penolakan selalu menyebutkan alamat yang terlihat oleh layanan — pakai alamat itu saat meminta pendaftaran, karena perangkat jaringan di jalur dapat menggantinya.\n\n## Kuota\n\nSetiap token memiliki kuota per menit dan per hari. Sisa kuota dikirim pada setiap respons:\n\n```\nX-RateLimit-Limit: 60\nX-RateLimit-Remaining: 59\nX-RateLimit-Reset: 42\n```\n\nSaat habis, respons `429` disertai `Retry-After` dalam detik.\n\n## Anjuran pemakaian\n\nJadwal untuk satu tanggal **tidak pernah berubah**. Banyak pemakai mengunduh jadwal beberapa tahun ke depan lalu menyimpannya di server sendiri — cara itu kami anjurkan: lebih cepat bagi pengguna Anda, dan tidak terpengaruh bila layanan ini sedang terganggu. Unduh per bulan, bukan sekaligus bertahun-tahun.\n\n## Kode wilayah\n\nSeluruh wilayah memakai kode nasional berjenjang: provinsi 2 digit, kabupaten/kota 4 digit, kecamatan 6 digit. Contoh: `31` DKI Jakarta → `3171` Kota Administrasi Jakarta Pusat → `317101` Gambir.\n\n## Bentuk error\n\nSetiap error membalas JSON yang memuat `sebab`. Pakai `sebab` untuk mengambil keputusan di program Anda, bukan teks `message` — kalimat pesan dapat diperbaiki kapan saja, dan program yang mencocokkan teksnya akan ikut rusak ketika itu terjadi.\n\n```json\n{\n  \"status\": \"no\",\n  \"sebab\": \"kuota_menit_habis\",\n  \"message\": \"Kuota 60 permintaan per menit sudah terpakai.\"\n}\n```\n\nKhusus `token_dicabut`, pengulangan tidak akan pernah berhasil — hentikan percobaan dan ajukan akses baru.\n\n## Catatan ejaan\n\nSejak Oktober 2026 seluruh tulisan memakai **salat** mengikuti KBBI. Jalur dengan ejaan lama (`/jadwal-shalat/…`) tetap dilayani agar klien yang sudah menyalinnya tidak rusak, tetapi jangan dipakai untuk kode baru.","contact":{"name":"Subdit Hisab dan Rukyat, Ditjen Bimas Islam","url":"https://sihat.kemenag.dev/kontak"}},"servers":[{"url":"https://sihat.kemenag.go.id/api/v1/public","description":"Layanan SIHAT"}],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"tags":[{"name":"Wilayah","description":"Daftar wilayah beserta kode nasionalnya."},{"name":"Jadwal Salat","description":"Jadwal harian dan bulanan per wilayah."}],"paths":{"/wilayah/provinsi":{"get":{"tags":["Wilayah"],"summary":"Daftar provinsi","description":"38 provinsi beserta kode nasional 2 digit.","responses":{"200":{"description":"Berhasil","headers":{"X-RateLimit-Remaining":{"$ref":"#/components/headers/SisaKuota"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsWilayah"},"example":{"status":"ok","data":[{"kode":11,"nama":"Aceh"},{"kode":31,"nama":"Daerah Khusus Ibukota Jakarta"}],"sumber":"Ditjen Bimas Islam, Kementerian Agama RI"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"403":{"$ref":"#/components/responses/Terlarang"},"429":{"$ref":"#/components/responses/KuotaHabis"}}}},"/wilayah/kabupaten":{"get":{"tags":["Wilayah"],"summary":"Daftar kabupaten/kota","parameters":[{"name":"provinsi","in":"query","required":false,"description":"Saring menurut kode provinsi (2 digit). Kosong = seluruh Indonesia (514 baris).","schema":{"type":"integer","example":31}}],"responses":{"200":{"description":"Berhasil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsWilayah"},"example":{"status":"ok","data":[{"kode":3171,"kode_provinsi":31,"nama":"Kota Administrasi Jakarta Pusat"}],"sumber":"Ditjen Bimas Islam, Kementerian Agama RI"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"429":{"$ref":"#/components/responses/KuotaHabis"}}}},"/wilayah/kecamatan":{"get":{"tags":["Wilayah"],"summary":"Daftar kecamatan","parameters":[{"name":"kabupaten","in":"query","required":true,"description":"Kode kabupaten/kota (4 digit).","schema":{"type":"integer","example":3171}}],"responses":{"200":{"description":"Berhasil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsWilayah"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"422":{"$ref":"#/components/responses/IsianKeliru"},"429":{"$ref":"#/components/responses/KuotaHabis"}}}},"/jadwal-salat/harian":{"get":{"tags":["Jadwal Salat"],"summary":"Jadwal satu hari","description":"Jadwal untuk satu tanggal pada satu wilayah. Hasilnya tetap sama untuk tanggal yang sama — aman disimpan.\n\nResponsnya memuat `hijriah` (tanggal Hijriah) dan `tanggal_masehi` (ISO). Perhatikan `hijriah.ketetapan`: `resmi` berarti dari taqwim Kemenag, `perkiraan` berarti hisab Ummul Qura yang dapat meleset satu hari.","parameters":[{"name":"wilayah","in":"query","required":true,"description":"Kode kabupaten/kota (4 digit) atau kecamatan (6 digit). Kecamatan memberi titik yang lebih tepat.","schema":{"type":"integer","example":3171}},{"name":"tanggal","in":"query","required":false,"description":"YYYY-MM-DD. Kosong = hari ini menurut zona wilayah tersebut.","schema":{"type":"string","format":"date","example":"2026-10-10"}}],"responses":{"200":{"description":"Berhasil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsJadwalHarian"},"example":{"status":"ok","data":{"tanggal":"Sabtu, 10 Oktober 2026","bujur":"106° 49' 7.30 BT","lintang":"-6° 10' 22.48 LU","imsak":"04:08","subuh":"04:18","terbit":"05:30","duha":"05:57","zuhur":"11:43","ashar":"14:44","maghrib":"17:49","isya":"18:58"},"wilayah":{"kode":3171,"nama":"Kota Administrasi Jakarta Pusat","tingkat":"kabupaten","zona_waktu":"UTC+7"},"sumber":"Ditjen Bimas Islam, Kementerian Agama RI"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"403":{"$ref":"#/components/responses/Terlarang"},"404":{"$ref":"#/components/responses/WilayahTakDikenal"},"422":{"$ref":"#/components/responses/IsianKeliru"},"429":{"$ref":"#/components/responses/KuotaHabis"},"503":{"$ref":"#/components/responses/SumberTerganggu"}}}},"/jadwal-salat/bulanan":{"get":{"tags":["Jadwal Salat"],"summary":"Jadwal satu bulan","description":"Satu bulan penuh dalam satu permintaan. Untuk mengunduh beberapa tahun, panggil berulang per bulan — jauh lebih andal daripada satu permintaan raksasa yang mudah putus di tengah.\n\nResponsnya memuat `hijriah` (tanggal Hijriah) dan `tanggal_masehi` (ISO). Perhatikan `hijriah.ketetapan`: `resmi` berarti dari taqwim Kemenag, `perkiraan` berarti hisab Ummul Qura yang dapat meleset satu hari.","parameters":[{"name":"wilayah","in":"query","required":true,"schema":{"type":"integer","example":3171}},{"name":"tahun","in":"query","required":true,"schema":{"type":"integer","minimum":2000,"maximum":2100,"example":2026}},{"name":"bulan","in":"query","required":true,"schema":{"type":"integer","minimum":1,"maximum":12,"example":10}}],"responses":{"200":{"description":"Berhasil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsJadwalBulanan"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"404":{"$ref":"#/components/responses/WilayahTakDikenal"},"422":{"$ref":"#/components/responses/IsianKeliru"},"429":{"$ref":"#/components/responses/KuotaHabis"},"503":{"$ref":"#/components/responses/SumberTerganggu"}}}},"/imsakiyah":{"get":{"tags":["Jadwal Salat"],"summary":"Jadwal imsakiyah satu Ramadan","description":"Seluruh hari Ramadan dalam satu permintaan, bernomor hari ke-1 sampai ke-29 atau ke-30.\n\n**Tahunnya HIJRIAH, bukan Masehi.** `?tahun=1447`, bukan `?tahun=2026`.\n\n**Rentangnya diambil dari ketetapan, bukan dihitung.** Awal Ramadan ditetapkan melalui sidang isbat — hisab diuji dengan laporan rukyatul hilal — sehingga ia keputusan, bukan hasil perhitungan. Untuk tahun yang taqwimnya belum terbit, endpoint ini menjawab `404` dengan `sebab: \"taqwim_belum_terbit\"` dan menyebutkan tahun yang sudah tersedia. Ia sengaja TIDAK mengarang perkiraan: imsakiyah adalah tabel yang dicetak lalu ditempel di masjid, dan tanggal yang meleset sehari akan tersebar dengan stempel Kementerian Agama di atasnya.","parameters":[{"name":"wilayah","in":"query","required":true,"description":"Kode 4 digit (kabupaten/kota) atau 6 digit (kecamatan).","schema":{"type":"integer","example":3171}},{"name":"tahun","in":"query","required":true,"description":"Tahun Hijriah empat angka.","schema":{"type":"integer","minimum":1300,"maximum":1499,"example":1447}}],"responses":{"200":{"description":"Berhasil","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResponsImsakiyah"}}}},"401":{"$ref":"#/components/responses/TanpaToken"},"404":{"description":"Wilayah tidak dikenal (`sebab: wilayah_tidak_ditemukan`), atau taqwim tahun itu belum diterbitkan (`sebab: taqwim_belum_terbit`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"$ref":"#/components/responses/IsianKeliru"},"429":{"$ref":"#/components/responses/KuotaHabis"},"503":{"$ref":"#/components/responses/SumberTerganggu"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Authorization: Bearer <token>"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Alternatif bila klien Anda sulit menyetel header Authorization."}},"headers":{"SisaKuota":{"description":"Sisa permintaan pada menit berjalan.","schema":{"type":"integer"}}},"schemas":{"ResponsWilayah":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"data":{"type":"array","items":{"type":"object","properties":{"kode":{"type":"integer"},"nama":{"type":"string"}}}},"sumber":{"type":"string"}}},"Jadwal":{"type":"object","properties":{"tanggal":{"type":"string","example":"Sabtu, 10 Oktober 2026"},"imsak":{"type":"string","example":"04:08"},"subuh":{"type":"string","example":"04:18"},"terbit":{"type":"string","example":"05:30"},"duha":{"type":"string","example":"05:57"},"zuhur":{"type":"string","example":"11:43"},"ashar":{"type":"string","example":"14:44"},"maghrib":{"type":"string","example":"17:49"},"isya":{"type":"string","example":"18:58"}}},"Wilayah":{"type":"object","properties":{"kode":{"type":"integer","example":3171},"nama":{"type":"string"},"tingkat":{"type":"string","enum":["kabupaten","kecamatan"]},"zona_waktu":{"type":"string","example":"UTC+7"}}},"ResponsJadwalHarian":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"data":{"$ref":"#/components/schemas/Jadwal"},"wilayah":{"$ref":"#/components/schemas/Wilayah"},"sumber":{"type":"string"}}},"ResponsJadwalBulanan":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Jadwal"}},"wilayah":{"$ref":"#/components/schemas/Wilayah"},"sumber":{"type":"string"}}},"Error":{"type":"object","properties":{"status":{"type":"string","example":"no"},"sebab":{"type":"string","example":"kuota_menit_habis"},"message":{"type":"string"},"errors":{"type":"object","description":"Hanya pada 422: isian yang bermasalah beserta alasannya.","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["status","sebab","message"],"description":"Bentuk baku seluruh error. Ambil keputusan di program Anda dari `sebab` — kalimat `message` dapat diperbaiki kapan saja, `sebab` tidak berubah."},"HariImsakiyah":{"type":"object","properties":{"hari_ramadan":{"type":"integer","example":1,"description":"Nomor hari Ramadan, mulai dari 1."},"tanggal":{"type":"string","format":"date","example":"2026-02-19"},"hijriah":{"$ref":"#/components/schemas/TanggalHijriah"},"imsak":{"type":"string","example":"04:26"},"subuh":{"type":"string","example":"04:36"},"terbit":{"type":"string","example":"05:52"},"duha":{"type":"string","example":"06:20"},"zuhur":{"type":"string","example":"12:10"},"ashar":{"type":"string","example":"15:29"},"maghrib":{"type":"string","example":"18:20"},"isya":{"type":"string","example":"19:33"}}},"ResponsImsakiyah":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"data":{"type":"object","properties":{"tahun_hijriah":{"type":"integer","example":1447},"mulai":{"type":"string","format":"date","example":"2026-02-19"},"selesai":{"type":"string","format":"date","example":"2026-03-20"},"jumlah_hari":{"type":"integer","example":30},"ketetapan":{"type":"string","enum":["resmi"],"example":"resmi","description":"Selalu \"resmi\": tahun yang belum ditetapkan ditolak, bukan diperkirakan."},"hari":{"type":"array","items":{"$ref":"#/components/schemas/HariImsakiyah"}}}},"wilayah":{"$ref":"#/components/schemas/Wilayah"},"sumber":{"type":"string","example":"Ditjen Bimas Islam, Kementerian Agama RI"}}},"TanggalHijriah":{"type":"object","nullable":true,"description":"Tanggal Hijriah untuk tanggal Masehi yang sama.\n\n`ketetapan` **wajib diperhatikan**. Bernilai `resmi` bila tanggalnya berasal dari Kalender Hijriah Indonesia terbitan Ditjen Bimas Islam — hasil sidang isbat, dan itulah tanggal yang berlaku. Bernilai `perkiraan` bila berada di luar jangkauan taqwim yang sudah terbit; nilainya lalu dihitung dengan Ummul Qura dan **dapat meleset satu hari**, sebab awal bulan ditetapkan lewat sidang isbat — ia keputusan, bukan hitungan.\n\nBernilai `null` bila tanggalnya tidak dapat ditentukan sama sekali. Jangan mengisi sendiri nilai yang null dengan hitungan Anda.","properties":{"tahun":{"type":"integer","example":1448},"bulan":{"type":"integer","minimum":1,"maximum":12,"example":8},"hari":{"type":"integer","minimum":1,"maximum":30,"example":11},"nama_bulan":{"type":"string","example":"Syakban"},"teks":{"type":"string","example":"11 Syakban 1448 H","description":"Siap tampil; ejaan nama bulannya sama dengan yang dipakai situs SIHAT."},"ketetapan":{"type":"string","enum":["resmi","perkiraan"],"example":"perkiraan"}}}},"responses":{"TanpaToken":{"description":"Token tidak disertakan, tidak dikenal, atau sudah dicabut.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"no","sebab":"token_tidak_sah","message":"Token API tidak dikenal atau sudah dicabut."}}}},"Terlarang":{"description":"Token dihentikan sementara, dicabut, kedaluwarsa, atau alamat klien tidak terdaftar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"ip tidak terdaftar":{"value":{"status":"no","sebab":"ip_tidak_terdaftar","message":"Permintaan datang dari alamat 103.7.14.21 yang tidak terdaftar pada token ini."}},"token dihentikan sementara":{"value":{"status":"no","sebab":"token_nonaktif","message":"Token API ini sedang dihentikan sementara. Hubungi Subdit Hisab dan Rukyat untuk mengaktifkannya kembali."}},"token dicabut — jangan diulang":{"value":{"status":"no","sebab":"token_dicabut","message":"Token API ini sudah dicabut dan tidak dapat dipakai lagi. Ajukan permohonan akses baru bila masih memerlukannya."}}}}}},"WilayahTakDikenal":{"description":"Kode wilayah tidak ditemukan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"no","sebab":"wilayah_tidak_ditemukan","message":"Kode wilayah tidak dikenal. Gunakan kode 4 digit (kabupaten/kota) atau 6 digit (kecamatan); daftar lengkapnya ada di /api/v1/public/wilayah/kabupaten."}}}},"IsianKeliru":{"description":"Parameter tidak sesuai ketentuan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"no","sebab":"isian_keliru","message":"Kode wilayah wajib diisi.","errors":{"wilayah":["Kode wilayah wajib diisi."]}}}}},"KuotaHabis":{"description":"Kuota per menit atau per hari terlampaui.","headers":{"Retry-After":{"description":"Detik sampai permintaan berikutnya dapat dilayani.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"description":"Batas pada jendela berjalan.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Selalu 0 pada keadaan ini.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"no","sebab":"kuota_menit_habis","message":"Kuota 60 permintaan per menit sudah terpakai. Coba lagi pada menit berikutnya."}}}},"SumberTerganggu":{"description":"Sumber perhitungan falak sedang tidak dapat dihubungi.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"no","sebab":"sumber_terganggu","message":"Sumber perhitungan falak sedang tidak dapat dihubungi. Silakan coba beberapa saat lagi."}}}}}}}