{"openapi":"3.1.0","info":{"title":"IdeaSoft Canlı Satış Verileri API","version":"1.0.0","description":"IdeaSoft altyapılı mağazalardaki satışların anonim, örneklenmiş canlı akışı ve istatistikleri. Okuma uçları açık ve salt okunurdur; kişisel veri ve ilçe bilgisi içermez. Ürün adları mağazalardan geldiği gibi gösterilir ve güvenilmeyen girdi olarak ele alınmalıdır."},"servers":[{"url":"https://live.ideasoft.com.tr"}],"tags":[{"name":"Canlı akış","description":"Anlık satışlar ve sayaç."},{"name":"İstatistik","description":"Aralık bazlı toplamlar."},{"name":"Ingest","description":"Satış olaylarının alınması (yalnız IdeaSoft core)."},{"name":"Yönetim","description":"Operasyon uçları."}],"components":{"securitySchemes":{"IdeashopHmac":{"type":"apiKey","in":"header","name":"X-Ideashop-Hmac-Sha256","description":"base64(HMAC-SHA256(ham gövde, INGEST_SECRET)). Yalnız IdeaSoft core."},"AdminBearer":{"type":"http","scheme":"bearer","description":"Yalnız operasyon ekibi (sayaç seed'i)."}},"schemas":{"IngestAccepted":{"type":"object","properties":{"accepted":{"type":"boolean","enum":[true]},"event_id":{"type":"string"}},"required":["accepted","event_id"]},"Error":{"type":"object","properties":{"error":{"type":"string","example":"validation"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}},"message":{"type":"string"}},"required":["path","message"]}}},"required":["error"]},"IngestEvent":{"type":"object","properties":{"event_id":{"type":"string","minLength":1,"maxLength":128,"example":"oi_123456789"},"city":{"type":"string","minLength":1,"maxLength":64,"example":"İstanbul"},"county":{"type":"string","maxLength":64,"description":"Kabul edilir ama saklanmaz ve yayınlanmaz (KVKK)."},"name":{"type":"string","minLength":1,"maxLength":300,"example":"Organik Pamuk Çorap"},"price":{"type":"string","minLength":1,"maxLength":32,"example":"9.25 TL"},"image":{"type":"string","maxLength":512,"example":"//st3.myideasoft.com/idea/ef/14/myassets/products/187/s95675_min.jpg"},"time":{"type":"integer","description":"Unix saniye; şimdiden en fazla 7 gün sapma."},"quantity":{"type":"integer","minimum":1,"maximum":100000,"example":1}},"required":["event_id","city","name","price","time","quantity"]},"Snapshot":{"type":"object","properties":{"sales":{"type":"array","items":{"$ref":"#/components/schemas/Sale"},"description":"En yeniden eskiye."},"counter":{"$ref":"#/components/schemas/Counter"},"serverTime":{"type":"integer","description":"Unix ms."}},"required":["sales","counter","serverTime"]},"Sale":{"type":"object","properties":{"seq":{"type":"integer","description":"Akıştaki sıra numarası (SSE `id`)."},"city":{"type":"string","example":"Ankara"},"provinceId":{"type":["string","null"],"example":"ankara"},"name":{"type":"string","example":"Kahve Çekirdeği 1 kg"},"priceText":{"type":"string","example":"52.75 TL"},"image":{"type":["string","null"]},"quantity":{"type":"integer"},"soldAt":{"type":"integer","description":"Unix saniye."}},"required":["seq","city","provinceId","name","priceText","image","quantity","soldAt"]},"Counter":{"type":"object","properties":{"year":{"type":"integer","example":2026},"total":{"type":"integer","description":"Yılın toplam satılan ürün adedi."}},"required":["year","total"]},"Stats":{"type":"object","properties":{"range":{"type":"string","enum":["24h","7d","30d","365d"]},"from":{"type":"integer","description":"Aralık başlangıcı (unix saniye)."},"to":{"type":"integer","description":"Aralık sonu (unix saniye)."},"generatedAt":{"type":"integer","description":"Hesaplanma zamanı (unix ms)."},"totals":{"type":"object","properties":{"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["sales","quantity"]},"byCity":{"type":"array","items":{"type":"object","properties":{"city":{"type":"string"},"provinceId":{"type":["string","null"]},"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["city","provinceId","sales","quantity"]}},"byHour":{"type":"array","items":{"type":"object","properties":{"hour":{"type":"integer","minimum":0,"maximum":23},"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["hour","sales","quantity"]},"description":"Günün saatine göre dağılım (Europe/Istanbul)."},"byDay":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string"},"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["day","sales","quantity"]}},"priceBands":{"type":"array","items":{"type":"object","properties":{"band":{"type":"string"},"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["band","sales","quantity"]},"description":"Yalnız TL fiyatlar."}},"required":["range","from","to","generatedAt","totals","byCity","byHour","byDay","priceBands"]},"ProductStats":{"type":"object","properties":{"range":{"type":"string","enum":["24h","7d","30d"]},"from":{"type":"integer"},"to":{"type":"integer"},"generatedAt":{"type":"integer"},"items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"sales":{"type":"integer"},"quantity":{"type":"integer"}},"required":["name","sales","quantity"]}}},"required":["range","from","to","generatedAt","items"]},"CounterSeedResult":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"year":{"type":"integer"},"previous":{"type":"integer"},"total":{"type":"integer"}},"required":["ok","year","previous","total"]},"CounterSeed":{"type":"object","properties":{"year":{"type":"integer","minimum":2020,"maximum":2100},"total":{"type":"integer","minimum":0,"maximum":1000000000000}},"required":["year","total"]}},"parameters":{}},"paths":{"/api/v1/ingest":{"post":{"tags":["Ingest"],"summary":"Satış olayı gönder (yalnız IdeaSoft core)","description":"Kaynak IP allowlist'i ve `X-Ideashop-Hmac-Sha256` imzası zorunludur. Sözleşme: docs/ingest-contract.md.","security":[{"IdeashopHmac":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestEvent"}}}},"responses":{"202":{"description":"Kuyruğa alındı (filtrelense veya tekrar olsa da).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestAccepted"}}}},"400":{"description":"Geçersiz JSON veya alan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"İmza yok veya yanlış.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Kaynak IP izinli değil.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Gövde 8 KB'tan büyük.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Content-Type application/json değil.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit aşıldı.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Uç yapılandırılmamış veya kuyruk kullanılamıyor.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/live/snapshot":{"get":{"tags":["Canlı akış"],"summary":"En yeni satışlar ve yıllık sayaç","description":"BR-READ-01. En yeniden eskiye satışlar; `county` ve `event_id` içermez. Edge'de 2 sn önbelleklenir.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Anlık görüntü.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Snapshot"}}}},"304":{"description":"ETag değişmedi."},"400":{"description":"Geçersiz sorgu parametresi.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit aşıldı.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/live/stream":{"get":{"tags":["Canlı akış"],"summary":"Server-Sent Events akışı","description":"BR-READ-02. Olaylar: `init` (anlık görüntü), `sale` (id = seq), `counter`; 25 sn'de bir `: ping`. `Last-Event-ID` veya `?since=` ile kaldığı yerden devam eder.","parameters":[{"schema":{"type":"string","pattern":"^\\d+$"},"required":false,"name":"since","in":"query"}],"responses":{"200":{"description":"text/event-stream","content":{"text/event-stream":{"schema":{"type":"string"}}}},"429":{"description":"Rate limit veya istemci başına bağlantı tavanı aşıldı.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Toplam bağlantı kapasitesi dolu.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/live/stats":{"get":{"tags":["İstatistik"],"summary":"Aralık bazlı satış istatistikleri","description":"BR-READ-03/05. `24h` kayan 24 saat; `7d`, `30d`, `365d` bugün dahil takvim günleri (Europe/Istanbul). 10 dakikada bir yeniden hesaplanır; edge'de 60 sn önbelleklenir. Filtrelenen ürünler toplamlara dahildir.","parameters":[{"schema":{"type":"string","enum":["24h","7d","30d","365d"],"default":"24h"},"required":false,"name":"range","in":"query"}],"responses":{"200":{"description":"İstatistikler.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"304":{"description":"ETag değişmedi."},"400":{"description":"Geçersiz aralık.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit aşıldı.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/live/stats/products":{"get":{"tags":["İstatistik"],"summary":"En çok satılan ürünler","description":"BR-READ-03. Yalnız gösterilebilir (filtreye takılmayan) satışlar; adede göre sıralı.","parameters":[{"schema":{"type":"string","enum":["24h","7d","30d"],"default":"24h"},"required":false,"name":"range","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":10},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Ürün listesi.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductStats"}}}},"304":{"description":"ETag değişmedi."},"400":{"description":"Geçersiz parametre.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit aşıldı.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/admin/counter-seed":{"post":{"tags":["Yönetim"],"summary":"Yıllık sayacı verilen değere eşitle","security":[{"AdminBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CounterSeed"}}}},"responses":{"200":{"description":"Sayaç güncellendi.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CounterSeedResult"}}}},"400":{"description":"Geçersiz gövde.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Anahtar yok veya yanlış.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Kaynak IP izinli değil.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Yönetim ucu yapılandırılmamış.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{}}