Urban Crisis Engine API

OpenAPI: /api/openapi.json · Səhv mesajları ?lang=az|en|ru · Personal: POST /api/auth/login → Authorization: Bearer <JWT>

Sistem

GET/api/healthaçıq

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

→ { ok, time, mode, dependencies: { routing: { mode, breaker: { state, retryInMs, lastError }, cacheSize, served } } }
GET/api/configaçıq

SOS növləri, dillər, qayda həddləri

→ { sosTypes, languages, rules }
GET/api/i18n/:langaçıq

Tərcümə lüğəti (az, en, ru)

→ { lang, messages }

Vətəndaş

GET/api/districtsaçıq

Rayonlar siyahısı

→ [ { id, name, lat, lng } ]
GET/api/pointsaçıq

Aktiv toplanış məntəqələri və doluluq

→ [ { id, name, type, capacity, occupied, occupancyPct } ]
GET/api/roadsaçıq

Yol şəbəkəsi (bağlı yollar daxil)

→ [ { id, from, to, closed, congestion } ]
GET/api/evacuationaçıq

Ə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.

Query
latnumber
lngnumber
districtstring (lat/lng əvəzinə)
accessible1 = yalnız əlçatan (panduslu/maneəsiz) məntəqə və marşrut. Prioritet rollu imzalı cihaz üçün avtomatik
→ { 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}} ] }
POST/api/sessionaçıq

İmzalı cihaz kimliyi alır (IP üzrə sürət limiti var)

JSON body
deviceIdstring (ixtiyari, əvvəlki kimliyi saxlamaq üçün)
→ { deviceId, token }
POST/api/sosixtiyari X-Device-Token

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.

JSON body
citizenIdstring (imzalı token varsa nəzərə alınmır)
typeFIRE | COLLAPSE | FLOOD | MEDICAL
latnumber
lngnumber
accuracynumber (metr, ixtiyari)
notestring ≤280
needsstring[] (ixtiyari, yalnız imzalı cihaz: wheelchair | reduced_mobility | medical_transport. Pis dəyərlər səssiz atılır)
→ 201 yeni | 200 dublikat: { id, duplicate, repeats, status, createdAt, districtId, verified, priority (1 = Kritik Prioritet), needs[] }
GET/api/broadcastsaçıq

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

Query
latnumber
lngnumber
accessible1 = əlçatan məntəqə əvəzləməsi (prioritet rol üçün avtomatik)
→ { broadcasts: [ { id, type, severity, text, point, substituted, expiresAt } ] }
POST/api/broadcasts/:id/ackaçıq

Vətəndaş bildirişi oxuduğunu təsdiqləyir (dispetçerdə "oxudu" sayğacı)

→ { id, acks }
POST/api/sms/inboundaçıq

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

JSON body
fromstring (nömrə, saxlanılmır, yalnız duzlu hash)
textstring ≤320
→ { intent, reply, sosId?, priority? }
GET/api/profileixtiyari X-Device-Token

Cihazın rolü: citizen | priority (hərəkət məhdudiyyətli / xüsusi qayğı). X-Device-Token tələb olunur

→ { role, needs[], updatedAt }
POST/api/profileixtiyari X-Device-Token

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

JSON body
rolecitizen | priority
needsstring[]: wheelchair | reduced_mobility | medical_transport
→ { role, needs[], updatedAt }
GET/api/sos/:idaçıq

SOS-un gedişi: stage 0 ləğv, 2 briqada təyin olunur, 3 yardım yoldadır (+ETA)

→ { id, status, stage, brigade: { name, kind }, etaSec, etaMin, cancelMsLeft }
POST/api/sos/:id/cancelaçıq

Öz SOS-unu 60 san. ərzində ləğv edir ("səhv göndərdim")

JSON body
citizenIdstring (SOS sahibi)
→ { id, status }
POST/api/safeaçıq

"Təhlükəsizəm": açıq SOS-ları bağlayır

JSON body
citizenIdstring
latnumber?
lngnumber?
→ { citizenId, resolvedSos }
POST/api/points/:id/checkinaçıq

Məntəqəyə gəliş qeydi (doluluğu artırır)

JSON body
citizenIdstring
→ məntəqə

Dispetçer

POST/api/auth/loginaçıq

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ı)

JSON body
usernamestring
passwordstring
→ { token, tokenType: Bearer, expiresInSec, user, role, permissions[] }
GET/api/auth/meBearer JWT (istənilən personal rolu)

Cari istifadəçi, rol və icazələr

→ { user, role, permissions[], expiresAt }
POST/api/auth/refreshBearer JWT (istənilən personal rolu)

Etibarlı tokeni yenisi ilə əvəz edir (növbə ərzində yenidən giriş lazım olmasın)

→ { token, expiresInSec, … }
POST/api/auth/logoutBearer JWT (istənilən personal rolu)

