Hayyalasalah › User Guide › Prayer Times API ↓ PDF

Prayer Times & Content API

Pull your mosque's prayer timetable — and now Qur'an verses, Hadith, Du'ās, announcements and events — straight into your own website, app, spreadsheet or a scheduled script, without logging into the portal. Written for anyone comfortable with a command line or a little code.

Base URL:

https://hayyalasalah.co.uk/prayer_times_api.php

One credential = one mosque

Your API key or login is tied to a single mosque, so you never send a mosque id. The endpoint always reads and writes your timetable only.

1. Authentication

Every request must be authenticated, and the credential goes in the Authorization header — never in the URL (that would leak it into logs). There are two ways to authenticate.

Option A — API key (recommended for scripts)

  1. Open the portal

    Sign in and open 🔑 API Keys in the left-hand menu.

  2. Generate a key

    Click Generate API key, choose Read & write (or Read only), and copy it now — the key is shown only once.

  3. Send it as a Bearer token

    On every request, add the header:

    Authorization: Bearer hpk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

You can create several keys (e.g. one per integration) and revoke any of them at any time from the same page. Keys are stored hashed — if one is lost, revoke it and generate a new one.

Option B — your MySQL login

If your mosque already has a MySQL username and password, use those directly with HTTP Basic authentication — no key needed. With curl that is just -u user:password:

curl -u YOUR_MYSQL_USER:YOUR_PASSWORD \
  "https://hayyalasalah.co.uk/prayer_times_api.php?date=2026-07-01"

MySQL logins always have read + write access.

2. Downloading prayer times

Send a GET request and choose the date window with one of these parameters:

ParameterMeaningExample
(none)Current calendar year?
dateA single day?date=2026-07-01
from + toInclusive range (max 750 days)?from=2026-01-01&to=2026-03-31
yearA whole year?year=2026
format=csvCSV instead of JSON?year=2026&format=csv

One day as JSON:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://hayyalasalah.co.uk/prayer_times_api.php?date=2026-07-01"

A full year as a CSV file:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://hayyalasalah.co.uk/prayer_times_api.php?year=2026&format=csv" \
  -o my_timetable_2026.csv

Sample JSON response:

{
  "ok": true,
  "mosque_id": "your_mosque",
  "from": "2026-07-01",
  "to": "2026-07-01",
  "count": 1,
  "prayer_times": [
    {
      "Date": "2026-07-01", "Day": "Wednesday",
      "Fajr_Begins": "02:49:00", "Fajr_Jamaat": "03:10:00",
      "Sunrise": "04:47:00",
      "Zohr_Begins": "13:10:00", "Zohr_Jamaat": "13:30:00",
      "Asr_Begins": "18:40:00",  "Asr_Jamaat": "19:30:00",
      "Magrib_Begins": "21:25:00", "Magrib_Jamaat": "21:25:00",
      "Isha_Begins": "22:41:00",  "Isha_Jamaat": "22:50:00",
      "Jumah_1": "13:30:00", "Jumah_2": "14:00:00", "Jumah_3": null
    }
  ]
}

3. Uploading prayer times

Send a POST request with your data as JSON or CSV (set Content-Type to match).

How updates work

Rows are matched by Date. Only the columns you send are changed — anything you leave out keeps its current value. New dates are added; dates you don't mention are untouched. Up to 750 rows per request. Each upload also snapshots the affected year on the server so it can be rolled back.

Writable columns

Day,
Fajr_Begins,   Fajr_Jamaat,
Imsak_Begins,  Sunrise,
Zohr_Begins,   Zohr_Jamaat,
Asr_Begins,    Asr_Jamaat,
Magrib_Begins, Magrib_Jamaat,
Isha_Begins,   Isha_Jamaat,
Midnight,
Jumah_1, Jumah_2, Jumah_3

JSON upload

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
        {"Date":"2026-07-01","Fajr_Jamaat":"03:10","Zohr_Jamaat":"13:30","Isha_Jamaat":"22:50"},
        {"Date":"2026-07-02","Fajr_Jamaat":"03:12","Isha_Jamaat":"22:49"}
      ]' \
  "https://hayyalasalah.co.uk/prayer_times_api.php"

You may also send an object like {"prayer_times": [ ... ]} instead of a bare array.

CSV upload

The first line must be the header row and include Date:

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary $'Date,Fajr_Jamaat,Isha_Jamaat\n2026-07-01,03:10,22:50\n2026-07-02,03:12,22:49' \
  "https://hayyalasalah.co.uk/prayer_times_api.php"

To upload an existing CSV file, point --data-binary at it:

curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @my_timetable.csv \
  "https://hayyalasalah.co.uk/prayer_times_api.php"

CSV upload with your MySQL login (Basic auth)

Every example on this page also works with your MySQL username and password instead of an API key — just swap the Authorization: Bearer header for curl's -u USER:PASSWORD. For a CSV file:

curl -X POST \
  -u YOUR_MYSQL_USER:YOUR_PASSWORD \
  -H "Content-Type: text/csv" \
  --data-binary @my_timetable.csv \
  "https://hayyalasalah.co.uk/prayer_times_api.php"

Or a quick inline test (uploads to a throwaway date so your live timetable is untouched):

curl -X POST \
  -u YOUR_MYSQL_USER:YOUR_PASSWORD \
  -H "Content-Type: text/csv" \
  --data-binary $'Date,Fajr_Jamaat,Isha_Jamaat\n2099-12-31,03:10,22:50' \
  "https://hayyalasalah.co.uk/prayer_times_api.php"
Use --data-binary, not -d

Send the CSV with --data-binary (for a file, --data-binary @file.csv). Plain -d strips the line breaks, which merges every row into one line and breaks the upload. The header row must be first and include Date.

Sample upload response:

{
  "ok": true,
  "mosque_id": "your_mosque",
  "rows_written": 2,
  "inserted": 1,
  "updated": 1,
  "failed": 0
}

After a successful upload your screens and apps pick up the change automatically — the cache is refreshed for you.

4. Content resources (Qur'an, Hadith, Du'ā, announcements, events)

Besides prayer times, the same endpoint can serve read-only content for you to display on your website or app. Add a resource parameter to a GET request:

GET …/prayer_times_api.php?resource=NAME

resourceWhat you getScope
quranA Qur'an verse (Arabic + English + reference)Shared library
hadithA Hadith (Arabic + English + source + narrator)Shared library
duaA Du'ā (title, Arabic, transliteration, English, occasion)Shared library
announcementsYour mosque's active ticker announcementsYour mosque
eventsYour mosque's upcoming eventsYour mosque
panelsYour enabled custom text panelsYour mosque

Options for quran, hadith and dua

ParameterMeaningExample
(none)Daily — a stable item that stays the same all day, then rotates. Great for a "verse of the day".?resource=quran
mode=randomA different random item on every request?resource=hadith&mode=random
id=NOne specific item by its id?resource=dua&id=132
limit=NHow many items to return (1–50, default 1)?resource=quran&limit=3

announcements and events always return your current items (default up to 20, limit up to 50); they need no mode. panels returns whatever custom panels you've enabled in the portal.

Every response has the same shape

{
  "ok": true,
  "resource": "quran",
  "count": 1,
  "items": [ … ],
  "server_time": "2026-07-02T21:47:46+01:00"
}

Verse of the day:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://hayyalasalah.co.uk/prayer_times_api.php?resource=quran"
{
  "ok": true, "resource": "quran", "count": 1, "mode": "daily",
  "items": [
    {
      "id": 1025,
      "arabic": "إِنَّ ٱلَّذِينَ كَفَرُوا۟ …",
      "english": "Indeed, those who disbelieve …",
      "surah_name": "Al-Baqarah", "surah_number": 2, "verse_number": 6,
      "reference": "Qur'an 2:6"
    }
  ]
}

Three random Hadith:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://hayyalasalah.co.uk/prayer_times_api.php?resource=hadith&mode=random&limit=3"

Your announcements:

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://hayyalasalah.co.uk/prayer_times_api.php?resource=announcements"
{
  "ok": true, "resource": "announcements", "count": 1,
  "items": [
    { "title": "Eid Mubarak", "message": "Eid prayer will be held at 8:00 AM …" }
  ]
}

Upcoming events return title, description, event_date, event_time and location; panels return slot, title and body. If a mosque has none configured you simply get "count": 0 and an empty items list — never an error.

Content is read-only

These resources are GET only — there is nothing to upload. A Read only API key is all you need, and it's the right choice for anything you put on a public website (see below).

5. Adding it to your website

Because content requests are read-only and safe to call from a browser, you can drop them straight into a web page. Cross-origin (CORS) requests are allowed from any domain, so this works on any site — WordPress, Wix, a static HTML page, anything.

Use a READ-ONLY key on a website

Anything in a web page's JavaScript is visible to visitors. Generate a Read only key for your site — it can fetch content but can never change your prayer times. Never put a read & write key (or your MySQL password) in a public page.

Copy-paste "Verse of the Day" widget. Paste this anywhere in your page's HTML and set your key:

