{"openapi":"3.0.3","info":{"title":"Urban Crisis & Crowd Evacuation Engine API","version":"0.2.0","description":"Vətəndaş təhlükəsizliyi və dispetçer analitikası. Səhv mesajları ?lang=az|en|ru ilə lokallaşır."},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"},"deviceToken":{"type":"apiKey","in":"header","name":"X-Device-Token"}}},"paths":{"/api/health":{"get":{"tags":["Sistem"],"summary":"Sağlamlıq yoxlaması + asılılıqların vəziyyəti: xarici xəritə/marşrut API-sinin dövrə kəsicisi (closed / open / half_open), xətanın növü, keş ölçüsü, mənbələr üzrə xidmət sayı. mode = online | offline-fallback","parameters":[],"responses":{"200":{"description":"{ ok, time, mode, dependencies: { routing: { mode, breaker: { state, retryInMs, lastError }, cacheSize, served } } }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/config":{"get":{"tags":["Sistem"],"summary":"SOS növləri, dillər, qayda həddləri","parameters":[],"responses":{"200":{"description":"{ sosTypes, languages, rules }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/i18n/{lang}":{"get":{"tags":["Sistem"],"summary":"Tərcümə lüğəti (az, en, ru)","parameters":[{"name":"lang","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ lang, messages }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/districts":{"get":{"tags":["Vətəndaş"],"summary":"Rayonlar siyahısı","parameters":[],"responses":{"200":{"description":"[ { id, name, lat, lng } ]"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/points":{"get":{"tags":["Vətəndaş"],"summary":"Aktiv toplanış məntəqələri və doluluq","parameters":[],"responses":{"200":{"description":"[ { id, name, type, capacity, occupied, occupancyPct } ]"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/roads":{"get":{"tags":["Vətəndaş"],"summary":"Yol şəbəkəsi (bağlı yollar daxil)","parameters":[],"responses":{"200":{"description":"[ { id, from, to, closed, congestion } ]"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/evacuation":{"get":{"tags":["Vətəndaş"],"summary":"Ən yaxın təhlükəsiz məntəqələr + tövsiyə olunan təxliyyə marşrutu. Məntəqə ≥90% dolu, yol bağlı və ya dolma sürəti səbəbindən çatanda dolacaqsa alternativ təklif olunur.","parameters":[{"name":"lat","in":"query","schema":{"type":"string"},"description":"number"},{"name":"lng","in":"query","schema":{"type":"string"},"description":"number"},{"name":"district","in":"query","schema":{"type":"string"},"description":"string (lat/lng əvəzinə)"},{"name":"accessible","in":"query","schema":{"type":"string"},"description":"1 = yalnız əlçatan (panduslu/maneəsiz) məntəqə və marşrut. Prioritet rollu imzalı cihaz üçün avtomatik"}],"responses":{"200":{"description":"{ origin, recommendedPointId, rerouted:{reasons[]}, noSafePoint, routing:{ mode: online | offline-fallback, degraded, sources: [external | cache | matrix | local], reason, cacheAgeSec }, accessible, noAccessibleRoute, needsTransport, points[ {status, projectedPct, fillingFast, accessible, access[], route:{geometry, distanceM, etaMin, source}} ] }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/session":{"post":{"tags":["Vətəndaş"],"summary":"İmzalı cihaz kimliyi alır (IP üzrə sürət limiti var)","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deviceId":{"description":"string (ixtiyari, əvvəlki kimliyi saxlamaq üçün)"}}}}}},"responses":{"200":{"description":"{ deviceId, token }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/sos":{"post":{"tags":["Vətəndaş"],"summary":"SOS göndərir. X-Device-Token olmadan da qəbul olunur (təsdiqsiz sayılır). Sürət limiti: imzalı cihaz üçün cihaz üzrə, imzasız sorğu üçün IP üzrə + ümumi büdcə (429 + Retry-After). Dublikat filtri: eyni göndərənin eyni növ SOS-u 60 san. ərzində yeni siqnal yaratmır (200, duplicate: true, repeats). Axın (flood) zamanı imzasız SOS qəbul olunur, amma karantinə düşür.","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"citizenId":{"description":"string (imzalı token varsa nəzərə alınmır)"},"type":{"description":"FIRE | COLLAPSE | FLOOD | MEDICAL"},"lat":{"description":"number"},"lng":{"description":"number"},"accuracy":{"description":"number (metr, ixtiyari)"},"note":{"description":"string ≤280"},"needs":{"description":"string[] (ixtiyari, yalnız imzalı cihaz: wheelchair | reduced_mobility | medical_transport. Pis dəyərlər səssiz atılır)"}}}}}},"responses":{"200":{"description":"201 yeni | 200 dublikat: { id, duplicate, repeats, status, createdAt, districtId, verified, priority (1 = Kritik Prioritet), needs[] }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"ixtiyari X-Device-Token"}},"/api/broadcasts":{"get":{"tags":["Vətəndaş"],"summary":"Dispetçerin göndərdiyi aktiv bildirişlər (yalnız vətəndaşın yerinə aid olanlar). Server vətəndaşın yerini saxlamır, tətbiq öz koordinatı ilə sorğu edir. Əlçatan istifadəçi üçün pandussuz məntəqə əlçatanla əvəzlənir","parameters":[{"name":"lat","in":"query","schema":{"type":"string"},"description":"number"},{"name":"lng","in":"query","schema":{"type":"string"},"description":"number"},{"name":"accessible","in":"query","schema":{"type":"string"},"description":"1 = əlçatan məntəqə əvəzləməsi (prioritet rol üçün avtomatik)"}],"responses":{"200":{"description":"{ broadcasts: [ { id, type, severity, text, point, substituted, expiresAt } ] }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"},"post":{"tags":["Dispetçer"],"summary":"Kütləvi bildiriş: növ evacuate (məntəqəyə köçün) | shelter | avoid_area | all_clear (əhatə etdiyi xəbərdarlıqları ləğv edir) | custom. Hədəf: bütün şəhər, rayonlar və ya radius","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"evacuate | shelter | avoid_area | all_clear | custom"},"severity":{"description":"info | warning | critical (yalnız custom)"},"target":{"description":"{ kind: all } | { kind: districts, districts: [id] } | { kind: radius, lat, lng, radiusM }"},"pointId":{"description":"string (evacuate üçün)"},"text":{"description":"{ az, en, ru } ≤280 (custom üçün məcburi)"},"expiresInMin":{"description":"number 1..720 (default 30)"}}}}}},"responses":{"200":{"description":"{ id, type, severity, target, reach, acks, status }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"broadcast:send","security":[{"bearer":[]}],"x-permission":"broadcast:send"}},"/api/broadcasts/{id}/ack":{"post":{"tags":["Vətəndaş"],"summary":"Vətəndaş bildirişi oxuduğunu təsdiqləyir (dispetçerdə \"oxudu\" sayğacı)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ id, acks }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/sms/inbound":{"post":{"tags":["Vətəndaş"],"summary":"SMS gateway webhook-u (internetsiz SOS). X-Gateway-Key tələb olunur. Komandalar: SOS [növ] [ehtiyac] <rayon | lat,lng>, TEHLUKESIZEM, YER <rayon>. Cavab mətni qayıdır","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"description":"string (nömrə, saxlanılmır, yalnız duzlu hash)"},"text":{"description":"string ≤320"}}}}}},"responses":{"200":{"description":"{ intent, reply, sosId?, priority? }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/profile":{"get":{"tags":["Vətəndaş"],"summary":"Cihazın rolü: citizen | priority (hərəkət məhdudiyyətli / xüsusi qayğı). X-Device-Token tələb olunur","parameters":[],"responses":{"200":{"description":"{ role, needs[], updatedAt }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"ixtiyari X-Device-Token"},"post":{"tags":["Vətəndaş"],"summary":"Prioritet SOS rolunu verir/ləğv edir. Rol imzalı cihaza bağlıdır; priority üçün ən azı bir ehtiyac lazımdır. Bundan sonra cihazın hər SOS-u Kritik Prioritet #1 alır","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"description":"citizen | priority"},"needs":{"description":"string[]: wheelchair | reduced_mobility | medical_transport"}}}}}},"responses":{"200":{"description":"{ role, needs[], updatedAt }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"ixtiyari X-Device-Token"}},"/api/sos/{id}":{"get":{"tags":["Vətəndaş"],"summary":"SOS-un gedişi: stage 0 ləğv, 2 briqada təyin olunur, 3 yardım yoldadır (+ETA)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ id, status, stage, brigade: { name, kind }, etaSec, etaMin, cancelMsLeft }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/sos/{id}/cancel":{"post":{"tags":["Vətəndaş"],"summary":"Öz SOS-unu 60 san. ərzində ləğv edir (\"səhv göndərdim\")","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"citizenId":{"description":"string (SOS sahibi)"}}}}}},"responses":{"200":{"description":"{ id, status }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/safe":{"post":{"tags":["Vətəndaş"],"summary":"\"Təhlükəsizəm\": açıq SOS-ları bağlayır","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"citizenId":{"description":"string"},"lat":{"description":"number?"},"lng":{"description":"number?"}}}}}},"responses":{"200":{"description":"{ citizenId, resolvedSos }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/points/{id}/checkin":{"post":{"tags":["Vətəndaş"],"summary":"Məntəqəyə gəliş qeydi (doluluğu artırır)","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"citizenId":{"description":"string"}}}}}},"responses":{"200":{"description":"məntəqə"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/auth/login":{"post":{"tags":["Dispetçer"],"summary":"Personal girişi. Uğurlu olarsa HS256 imzalı JWT qaytarır (rol tokenin içindədir). Ünvan və istifadəçi adı üzrə sürət limiti (brute-force qoruması)","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"username":{"description":"string"},"password":{"description":"string"}}}}}},"responses":{"200":{"description":"{ token, tokenType: Bearer, expiresInSec, user, role, permissions[] }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"açıq"}},"/api/auth/me":{"get":{"tags":["Dispetçer"],"summary":"Cari istifadəçi, rol və icazələr","parameters":[],"responses":{"200":{"description":"{ user, role, permissions[], expiresAt }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer JWT (istənilən personal rolu)","security":[{"bearer":[]}],"x-permission":"@staff"}},"/api/auth/refresh":{"post":{"tags":["Dispetçer"],"summary":"Etibarlı tokeni yenisi ilə əvəz edir (növbə ərzində yenidən giriş lazım olmasın)","parameters":[],"responses":{"200":{"description":"{ token, expiresInSec, … }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer JWT (istənilən personal rolu)","security":[{"bearer":[]}],"x-permission":"@staff"}},"/api/auth/logout":{"post":{"tags":["Dispetçer"],"summary":"Çıxış: token dərhal ləğv olunur (deny-list)","parameters":[],"responses":{"200":{"description":"{ ok, revoked }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer JWT (istənilən personal rolu)","security":[{"bearer":[]}],"x-permission":"@staff"}},"/api/auth/stream-ticket":{"post":{"tags":["Dispetçer"],"summary":"Canlı axın (SSE) üçün 30 saniyəlik birdəfəlik bilet. EventSource başlıq göndərə bilmir, JWT isə URL-ə yazılmır","parameters":[],"responses":{"200":{"description":"{ ticket, expiresInSec }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/dashboard":{"get":{"tags":["Dispetçer"],"summary":"Canlı panel snapshot-ı: SOS, məntəqələr, briqadalar, həyəcanlar (plan, typeCounts, undoMsLeft), karantin, hücum nəticəsi","parameters":[],"responses":{"200":{"description":"snapshot"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/stream":{"get":{"tags":["Dispetçer"],"summary":"Server-Sent Events: hər dəyişiklikdə \"snapshot\" hadisəsi. ?ticket= (birdəfəlik bilet) və ya Authorization başlığı","parameters":[],"responses":{"200":{"description":"text/event-stream"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/dashboard/history":{"get":{"tags":["Dispetçer"],"summary":"Zaman maşını: son N dəqiqənin kompakt kadrları","parameters":[{"name":"minutes","in":"query","schema":{"type":"string"},"description":"number ≤240 (default 120)"}],"responses":{"200":{"description":"{ frames[], t0, t1, everyMs }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/decisions":{"get":{"tags":["Dispetçer"],"summary":"Qərar jurnalı: kim, nə vaxt, hansı qərarı verdi (təsdiq, geri qaytarma, buraxma, yol, briqada, bildiriş) + sistem həyəcan hadisələri. IP/token/kimlik yoxdur","parameters":[{"name":"limit","in":"query","schema":{"type":"string"},"description":"number ≤200 (default 30)"}],"responses":{"200":{"description":"{ decisions: [ { id, t, actor, action, target, details } ] }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/broadcasts/{id}/cancel":{"post":{"tags":["Dispetçer"],"summary":"Aktiv bildirişi geri çəkir","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"bildiriş"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"broadcast:send","security":[{"bearer":[]}],"x-permission":"broadcast:send"}},"/api/rules":{"get":{"tags":["Dispetçer"],"summary":"Cari qayda həddləri","parameters":[],"responses":{"200":{"description":"rules"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/müşahidəçi/admin)","security":[{"bearer":[]}],"x-permission":"dashboard"}},"/api/alerts/{id}/approve":{"post":{"tags":["Dispetçer"],"summary":"Bir kliklə: SOS növünə uyğun ən yaxın azad briqadanı göndər (yanğın → yanğınsöndürən, tibbi → təcili tibbi, dağıntı/sel → xilasetmə) + ehtiyat məntəqəni aç (amber xəbərdarlıqda yalnız məntəqə). Dispetçer istənilən AZAD briqadanı brigadeId ilə seçib avtomatik seçimi üstələyə bilər. İdempotentdir.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"brigadeId":{"description":"string (ixtiyari; azad olmalıdır)"}}}}}},"responses":{"200":{"description":"alert (result: { brigadeId, etaMin, manual, match })"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"alert:approve"}},"/api/alerts/{id}/undo":{"post":{"tags":["Dispetçer"],"summary":"Təsdiqi 10 saniyə ərzində geri qaytarır","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"alert"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"alert:approve"}},"/api/sos/{id}/dispatch":{"post":{"tags":["Dispetçer"],"summary":"Tək SOS-a briqada göndər (4 nəfərlik həyəcan gözləmədən). Briqada SOS növünə görə avtomatik seçilir, dispetçer brigadeId ilə üstələyə bilər. Vətəndaşın telefonunda addımlar dərhal yenilənir. 10 san. ərzində geri qaytarıla bilər","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"brigadeId":{"description":"string (ixtiyari; azad olmalıdır)"}}}}}},"responses":{"200":{"description":"alert (type SOS_SINGLE, result: { brigadeId, etaMin, manual, match })"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"alert:approve"}},"/api/sos/{id}/release":{"post":{"tags":["Dispetçer"],"summary":"Karantindəki SOS-u \"doğrudur\" kimi buraxır","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"sos"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"alert:approve"}},"/api/roads/{id}/close":{"post":{"tags":["Dispetçer"],"summary":"Yolu bağlayır","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ id, closed }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"road:write"}},"/api/roads/{id}/open":{"post":{"tags":["Dispetçer"],"summary":"Yolu açır","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ id, closed }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"road:write"}},"/api/roads/{id}/accessibility":{"post":{"tags":["Dispetçer"],"summary":"Yol seqmentinin maneəsiz (pilləsiz/pandus) olub-olmadığı: əlçatan marşrut buna görə hesablanır","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"stepFree":{"description":"boolean"}}}}}},"responses":{"200":{"description":"{ id, stepFree }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"road:write"}},"/api/roads/{id}/congestion":{"post":{"tags":["Dispetçer"],"summary":"Yol tıxacı əmsalı","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"factor":{"description":"number ≥1"}}}}}},"responses":{"200":{"description":"yol"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"road:write"}},"/api/brigades/{id}/status":{"post":{"tags":["Dispetçer"],"summary":"Briqada statusu","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"available | dispatched | on_scene | offline"}}}}}},"responses":{"200":{"description":"briqada"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (dispetçer/admin)","security":[{"bearer":[]}],"x-permission":"brigade:write"}},"/api/sim/occupancy":{"post":{"tags":["Admin / simulyasiya"],"summary":"Məntəqənin doluluğunu təyin edir","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"pointId":{"description":"string"},"occupied":{"description":"number"}}}}}},"responses":{"200":{"description":"məntəqə"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/chaos":{"post":{"tags":["Admin / simulyasiya"],"summary":"Xarici xəritə API-sinin nasazlığını simulyasiya edir: mode = ok | http503 | slow (cavab 5 san.-dən gec) | error (şəbəkə xətası). ok seçiləndə dövrə kəsici dərhal sınaq sorğusu göndərir. Köhnə externalDown / externalLatencyMs də işləyir","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"description":"ok | http503 | slow | error"},"externalDown":{"description":"boolean (köhnə)"},"externalLatencyMs":{"description":"number (köhnə)"}}}}}},"responses":{"200":{"description":"chaos"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/rules":{"post":{"tags":["Admin / simulyasiya"],"summary":"Qayda həddlərini işləyərkən dəyişir (yoxlanılır). \"Təhlükəsizlik rejimi\": requireVerified","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"minDistinctReporters":{"description":"number"},"overcrowdPct":{"description":"number"},"requireVerified":{"description":"boolean"},"…":{"description":"bax /api/config"}}}}}},"responses":{"200":{"description":"rules"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/scenarios":{"get":{"tags":["Admin / simulyasiya"],"summary":"Demo ssenari adları","parameters":[],"responses":{"200":{"description":"[ name ]"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/sms":{"post":{"tags":["Admin / simulyasiya"],"summary":"SMS simulyatoru: gateway açarı olmadan eyni emal xəttini işlədir","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"from":{"description":"string"},"text":{"description":"string"}}}}}},"responses":{"200":{"description":"{ intent, reply }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/scenario":{"post":{"tags":["Admin / simulyasiya"],"summary":"Ssenarini real boru kəmərində işlədir","parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"cluster | fake_flood | mass_event | filling | overcrowd | api_outage | road_block | reset"}}}}}},"responses":{"200":{"description":"{ name, … }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}},"/api/sim/reset":{"post":{"tags":["Admin / simulyasiya"],"summary":"Bütün vəziyyəti sıfırlayır","parameters":[],"responses":{"200":{"description":"{ ok }"},"400":{"description":"Yanlış sorğu"},"401":{"description":"Token yoxdur"},"403":{"description":"İcazə yoxdur"},"429":{"description":"Sürət limiti"}},"x-auth":"Bearer (yalnız admin)","security":[{"bearer":[]}],"x-permission":"*"}}}}