{"openapi":"3.1.0","info":{"title":"Qivam API","description":"Open infrastructure for Muslim developers — mosque discovery and standalone location-based prayer utilities.\n\n**Authentication:**\n- Developer endpoints: `X-API-Key` header\n- Mosque admin endpoints: `Authorization: Bearer <token>` (JWT from `/auth/login`)","version":"1.0.0"},"servers":[{"url":"/v1"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key for developer access. Request one at /api-keys/request."},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token for mosque admin access. Obtain via POST /auth/login."}},"schemas":{},"parameters":{}},"paths":{"/mosques":{"get":{"parameters":[{"schema":{"type":"integer","minimum":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":20},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"city","in":"query"},{"schema":{"type":"string"},"required":false,"name":"country","in":"query"},{"schema":{"type":"array","items":{"type":"string"}},"required":false,"name":"facilities","in":"query"},{"schema":{"type":"string"},"required":false,"name":"source","in":"query"},{"schema":{"type":"string","enum":["unclaimed","claimed"]},"required":false,"name":"claim_status","in":"query"}],"responses":{"200":{"description":"List of mosques","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string","nullable":true},"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"type":"string"},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}},"source":{"type":"string"},"sourceId":{"type":"string","nullable":true},"claimStatus":{"type":"string","enum":["unclaimed","claimed"]},"claimedBy":{"type":"string","nullable":true},"claimedAt":{"type":"string","nullable":true},"verificationStatus":{"type":"string","enum":["pending","verified","rejected"]},"isPublished":{"type":"boolean"},"logoUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"prayerSchedule":{"type":"object","nullable":true,"properties":{"fajrAdhan":{"type":"string"},"fajrIqamah":{"type":"string","nullable":true},"dhuhrAdhan":{"type":"string"},"dhuhrIqamah":{"type":"string","nullable":true},"asrAdhan":{"type":"string"},"asrIqamah":{"type":"string","nullable":true},"maghribAdhan":{"type":"string"},"maghribIqamah":{"type":"string","nullable":true},"ishaAdhan":{"type":"string"},"ishaIqamah":{"type":"string","nullable":true},"jummahTimes":{"type":"array","items":{"type":"object","properties":{"adhan":{"type":"string"},"iqamah":{"type":"string","nullable":true}},"required":["adhan","iqamah"]}}},"required":["fajrAdhan","fajrIqamah","dhuhrAdhan","dhuhrIqamah","asrAdhan","asrIqamah","maghribAdhan","maghribIqamah","ishaAdhan","ishaIqamah","jummahTimes"]}},"required":["id","slug","name","address","city","postcode","country","website","lat","lng","timezone","facilities","source","sourceId","claimStatus","claimedBy","claimedAt","verificationStatus","isPublished","logoUrl","coverUrl","createdAt","updatedAt","prayerSchedule"]}},"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}},"required":["data","page","limit","total","totalPages"]}}}}}},"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"address":{"type":"string","minLength":1,"maxLength":500},"city":{"type":"string","minLength":1,"maxLength":100},"postcode":{"type":"string","minLength":1,"maxLength":20},"country":{"type":"string","minLength":2,"maxLength":2},"phone":{"type":"string","nullable":true,"maxLength":20},"email":{"type":"string","nullable":true,"format":"email"},"website":{"type":"string","nullable":true,"format":"uri"},"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"timezone":{"type":"string","minLength":1,"maxLength":64},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}}},"required":["name","address","city","postcode","country","lat","lng"]}}}},"responses":{"201":{"description":"Mosque created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string","nullable":true},"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"type":"string"},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}},"source":{"type":"string"},"sourceId":{"type":"string","nullable":true},"claimStatus":{"type":"string","enum":["unclaimed","claimed"]},"claimedBy":{"type":"string","nullable":true},"claimedAt":{"type":"string","nullable":true},"verificationStatus":{"type":"string","enum":["pending","verified","rejected"]},"isPublished":{"type":"boolean"},"logoUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"prayerSchedule":{"type":"object","nullable":true,"properties":{"fajrAdhan":{"type":"string"},"fajrIqamah":{"type":"string","nullable":true},"dhuhrAdhan":{"type":"string"},"dhuhrIqamah":{"type":"string","nullable":true},"asrAdhan":{"type":"string"},"asrIqamah":{"type":"string","nullable":true},"maghribAdhan":{"type":"string"},"maghribIqamah":{"type":"string","nullable":true},"ishaAdhan":{"type":"string"},"ishaIqamah":{"type":"string","nullable":true},"jummahTimes":{"type":"array","items":{"type":"object","properties":{"adhan":{"type":"string"},"iqamah":{"type":"string","nullable":true}},"required":["adhan","iqamah"]}}},"required":["fajrAdhan","fajrIqamah","dhuhrAdhan","dhuhrIqamah","asrAdhan","asrIqamah","maghribAdhan","maghribIqamah","ishaAdhan","ishaIqamah","jummahTimes"]}},"required":["id","slug","name","address","city","postcode","country","website","lat","lng","timezone","facilities","source","sourceId","claimStatus","claimedBy","claimedAt","verificationStatus","isPublished","logoUrl","coverUrl","createdAt","updatedAt","prayerSchedule"]}}}},"409":{"description":"Mosque already exists","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/mosques/nearby":{"get":{"parameters":[{"schema":{"type":"number","nullable":true,"minimum":-90,"maximum":90},"required":false,"name":"lat","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":-180,"maximum":180},"required":false,"name":"lng","in":"query"},{"schema":{"type":"number","minimum":0.1,"maximum":50},"required":false,"name":"radius_km","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Nearby mosques","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string","nullable":true},"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"type":"string"},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}},"source":{"type":"string"},"sourceId":{"type":"string","nullable":true},"claimStatus":{"type":"string","enum":["unclaimed","claimed"]},"claimedBy":{"type":"string","nullable":true},"claimedAt":{"type":"string","nullable":true},"verificationStatus":{"type":"string","enum":["pending","verified","rejected"]},"isPublished":{"type":"boolean"},"logoUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"prayerSchedule":{"type":"object","nullable":true,"properties":{"fajrAdhan":{"type":"string"},"fajrIqamah":{"type":"string","nullable":true},"dhuhrAdhan":{"type":"string"},"dhuhrIqamah":{"type":"string","nullable":true},"asrAdhan":{"type":"string"},"asrIqamah":{"type":"string","nullable":true},"maghribAdhan":{"type":"string"},"maghribIqamah":{"type":"string","nullable":true},"ishaAdhan":{"type":"string"},"ishaIqamah":{"type":"string","nullable":true},"jummahTimes":{"type":"array","items":{"type":"object","properties":{"adhan":{"type":"string"},"iqamah":{"type":"string","nullable":true}},"required":["adhan","iqamah"]}}},"required":["fajrAdhan","fajrIqamah","dhuhrAdhan","dhuhrIqamah","asrAdhan","asrIqamah","maghribAdhan","maghribIqamah","ishaAdhan","ishaIqamah","jummahTimes"]},"distance_km":{"type":"number"}},"required":["id","slug","name","address","city","postcode","country","website","lat","lng","timezone","facilities","source","sourceId","claimStatus","claimedBy","claimedAt","verificationStatus","isPublished","logoUrl","coverUrl","createdAt","updatedAt","prayerSchedule","distance_km"]}}},"required":["data"]}}}}}}},"/mosques/{id}":{"get":{"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Mosque details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string","nullable":true},"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"type":"string"},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}},"source":{"type":"string"},"sourceId":{"type":"string","nullable":true},"claimStatus":{"type":"string","enum":["unclaimed","claimed"]},"claimedBy":{"type":"string","nullable":true},"claimedAt":{"type":"string","nullable":true},"verificationStatus":{"type":"string","enum":["pending","verified","rejected"]},"isPublished":{"type":"boolean"},"logoUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"prayerSchedule":{"type":"object","nullable":true,"properties":{"fajrAdhan":{"type":"string"},"fajrIqamah":{"type":"string","nullable":true},"dhuhrAdhan":{"type":"string"},"dhuhrIqamah":{"type":"string","nullable":true},"asrAdhan":{"type":"string"},"asrIqamah":{"type":"string","nullable":true},"maghribAdhan":{"type":"string"},"maghribIqamah":{"type":"string","nullable":true},"ishaAdhan":{"type":"string"},"ishaIqamah":{"type":"string","nullable":true},"jummahTimes":{"type":"array","items":{"type":"object","properties":{"adhan":{"type":"string"},"iqamah":{"type":"string","nullable":true}},"required":["adhan","iqamah"]}}},"required":["fajrAdhan","fajrIqamah","dhuhrAdhan","dhuhrIqamah","asrAdhan","asrIqamah","maghribAdhan","maghribIqamah","ishaAdhan","ishaIqamah","jummahTimes"]}},"required":["id","slug","name","address","city","postcode","country","website","lat","lng","timezone","facilities","source","sourceId","claimStatus","claimedBy","claimedAt","verificationStatus","isPublished","logoUrl","coverUrl","createdAt","updatedAt","prayerSchedule"]}}}},"404":{"description":"Mosque not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200},"address":{"type":"string","minLength":1,"maxLength":500},"city":{"type":"string","minLength":1,"maxLength":100},"postcode":{"type":"string","minLength":1,"maxLength":20},"country":{"type":"string","minLength":2,"maxLength":2},"phone":{"type":"string","nullable":true,"maxLength":20},"email":{"type":"string","nullable":true,"format":"email"},"website":{"type":"string","nullable":true,"format":"uri"},"lat":{"type":"number","minimum":-90,"maximum":90},"lng":{"type":"number","minimum":-180,"maximum":180},"timezone":{"type":"string","minLength":1,"maxLength":64},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}}}}}}},"responses":{"200":{"description":"Mosque updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string","nullable":true},"lat":{"type":"number"},"lng":{"type":"number"},"timezone":{"type":"string"},"facilities":{"type":"array","items":{"type":"string","enum":["parking","wheelchair_access","womens_area","wudu_area","funeral_services","islamic_school","library","community_hall"]}},"source":{"type":"string"},"sourceId":{"type":"string","nullable":true},"claimStatus":{"type":"string","enum":["unclaimed","claimed"]},"claimedBy":{"type":"string","nullable":true},"claimedAt":{"type":"string","nullable":true},"verificationStatus":{"type":"string","enum":["pending","verified","rejected"]},"isPublished":{"type":"boolean"},"logoUrl":{"type":"string","nullable":true},"coverUrl":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"prayerSchedule":{"type":"object","nullable":true,"properties":{"fajrAdhan":{"type":"string"},"fajrIqamah":{"type":"string","nullable":true},"dhuhrAdhan":{"type":"string"},"dhuhrIqamah":{"type":"string","nullable":true},"asrAdhan":{"type":"string"},"asrIqamah":{"type":"string","nullable":true},"maghribAdhan":{"type":"string"},"maghribIqamah":{"type":"string","nullable":true},"ishaAdhan":{"type":"string"},"ishaIqamah":{"type":"string","nullable":true},"jummahTimes":{"type":"array","items":{"type":"object","properties":{"adhan":{"type":"string"},"iqamah":{"type":"string","nullable":true}},"required":["adhan","iqamah"]}}},"required":["fajrAdhan","fajrIqamah","dhuhrAdhan","dhuhrIqamah","asrAdhan","asrIqamah","maghribAdhan","maghribIqamah","ishaAdhan","ishaIqamah","jummahTimes"]}},"required":["id","slug","name","address","city","postcode","country","website","lat","lng","timezone","facilities","source","sourceId","claimStatus","claimedBy","claimedAt","verificationStatus","isPublished","logoUrl","coverUrl","createdAt","updatedAt","prayerSchedule"]}}}},"404":{"description":"Mosque not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/prayer-times/methods":{"get":{"responses":{"200":{"description":"Supported prayer time calculation methods","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"fajrAngle":{"type":"number"},"isha":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["angle"]},"degrees":{"type":"number"}},"required":["type","degrees"]},{"type":"object","properties":{"type":{"type":"string","enum":["minutes"]},"minutes":{"type":"number"},"ramadanMinutes":{"type":"number"}},"required":["type","minutes"]}]}},"required":["id","name","fajrAngle","isha"]}}},"required":["data"]}}}}}}},"/prayer-times/calculate":{"get":{"parameters":[{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"date","in":"query"},{"schema":{"type":"string","enum":["mwl","isna","umm_al_qura","egyptian","karachi","tehran","jafari","gulf","kuwait","qatar","diyanet","jakim","muis","kemenag","tunisia","algeria","morocco","france","russia","dubai","jordan"]},"required":false,"name":"method","in":"query"},{"schema":{"type":"string","enum":["standard","hanafi"],"default":"standard"},"required":false,"name":"madhab","in":"query"},{"schema":{"type":"string","enum":["middle_of_night","one_seventh","angle_based","none"],"default":"middle_of_night"},"required":false,"name":"high_latitude_rule","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"fajr_adjustment","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"sunrise_adjustment","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"dhuhr_adjustment","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"asr_adjustment","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"maghrib_adjustment","in":"query"},{"schema":{"type":"integer","nullable":true,"minimum":-30,"maximum":30},"required":false,"name":"isha_adjustment","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":-90,"maximum":90},"required":false,"name":"latitude","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":-180,"maximum":180},"required":false,"name":"longitude","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"maximum":10000},"required":false,"name":"elevation","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"timezone","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":30,"default":1},"required":false,"name":"days","in":"query"}],"responses":{"200":{"description":"Calculated prayer times for given coordinates","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string"},"prayers":{"type":"object","properties":{"fajr":{"type":"string"},"sunrise":{"type":"string"},"dhuhr":{"type":"string"},"asr":{"type":"string"},"maghrib":{"type":"string"},"isha":{"type":"string"},"midnight":{"type":"string"}},"required":["fajr","sunrise","dhuhr","asr","maghrib","isha","midnight"]},"meta":{"type":"object","properties":{"method":{"type":"string"},"madhab":{"type":"string"},"timezone":{"type":"string"},"coordinates":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}},"required":["latitude","longitude"]}},"required":["method","madhab","timezone","coordinates"]}},"required":["date","prayers","meta"]}}},"required":["data"]},{"type":"object","properties":{"date":{"type":"string"},"prayers":{"type":"object","properties":{"fajr":{"type":"string"},"sunrise":{"type":"string"},"dhuhr":{"type":"string"},"asr":{"type":"string"},"maghrib":{"type":"string"},"isha":{"type":"string"},"midnight":{"type":"string"}},"required":["fajr","sunrise","dhuhr","asr","maghrib","isha","midnight"]},"meta":{"type":"object","properties":{"method":{"type":"string"},"madhab":{"type":"string"},"timezone":{"type":"string"},"coordinates":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}},"required":["latitude","longitude"]}},"required":["method","madhab","timezone","coordinates"]}},"required":["date","prayers","meta"]}]}}}}}}},"/prayer-times/qibla":{"get":{"parameters":[{"schema":{"type":"number","nullable":true,"minimum":-90,"maximum":90},"required":false,"name":"latitude","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":-180,"maximum":180},"required":false,"name":"longitude","in":"query"}],"responses":{"200":{"description":"Qibla direction from given coordinates","content":{"application/json":{"schema":{"type":"object","properties":{"bearing":{"type":"number"},"distance":{"type":"number"},"coordinates":{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}},"required":["latitude","longitude"]}},"required":["bearing","distance","coordinates"]}}}}}}},"/api-keys/request":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"contactEmail":{"type":"string","format":"email"}},"required":["name","contactEmail"]}}}},"responses":{"201":{"description":"API key created","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"prefix":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"}},"required":["key","prefix","name","isActive"]}}}}}}},"/api-keys/{prefix}":{"get":{"parameters":[{"schema":{"type":"string"},"required":true,"name":"prefix","in":"path"}],"responses":{"200":{"description":"API key status","content":{"application/json":{"schema":{"type":"object","properties":{"prefix":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string"}},"required":["prefix","name","isActive","createdAt"]}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/analytics/opt-out":{"post":{"security":[{"apiKey":[]}],"responses":{"200":{"description":"Analytics logging disabled for this key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/analytics/opt-in":{"post":{"security":[{"apiKey":[]}],"responses":{"200":{"description":"Analytics logging enabled for this key","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/auth/register":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","minLength":1,"maxLength":100},"password":{"type":"string","minLength":8,"maxLength":128}},"required":["email","name","password"]}}}},"responses":{"201":{"description":"Admin registered","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"admin":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"mosqueId":{"type":"string","nullable":true,"format":"uuid"},"createdAt":{"type":"string"}},"required":["id","email","name","mosqueId","createdAt"]}},"required":["token","admin"]}}}},"409":{"description":"Email already registered","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/login":{"post":{"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":1}},"required":["email","password"]}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"admin":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"name":{"type":"string"},"mosqueId":{"type":"string","nullable":true,"format":"uuid"},"createdAt":{"type":"string"}},"required":["id","email","name","mosqueId","createdAt"]}},"required":["token","admin"]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}}}}