<div id="hayya-verse" style="max-width:640px;margin:1em auto;text-align:center;
     font-family:system-ui,sans-serif">Loading…</div>

<script>
const HAYYA_KEY = "hpk_your_read_only_key_here";   // Read-only key from the portal
const HAYYA_API = "https://hayyalasalah.co.uk/prayer_times_api.php";

fetch(HAYYA_API + "?resource=quran", { headers: { "X-Api-Key": HAYYA_KEY } })
  .then(r => r.json())
  .then(d => {
    const v = d.items[0];
    document.getElementById("hayya-verse").innerHTML =
      '<p dir="rtl" lang="ar" style="font-size:1.6em;line-height:2">' + v.arabic + '</p>' +
      '<p style="font-style:italic">' + v.english + '</p>' +
      '<p style="opacity:.7">— ' + v.reference + '</p>';
  })
  .catch(() => { document.getElementById("hayya-verse").textContent = "Unavailable"; });
</script>

Announcements list. The same pattern shows your mosque's live announcements:

<ul id="hayya-news"></ul>
<script>
fetch("https://hayyalasalah.co.uk/prayer_times_api.php?resource=announcements",
      { headers: { "X-Api-Key": "hpk_your_read_only_key_here" } })
  .then(r => r.json())
  .then(d => {
    document.getElementById("hayya-news").innerHTML =
      d.items.map(a => "<li><strong>" + a.title + "</strong> — " + a.message + "</li>").join("");
  });
</script>
Tips for web pages

Use resource=quran (daily mode) rather than mode=random so every visitor sees the same verse and it changes once a day. For Arabic, set dir="rtl" and a font that supports Arabic. Both X-Api-Key: KEY and Authorization: Bearer KEY headers work.

6. A quick Python example

import requests

BASE = "https://hayyalasalah.co.uk/prayer_times_api.php"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# Download July 2026
r = requests.get(BASE, headers=HEADERS, params={"from": "2026-07-01", "to": "2026-07-31"})
print(r.json()["count"], "days")

# Upload two days
rows = [
    {"Date": "2026-07-01", "Fajr_Jamaat": "03:10", "Isha_Jamaat": "22:50"},
    {"Date": "2026-07-02", "Fajr_Jamaat": "03:12", "Isha_Jamaat": "22:49"},
]
r = requests.post(BASE, headers=HEADERS, json=rows)
print(r.json())

# Pull the daily Qur'an verse
r = requests.get(BASE, headers=HEADERS, params={"resource": "quran"})
print(r.json()["items"][0]["reference"])

7. Response codes

CodeMeaning
200Success
400Bad request — malformed date/time or invalid JSON/CSV. The error field explains what's wrong.
401Missing or invalid credentials
403Your key is read-only but you tried to upload
413Payload too large (over 2 MB, or more than 750 rows)
429Rate limit hit — wait and retry (see the Retry-After header)
503Service temporarily unavailable — retry shortly

On any error, the body looks like this, and nothing is written if validation fails — fix the row and resend:

{ "ok": false, "error": "Row 3: invalid time for Fajr_Jamaat ('25:99'). Use HH:MM or HH:MM:SS." }

8. Tips & good practice

How can I test safely without disturbing my live timetable?

Upload to a throwaway future date such as 2099-12-31, confirm it with a GET, then overwrite or ignore it. Your real dates are never touched unless you send them.

Do I have to send every column every time?

No — send only the columns you're changing. For example, a CSV of just Date,Fajr_Jamaat updates Fajr Jamā'ah and leaves everything else exactly as it was.

Should I use an API key or my MySQL login?

Prefer an API key for automated scripts — it's scoped and revocable, so you can rotate it without changing your database password. Use the MySQL login only for quick manual checks.

Can I show the verse of the day / announcements on my website?

Yes. Generate a Read only key and use the browser snippets in §5. Content requests allow cross-origin (CORS) calls from any domain, so they work on any website. Keep read & write keys off public pages.

Will the daily verse be the same for everyone?

Yes — resource=quran (and hadith/dua) in the default daily mode returns a fixed item that's identical for every visitor and rotates once per day. Use mode=random if you'd rather it change on every page load.

My key was exposed. What now?

Go to 🔑 API Keys in the portal, revoke it, and generate a new one. Revocation takes effect immediately.

How big can an upload be?

Up to 750 rows (about two years of dates) and 2 MB per request. For a full multi-year import, send it in batches — for example one month or one year at a time.

Keep your key secret

Treat your API key like a password. Never put it in a URL, a screenshot, or a public code repository. If in doubt, revoke and regenerate.