Developers
Tafheem Research Lab runs on a JSON API. The Quran text endpoints are open to read without an account; anything that writes data needs a login token.
Base URL
https://tafheemulquran.net/api/v1The full, always-current list of endpoints and their request and response shapes:
Ayahs
No authentication needed.
List and look up
# All ayahs, paginated (limit defaults to 100, max 500)
GET /api/v1/ayahs/?skip=0&limit=10
# One surah, optionally a range of ayahs within it
GET /api/v1/ayahs/surah/2
GET /api/v1/ayahs/surah/2?from=1&to=5
# One ayah
GET /api/v1/ayahs/surah/2/ayah/3
# By juz, rukoo or mushaf page
GET /api/v1/ayahs/juz/1
GET /api/v1/ayahs/rukoo/1
GET /api/v1/ayahs/page/1Each ayah looks like this:
{
"id": 1,
"surah_id": 1,
"number": 1,
"arabic_text": "الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ",
"juz_number": 1,
"page_number": 1,
"rukoo_number": 1,
"hizb_number": 1,
"rub_el_hizb_number": 1,
"sajdah": false,
"transliteration": null,
"audio_url": null
}Search
The search term goes in query. Arabic is matched without diacritics, so plain letters find fully vowelled text.
# Ayah text, translations and tafseer together
# Optional: surah_id, language, translator, limit (default 20, max 300)
GET /api/v1/ayahs/search?query=الرحمن&limit=10
# Arabic ayah text only
GET /api/v1/ayahs/search/arabic?query=الرحمنBoth return an object with query, result_count and a results list.
Statistics
GET /api/v1/ayahs/stats
{
"total_ayahs": 6236,
"total_surahs": 114,
"total_rukoos": 556,
"total_juz": 30,
"total_pages": 604,
"surah_with_most_ayahs": { "surah_id": 2, "ayah_count": 286 }
}
# One surah
GET /api/v1/ayahs/surah/2/statsAuthentication
Register, confirm the email address from the message we send, then log in to get a token.
Register
POST /api/v1/users/register
Content-Type: application/json
{
"email": "developer@example.com",
"name": "Developer Name",
"password": "at-least-8-characters",
"password_confirmation": "at-least-8-characters"
}Log in
POST /api/v1/users/login
Content-Type: application/json
{
"email": "developer@example.com",
"password": "at-least-8-characters"
}
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "developer@example.com",
"username": "developer",
"role": "user",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}Use the token
Send it as a Bearer token on every request that needs a login:
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://tafheemulquran.net/api/v1/users/meArticles
Reading is open; creating, editing and deleting need a token.
# List (optional: status, user_id, search, skip, limit up to 100)
GET /api/v1/articles?status=published&skip=0&limit=20
# One article
GET /api/v1/articles/{article_id}
# Create - title and content are required
POST /api/v1/articles
Authorization: Bearer YOUR_TOKEN
Content-Type: application/json
{
"title": "Understanding Surah Al-Fatiha",
"content": "The Opening Chapter...",
"category": "tafseer",
"status": "draft",
"type": "public"
}
# Update / delete (author, collaborator or admin)
PUT /api/v1/articles/{article_id}
DELETE /api/v1/articles/{article_id}Rate limits
Limits are set per endpoint and counted per IP address. They are tightest on account endpoints (login allows 5 attempts per 15 minutes) and looser on writes such as creating an article (20 per 15 minutes). Going over returns 429:
{
"error": "Too many requests",
"detail": "Rate limit exceeded. Please try again later."
}Please cache what you fetch. The Quran text does not change, so there is rarely a reason to request the same ayah twice.
Questions and problems
Found something wrong, or need an endpoint that is not here? Tell us through the feedback page.