Kaynak:
docs/API.md— bu sayfa her build'de otomatik senkronize edilir.
API Referansı
Tüm uçlar /api altındadır. Kimlik doğrulama açıkken (-auth-password) korumalı
uçlar şunlardan birini ister:
- Cookie:
nm_session(login yanıtında HttpOnly olarak set edilir; tarayıcı otomatik taşır, WS handshake'i dahil) - Header:
Authorization: Bearer <token>(login yanıtındakitoken)
Yetkisiz istek: 401 + {"error":"oturum gerekli","auth_required":true}
Çok fazla hatalı giriş: 429 + Retry-After: 60
Makine-okunur şema (OpenAPI)
Bu dokümanın makine-okunur karşılığı api/openapi.yaml'dedir (OpenAPI 3.1) ve
hub tarafından kimlik doğrulaması gerektirmeden sunulur:
| Uç | İçerik |
|---|---|
GET /api/openapi.yaml | Ham şema (YAML) |
GET /api/openapi.json | Aynı şema JSON'a çevrilmiş — Postman/Insomnia/editor.swagger.io |
GET /api/docs | Tarayıcıda gezilebilir uç listesi (tek dosya, harici CDN yok) |
internal/server içindeki TestOpenAPICoversRouter sözleşme testi şema ile
gerçek yönlendiricinin birebir örtüştüğünü doğrular — yeni bir uç eklenip
şemaya işlenmezse (veya tersi) CI kırılır.
Kimlik Doğrulama
POST /api/login (korumasız)
{"password": "gizliSifre123"}
200: {"ok":true,"token":"<hex>"} + Set-Cookie: nm_session=...; HttpOnly; SameSite=Lax; Max-Age=604800
401: hatalı şifre · 429: bloklandı
POST /api/logout
Cookie ve/veya Bearer oturumunu iptal eder. → {"ok":true}
GET /api/auth/status (korumasız)
{"required": true, "authenticated": false}
Canlı Veri
WS /ws
Her saniye bir tick gönderir:
{
"type": "tick",
"stats": { "running": true, "device": "en0", "bps_in": 52000.0, "...": "..." },
"connections": [ { "proto": "tcp", "local_addr": "...", "remote_addr": "...", "...": "" } ],
"alert_events": [ { "id": 1, "ts": 1787938964, "kind": "bw", "key": "in", "message": "..." } ],
"record": { "recording": false, "packets": 0, "bytes": 0 }
}
stats alanının tam şeması GET /api/status ile aynıdır.
Yakalama
GET /api/status
Anlık yakalama anlık görüntüsü (Snapshot):
| Alan | Tip | Açıklama |
|---|---|---|
running | bool | yakalama açık mı |
device | string | aktif arayüz |
error | string | yakalama döngüsü hatası (varsa) |
total_packets / total_bytes / dropped | int | oturum toplamları |
bps_in / bps_out / bps_local | float | son saniyenin hızı (bit/sn) |
pps | int | son saniyenin paket/sayısı |
protocols | object | "TCP": n, "UDP": n, ... |
top_endpoints | array | ip, hostname, local, country, asn, in, out, total, packets (en fazla 50) |
top_ports | array | port, name, bytes, packets (25) |
top_domains | array | domain, queries, responses, ips[] (30) |
history | array | son 120 saniyelik kova: ts, in, out, local, packets (bayt) |
GET /api/interfaces
Ağ arayüzleri: name, hw_addr, mtu, up, loopback, can_sniff, addresses[], rx_bytes, tx_bytes, rx_packets, tx_packets
POST /api/capture/start
{"device": "en0"}
200: {"ok":true} — hata: {"ok":false,"error":"... (root/admin yetkisi gerekli olabilir)"}
POST /api/capture/stop
Yakalamayı durdurur; açık PCAP kaydı da temizce kapanır. → {"ok":true}
Geçmiş ve Karşılaştırma
GET /api/history?minutes=60
DB'den dakikalık seriler:
{
"range_minutes": 60,
"db_bytes": 106936,
"totals": { "avg_bps_in": 0, "avg_bps_out": 0, "peak_bps_in": 0, "peak_bps_out": 0, "seconds": 0, "samples": 0 },
"buckets": [ { "ts": 1787900000, "in": 2500.0, "out": 625.0, "local": 0, "pps": 12 } ]
}
buckets[i].in/out bayt/sn cinsindendir (dakikalık ortalama). minutes 1–10080.
GET /api/compare?days=7
{
"days": [ { "day": 1787864400, "avg_bps_in": 0, "avg_bps_out": 0, "peak_bps_in": 0, "peak_bps_out": 0, "samples": 0 } ],
"today_hours": [ { "hour": 0, "bps_in": 0, "bps_out": 0 } ],
"yesterday_hours": [ { "hour": 0, "bps_in": 0, "bps_out": 0 } ]
}
days[].day yerel gece yarısı (unix). Saat dizileri her zaman 24 kayıttır; olmayan saatler 0'dır. days 2–30.
Rapor
GET /api/report?days=7&format=html|pdf
format=html:text/html— tarayıcıda görüntülenir, yazdırılabilirformat=pdf:application/pdf+Content-Disposition: attachment
İçerik: yönetici özeti, günlük trafik (+grafik), en yoğun hedefler (ülke/ASN),
süreçler, DNS, protokoller, uyarılar, son 3 AI analizi. days 1–90.
PCAP Kayıt
| Uç | Açıklama |
|---|---|
POST /api/record/start | Kaydı başlat. Yakalama açık değilse hata: kayit için önce yakalama açık olmalı |
POST /api/record/stop | Kaydı kapat: {"ok":true,"file":"2026-08-28_20-05-00_en0.pcap","packets":12345,"bytes":987654} |
GET /api/record/status | {recording, file, packets, bytes, error} |
GET /api/record/files | {name, bytes, mod_time} dizini (yeni→eski) |
GET /api/record/download?file=<ad> | .pcap indirir. Yalnızca kayıt dizinindeki .pcap dosyaları; yoksa 400/404 |
Uyarılar
GET /api/alerts
{
"enabled": true,
"cooldown_min": 10,
"bandwidth": { "enabled": true, "in_mbps": 100, "out_mbps": 50, "seconds": 10 },
"ports": { "enabled": true, "ports": [23, 4444, 1337, 31337] },
"new_proc": { "enabled": true, "ignore": ["bazntms"] },
"new_target": { "enabled": true, "min_total_mb": 10 },
"notifiers": {
"desktop": true, "generic_url": "", "discord_url": "",
"slack_url": "", "telegram_token": "", "telegram_chat_id": ""
}
}
PUT /api/alerts
Aynı şemayla gövde; kaydeder ve anında uygular. → {"ok":true}
GET /api/alerts/events?limit=50
[ { "id": 1, "ts": 1787939000, "kind": "port", "key": "23", "message": "Şüpheli porta bağlantı: ..." } ]
kind: bw (bant genişliği) · port (şüpheli port) · proc (yeni süreç) · target (yeni hedef)
AI Analizi (Faz 26 — -ai ile açık)
Çok-turlu sohbet + çoklu sağlayıcı (yerel + bulut). Sohbet yetki:analyze,
sağlayıcı CRUD yetki:global-admin. api_key hiçbir yanıtta düz görünmez.
Tam şema: GET /api/openapi.yaml (ai tag). AI danışmandır — otomatik
aksiyon yok (bkz. docs/decisions/0014).
GET /api/v1/ai/status
{"enabled":true,"providers":[…],"default_provider":1,"default_model":"…","has_ready_provider":true}
— AI kapalıysa {"enabled":false}.
GET /api/v1/ai/presets
Sunucu-tanımlı hazır analiz butonları: {"presets":[{"id","label","scopes","task"}]}
GET /api/v1/ai/conversations?scope=&ref=&source=&archived=
Sohbet oturumları (site-kapsamlı süzülür). POST ile oluştur:
{"scope_kind":"fleet","scope_ref":"","provider_id":0} → {"ok":true,"id":N}
GET /api/v1/ai/conversations/{id} · DELETE (= arşivle)
{"conversation":{…},"messages":[{role,content,tokens_in,tokens_out,error,created_ts}]}
POST /api/v1/ai/conversations/{id}/messages — SSE
{"content": "filo nasıl görünüyor?", "preset": "fleet_summary", "refresh_context": false}
text/event-stream döner; her satır data: {"delta":"…"}, sonda
data: {"done":true,"tokens_in":N,"tokens_out":M} ya da data: {"error":"…"}.
Kullanıcı + asistan mesajı kalıcı yazılır; ilk turda kapsam bağlamı eklenir.
GET /api/v1/ai/providers · POST · PUT /{id} · DELETE /{id} — yetki:global-admin
Liste: {id,name,kind,base_url,default_model,enabled,has_key,is_local} — api_key YOK.
Yazma gövdesi: {name,kind,base_url,api_key,default_model,enabled,no_think,max_tokens,temperature}.
kind: openai | anthropic | ollama | lmstudio | openai-compat.
api_key boş + PUT → mevcut anahtar korunur.
POST /api/v1/ai/providers/{id}/test · GET /api/v1/ai/providers/{id}/models
Test: {"ok":true,"latency_ms":120,"models":["…"]} ya da {"ok":false,"error":"…"}.
Agent Filosu
Agent uçları UI oturumundan bağımsızdır. İki kimlik yolu:
- Bearer token —
Authorization: Bearer <agent_token>. Token enrollment ile verilir, diskte (bazntms-agent.state.json) saklanır; hub yalnızca SHA-256 hash'ini tutar. - Karşılıklı TLS (mTLS) — hub
-tlsile çalışıyorsa: agent'ın enrollment'ta aldığı istemci sertifikası (CN=bazntms-agent-<id>, hub CA'sınca imzalı) TLS el sıkışmasında sunulur ve Bearer'a eşdeğer kimlik sayılır. Silinmiş agent'ın sertifikası reddedilir (CRL yok,agent_idçözümü yeterli).
POST /api/v1/agent/hello (UI auth muaf)
Enrollment: header X-Enroll-Token: <hub -enroll-token VEYA aşağıdaki /api/v1/enroll-tokens ile üretilmiş bir token> zorunlu.
{"name":"workstation-01","site":"merkezi-ofis","version":"0.1.0","protocol_version":1,"os":"darwin","arch":"arm64","csr_pem":"-----BEGIN CERTIFICATE REQUEST-----\n…"}
csr_pem opsiyoneldir; verilir ve hub -tls ile çalışıyorsa yanıt client_cert_pem
ca_cert_pemiçerir (mTLS). CSR'daki CN yok sayılır — hubbazntms-agent-<id>koyar.
200: {"accepted":true,"agent_id":1,"agent_token":"<hex>","telemetry_interval_seconds":30,"pcap_enabled":false,"client_cert_pem":"…","ca_cert_pem":"…"}
IP başına deneme sınırlaması vardır (login sayfasıyla aynı politika: 1 dakikada
5 başarısız denemeden sonra 1 dakika bloklanır) — token tahmin etmeye çalışan
istekleri engeller. Bloklandığında 429 + Retry-After: 60 döner; başarılı
bir enrollment sayacı sıfırlar.
POST /api/v1/agent/cert (Bearer/mTLS agent kimliği)
İstemci sertifikasını yeniler (agent ömrünün yarısı geçince çağırır). Gövde:
{"csr_pem":"-----BEGIN CERTIFICATE REQUEST-----\n…"} →
200: {"client_cert_pem":"…","ca_cert_pem":"…"}. Hub -tls kapalıysa 404.