Prayer times and holidays are free forever — no API key at all. Build a complete app without spending a rupiah on API calls.
Two endpoints on API.MY.ID are completely free and need no API key: prayer times and national holidays. No quota, no points, no signup. This article builds a simple prayer reminder app on top of them.
The first call
No headers, no auth — just a GET:
curl "https://v1.api.my.id/sholat?city=jakarta"
{
"status": "success",
"data": {
"city": { "slug": "jakarta", "name": "Jakarta" },
"date": "2026-07-09",
"timezone": "WIB",
"jadwal": {
"imsak": "04:31", "subuh": "04:41", "terbit": "06:04", "dhuha": "06:28",
"dzuhur": "12:00", "ashar": "15:20", "maghrib": "17:53", "isya": "19:06"
}
}
}How the times are computed
Prayer times are not rows in a table — they are computed from the sun's position for the requested coordinates and date. We use the angle conventions commonly used by Kemenag: Fajr at −20°, Isha at −18°, sunrise and maghrib at −0.833° (accounting for atmospheric refraction and the solar radius), and Asr by the Shafi'i method. A +2 minute ihtiyat (safety margin) is added to Dhuhr and Maghrib.
The practical upshot: 54 cities are supported with correct time zones (WIB, WITA, WIT), and you can request any date — yesterday, today, or Ramadan next year.
Scheduling notifications
The right pattern: fetch the schedule once a day, then schedule local notifications. Do not poll the API every minute — the schedule does not change.
const PRAYERS = ['subuh', 'dzuhur', 'ashar', 'maghrib', 'isya'];
async function scheduleToday(city = 'jakarta') {
const res = await fetch(`https://v1.api.my.id/sholat?city=${city}`);
const { data } = await res.json();
for (const name of PRAYERS) {
const [h, m] = data.jadwal[name].split(':').map(Number);
const at = new Date();
at.setHours(h, m, 0, 0);
const delay = at - Date.now();
if (delay <= 0) continue; // already passed today
setTimeout(() => {
new Notification(`Time for ${name}`, {
body: `${data.jadwal[name]} ${data.timezone} — ${data.city.name}`,
});
}, delay);
}
}
// run on app open, and at midnight
scheduleToday();setTimeout above only illustrates the idea.Ramadan: imsak and iftar
For sahur and iftar timers, the two fields you need are already in the same response: imsak and maghrib. Since you can request any date, the whole Ramadan calendar can be fetched once and cached locally:
async function ramadanCalendar(city, start, days = 30) {
const out = [];
for (let i = 0; i < days; i++) {
const t = new Date(start);
t.setDate(t.getDate() + i);
const date = t.toISOString().slice(0, 10);
const res = await fetch(`https://v1.api.my.id/sholat?city=${city}&date=${date}`);
const { data } = await res.json();
out.push({ date, imsak: data.jadwal.imsak, iftar: data.jadwal.maghrib });
}
return out; // persist to localStorage / SQLite
}Bonus: the holiday calendar
The second free endpoint rounds out any calendar app. It returns national holidays and joint-leave days per the official SKB decree, with flags distinguishing the two:
curl "https://v1.api.my.id/holidays/upcoming?limit=3"
Because both are free and keyless, this entire app can run with no backend at all — call them straight from the client. This is the one case where we recommend that, precisely because there is no key to leak.
Ready to build?
Create a free account and get your API key — 5,000 free hits a month, and two endpoints that need no key at all.