Developer API
Show events from Islamic Events on your own website or app, such as your mosque's upcoming lectures, classes and community events. It's free.
Request an API keyAPI key required
Every request needs a key. Keys are free.
Filter anything
By mosque, date, category, audience or distance.
Read-only
Simple GET requests that return JSON.
Quick start
Every endpoint is a GET request that returns JSON. The base URL is:
https://islamicevents.app/api/v1You need an API key. Replace YOUR_API_KEY below with yours.
Most integrations need only two calls. First, find your mosque's id:
curl -H "X-API-Key: YOUR_API_KEY" \
"https://islamicevents.app/api/v1/mosques?q=example"Then fetch its upcoming events:
curl -H "X-API-Key: YOUR_API_KEY" \
"https://islamicevents.app/api/v1/mosques/MOSQUE_ID/events?limit=20"Or from JavaScript on your server:
const res = await fetch(
"https://islamicevents.app/api/v1/mosques/MOSQUE_ID/events?limit=10",
{ headers: { "X-API-Key": process.env.ISLAMIC_EVENTS_API_KEY } }
)
const { mosque, data: events } = await res.json()
for (const event of events) {
const when = new Date(event.starts_at).toLocaleString()
console.log(`${when} — ${event.title} (${event.url})`)
}Can't find your mosque? It may not be listed yet. You can still use /events with a location filter.
Authentication
Every request must include an API key. Send it in the X-API-Key header:
X-API-Key: YOUR_API_KEYOr as a bearer token: Authorization: Bearer YOUR_API_KEY. Requests without a valid key get a 401 error.
Keys are free and issued by the Islamic Events team. Request a key below. Use one key per app or website.
- Keep your key private. Call the API from your server, not from code that runs in your visitors' browsers, where anyone can read the key.
- We count the requests made with each key. Keys that are misused can be revoked.
- If your key leaks, ask us for a new one and we'll revoke the old one.
Attribution (required)
Wherever you show data from the API, you must credit Islamic Events App and show the website islamicevents.app. Both must be visible to your users, next to the events. On the web, link to the website:
<p>
Events from Islamic Events App ·
<a href="https://islamicevents.app">islamicevents.app</a>
</p>In a mobile app or on a screen where links aren't possible, show the same text: Events from Islamic Events App · islamicevents.app. We may revoke keys that are used without this credit.
Request an API key
Tell us who you are and what you're building. We review every request and email your key to you. You can also email admin@islamicevents.app.
Endpoints
List mosques
Returns mosques sorted by name. Use it to look up the id of a mosque.
Query parameters
| Name | Type | Description |
|---|---|---|
| q | string | Mosque name contains this text (case-insensitive, max 100 characters). |
| city | string | Exact city match (case-insensitive), e.g. London. |
| country | string | Exact country match (case-insensitive). |
| limit | integer | Results per page, 1–100. Default 50. |
| offset | integer | Number of results to skip. Default 0. |
Response: { "data": [Mosque, …], "pagination": { … } }
Get a mosque
Response: { "data": Mosque }. Returns 404 if the id is unknown or isn't a UUID.
Events at a mosque
Returns upcoming events at the mosque, earliest first. Accepts all of the event filters except mosque_id. The response also contains the mosque itself:
{
"mosque": {
"id": "1b3e…",
"name": "Example Mosque",
"website_url": "https://example-mosque.org",
"address": "1 Example Road",
"city": "London",
"postcode": "E1 1AA",
"country": "United Kingdom",
"lat": 51.517,
"lng": -0.065
},
"data": [
{
"id": "7f2c…",
"slug": "tafsir-class-7f2c1a9e",
"url": "https://islamicevents.app/events/tafsir-class-7f2c1a9e",
"title": "Tafsir class",
"description": "Weekly tafsir of Surah al-Kahf.",
"category": "lecture",
"audience": "all",
"starts_at": "2026-10-09T18:00:00+00:00",
"ends_at": "2026-10-09T19:30:00+00:00",
"venue_type": "venue",
"location": { "name": "Main hall", "address": null, "lat": 51.517, "lng": -0.065 },
"image_url": null,
"image_position": 50,
"source_url": "https://example-mosque.org/events",
"is_featured": false,
"series_id": "7f2c…",
"recurrence": { "rule": "weekly", "days": [5], "week_of_month": null, "until": null },
"mosque": { "id": "1b3e…", "name": "Example Mosque", "…": "…" }
}
],
"pagination": { "limit": 20, "offset": 0, "total": 14 }
}List events
Returns upcoming events across all mosques and organisers, earliest first. This includes events that aren't linked to a mosque, whose mosque is null.
Response: { "data": [Event, …], "pagination": { … } }
Example: online sisters' events in November:
curl -H "X-API-Key: YOUR_API_KEY" \
"https://islamicevents.app/api/v1/events?audience=sisters&venue_type=online&from=2026-11-01&to=2026-11-30T23:59:59Z"Example: events within 10 km of a point:
curl -H "X-API-Key: YOUR_API_KEY" \
"https://islamicevents.app/api/v1/events?lat=51.5072&lng=-0.1276&radius=10"Event filters
/events and /mosques/{id}/events accept these query parameters. Combine them as you like.
Query parameters
| Name | Type | Description |
|---|---|---|
| mosque_id | UUID | Only events at this mosque. /events only; same as /mosques/{id}/events. |
| from | ISO 8601 | Earliest time. Default is now. Events still in progress at this time are included. |
| to | ISO 8601 | Latest start time. Must be on or after from (now, if from is not set). |
| category | string | prayer, lecture, community, fundraiser, eid or other. New categories may be added. |
| audience | enum | brothers, sisters or all. |
| venue_type | enum | venue (in person), online or hybrid. |
| featured | boolean | true or false. |
| lat, lng | number | Search around a point. Both are required together. |
| radius | number | Search radius in km when lat/lng are given. Above 0 and up to 500. Default 25. |
| limit | integer | Results per page, 1–100. Default 50. |
| offset | integer | Number of results to skip. Default 0. |
- Dates can be a date (
2026-11-01) or a date and time with a UTC offset (2026-11-01T18:00:00Z). - Results are always sorted by start time, including on radius searches.
- Radius searches only return events that have coordinates.
Get an event
Look up an event by its id or slug. Unlike the lists, this also returns past events. Response: { "data": Event }.
Prayer times
Returns the mosque's daily prayer timetable: begin and jamaat times for the five prayers, sunrise, and the Jumu'ah times in effect each day. mosque_id is required. Without it you get a 400. With no dates you get today.
Query parameters
| Name | Type | Description |
|---|---|---|
| mosque_id | UUID | Required on /prayer-times. On /mosques/{id}/prayer-times the id comes from the path. |
| date | YYYY-MM-DD | One day. Can't be combined with from/to. |
| from | YYYY-MM-DD | First day. Default is today (UK time). |
| to | YYYY-MM-DD | Last day. Default is from. A request covers at most 366 days. |
curl -H "X-API-Key: YOUR_API_KEY" \
"https://islamicevents.app/api/v1/prayer-times?mosque_id=MOSQUE_ID&from=2026-10-01&to=2026-10-31"{
"mosque": { "id": "1b3e…", "name": "Example Mosque", "…": "…" },
"data": [
{
"date": "2026-10-09",
"fajr": { "begins": "05:46", "jamaat": "06:15" },
"sunrise": "07:17",
"dhuhr": { "begins": "12:56", "jamaat": "13:30" },
"asr": { "begins": "15:52", "jamaat": "16:15" },
"maghrib": { "begins": "18:26", "jamaat": "18:31" },
"isha": { "begins": "19:51", "jamaat": "20:00" },
"jumuah": ["13:15", "13:45"],
"source_url": "https://example-mosque.org/prayer-times",
"updated_at": "2026-10-06T03:00:12+00:00"
}
],
"range": { "from": "2026-10-09", "to": "2026-10-09" }
}- We read the times from each mosque's own published timetable, daily. Days the timetable doesn't cover aren't returned, so
datacan be shorter than the range or empty. - Times are local to the mosque, exactly as printed. They have no time zone.
Objects
Mosque
| Name | Type | Description |
|---|---|---|
| id | UUID | Use it with /mosques/{id}/events. |
| name | string | |
| website_url | string | The mosque's website. |
| address, city, postcode, country | string | null | |
| lat, lng | number | null | Coordinates. |
Event
| Name | Type | Description |
|---|---|---|
| id | UUID | Unique for every occurrence. |
| slug | string | Stable, URL-friendly identifier. |
| url | string | The event page on Islamic Events. Link here when you show an event. |
| title | string | |
| description | string | null | Plain text. |
| category | string | See the category filter. |
| audience | string | brothers, sisters or all. |
| starts_at | ISO 8601 | Start time with UTC offset. |
| ends_at | ISO 8601 | null | End time, if known. |
| venue_type | string | venue, online or hybrid. |
| location | object | name, address, lat, lng. Any of them can be null. |
| image_url | string | null | Poster or cover image. |
| image_position | number | Vertical focus point of the image, 0–100 (%). Use as CSS object-position: center N%. |
| source_url | string | null | Where we found the event (for example the organiser's page). |
| is_featured | boolean | |
| series_id | UUID | null | Shared by every occurrence of a recurring event. null for one-off events. |
| recurrence | object | null | How the series repeats. See Recurring events. |
| mosque | Mosque | null | The mosque hosting the event, if known. |
| distance_km | number | Only present on radius searches. Distance from lat/lng, 1 decimal place. |
Prayer times (one day)
| Name | Type | Description |
|---|---|---|
| date | YYYY-MM-DD | |
| fajr, dhuhr, asr, maghrib, isha | object | { begins, jamaat }. Each is "HH:MM" (24-hour, mosque local time) or null if the timetable doesn't show it. If maghrib has no jamaat time, its begins time is used. |
| sunrise | string | null | "HH:MM". |
| jumuah | string[] | Jumu'ah (Friday prayer) times in effect that day, earliest first (up to 3). Set on every day, not only Fridays: the mosque's current times, or the ones its timetable gives from that Friday on. Empty only if the mosque has never published any. |
| source_url | string | null | The page, PDF or image the times were read from. |
| updated_at | ISO 8601 | When the timetable was last read. |
Recurring events
A recurring event, such as a weekly class, is returned once per occurrence. Each occurrence has its own id, slug and times. All occurrences share the same series_id, so you can group them. The recurrence object describes the pattern:
Recurrence
| Name | Type | Description |
|---|---|---|
| rule | string | daily, weekly or monthly. |
| days | number[] | null | Weekdays, 1 = Monday … 7 = Sunday. For example [1, 4] is Monday and Thursday. |
| week_of_month | number | null | Monthly only: 1–4 = 1st–4th of those weekdays in the month, -1 = last. null = same date every month. |
| until | string | null | Date of the last occurrence, or null if open-ended. |
Pagination
List endpoints return a pagination object with the limit and offset you used and the total number of matching results. To get the next page, add limit to offset.
async function allEvents(mosqueId) {
const events = []
let offset = 0
while (true) {
const res = await fetch(
`https://islamicevents.app/api/v1/mosques/${mosqueId}/events?limit=100&offset=${offset}`,
{ headers: { "X-API-Key": process.env.ISLAMIC_EVENTS_API_KEY } }
)
const page = await res.json()
events.push(...page.data)
offset += page.data.length
if (page.data.length === 0 || offset >= page.pagination.total) return events
}
}Errors
Errors use the matching HTTP status code and this body:
{ "error": { "code": "bad_request", "message": "limit must be an integer between 1 and 100" } }Error codes
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | A query parameter is invalid. The message says which one. |
| 401 | unauthorized | The API key is missing, wrong or revoked. |
| 404 | not_found | The mosque or event doesn't exist. |
| 500 | internal_error | Something went wrong on our side. Retry later. |
Fair use
- Cache responses on your side and don't request the same data more than about once a minute.
- When you show an event, link to its
urlso people can see the full and latest details. - Credit Islamic Events App and show islamicevents.app wherever the data appears. See Attribution.
- Event details and images belong to their organisers. See our Terms of Use.
- We may add new fields and categories to v1, so ignore any you don't recognise.