Çıxış: token dərhal ləğv olunur (deny-list)

→ { ok, revoked }
POST/api/auth/stream-ticketBearer (dispetçer/müşahidəçi/admin)

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

→ { ticket, expiresInSec }
GET/api/dashboardBearer (dispetçer/müşahidəçi/admin)

Canlı panel snapshot-ı: SOS, məntəqələr, briqadalar, həyəcanlar (plan, typeCounts, undoMsLeft), karantin, hücum nəticəsi

→ snapshot
GET/api/streamBearer (dispetçer/müşahidəçi/admin)

Server-Sent Events: hər dəyişiklikdə "snapshot" hadisəsi. ?ticket= (birdəfəlik bilet) və ya Authorization başlığı

→ text/event-stream
GET/api/dashboard/historyBearer (dispetçer/müşahidəçi/admin)

Zaman maşını: son N dəqiqənin kompakt kadrları

Query
minutesnumber ≤240 (default 120)
→ { frames[], t0, t1, everyMs }
GET/api/decisionsBearer (dispetçer/müşahidəçi/admin)

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

Query
limitnumber ≤200 (default 30)
→ { decisions: [ { id, t, actor, action, target, details } ] }
POST/api/broadcastsbroadcast:send

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

JSON body
typeevacuate | shelter | avoid_area | all_clear | custom
severityinfo | warning | critical (yalnız custom)
target{ kind: all } | { kind: districts, districts: [id] } | { kind: radius, lat, lng, radiusM }
pointIdstring (evacuate üçün)
text{ az, en, ru } ≤280 (custom üçün məcburi)
expiresInMinnumber 1..720 (default 30)
→ { id, type, severity, target, reach, acks, status }
POST/api/broadcasts/:id/cancelbroadcast:send

Aktiv bildirişi geri çəkir

→ bildiriş
GET/api/rulesBearer (dispetçer/müşahidəçi/admin)

Cari qayda həddləri

→ rules
POST/api/alerts/:id/approveBearer (dispetçer/admin)

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.

JSON body
brigadeIdstring (ixtiyari; azad olmalıdır)
→ alert (result: { brigadeId, etaMin, manual, match })
POST/api/alerts/:id/undoBearer (dispetçer/admin)

Təsdiqi 10 saniyə ərzində geri qaytarır

→ alert
POST/api/sos/:id/dispatchBearer (dispetçer/admin)

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

JSON body
brigadeIdstring (ixtiyari; azad olmalıdır)
→ alert (type SOS_SINGLE, result: { brigadeId, etaMin, manual, match })
POST/api/sos/:id/releaseBearer (dispetçer/admin)

Karantindəki SOS-u "doğrudur" kimi buraxır

→ sos
POST/api/roads/:id/closeBearer (dispetçer/admin)

Yolu bağlayır

→ { id, closed }
POST/api/roads/:id/openBearer (dispetçer/admin)

Yolu açır

→ { id, closed }
POST/api/roads/:id/accessibilityBearer (dispetçer/admin)

Yol seqmentinin maneəsiz (pilləsiz/pandus) olub-olmadığı: əlçatan marşrut buna görə hesablanır

JSON body
stepFreeboolean
→ { id, stepFree }
POST/api/roads/:id/congestionBearer (dispetçer/admin)

Yol tıxacı əmsalı

JSON body
factornumber ≥1
→ yol
POST/api/brigades/:id/statusBearer (dispetçer/admin)

Briqada statusu

JSON body
statusavailable | dispatched | on_scene | offline
→ briqada

Admin / simulyasiya

POST/api/sim/occupancyBearer (yalnız admin)

Məntəqənin doluluğunu təyin edir

JSON body
pointIdstring
occupiednumber
→ məntəqə
POST/api/sim/chaosBearer (yalnız admin)

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

JSON body
modeok | http503 | slow | error
externalDownboolean (köhnə)
externalLatencyMsnumber (köhnə)
→ chaos
POST/api/sim/rulesBearer (yalnız admin)

Qayda həddlərini işləyərkən dəyişir (yoxlanılır). "Təhlükəsizlik rejimi": requireVerified

JSON body
minDistinctReportersnumber
overcrowdPctnumber
requireVerifiedboolean
…bax /api/config
→ rules
GET/api/sim/scenariosBearer (yalnız admin)

Demo ssenari adları

→ [ name ]
POST/api/sim/smsBearer (yalnız admin)

SMS simulyatoru: gateway açarı olmadan eyni emal xəttini işlədir

JSON body
fromstring
textstring
→ { intent, reply }
POST/api/sim/scenarioBearer (yalnız admin)

Ssenarini real boru kəmərində işlədir

JSON body
namecluster | fake_flood | mass_event | filling | overcrowd | api_outage | road_block | reset
→ { name, … }
POST/api/sim/resetBearer (yalnız admin)

Bütün vəziyyəti sıfırlayır

→ { ok }