WebSocket hızlı başlangıç
Tek bir WebSocket bağlantısı, anahtarınızın okuyabildiği her piyasada en fazla 200 enstrüman için canlı fiyat güncellemelerini akıtır.
Protokol konsolunda canlı deneyin →
Resmi KAP bildirimlerinin ayrı bir akışı var → KAP WS
1 — Bağlanın ve kimlik doğrulayın
Uç noktaya bağlanın, ardından auth mesajını ilk kare olarak gönderin (10 saniye içinde). live kapsamı zorunludur.
wss://api.theportfoy.com/portgate/v1/ws{"action": "auth", "api_key": "pg_live_…"}{"type": "auth_ok", "plan": "tester"}2 — Abone olun
Mesaj başına en fazla 100 kimlik, bağlantı başına 200 aktif, piyasaların herhangi bir karışımı. Her kimlik için anında bir anlık görüntü alırsınız (önbellekten), ardından her yenileme döngüsünde bir güncelleme:
{"action": "subscribe", "ids": ["bist:THYAO", "us:AAPL", "fx:USDTRY"]}{"type": "subscribed", "ids": ["bist:THYAO", "us:AAPL", "fx:USDTRY"], "invalid": []}{"type": "quote", "data": {
"instrument_id": "us:AAPL", "symbol": "AAPL", "market": "us",
"currency": "USD", "last": "314.96", "change_pct": "-0.3985",
"as_of": "2026-07-11T00:00:01.062000Z", "data_delay_seconds": 900, ...
}}quote.data değeri, REST Quote biçiminin bayt bayt aynısıdır — tek bir ayrıştırıcı her iki taşımaya da hizmet eder. Abonelikten çıkmak için {"action": "unsubscribe", "ids": [...]} kullanın.
3 — Bağlantıyı canlı tutun
{"action": "ping"} 30 saniyede bir kez gönderin. Kenar (edge) atıl bağlantıları ~60sn sonra kapatır — sessiz izleme listeleri için ping isteğe bağlı değildir. Sunucu {"type": "pong"} ile yanıt verir.Tam örnek
const ws = new WebSocket("wss://api.theportfoy.com/portgate/v1/ws");
ws.onopen = () => ws.send(JSON.stringify({ action: "auth", api_key: KEY }));
let pingTimer;
ws.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
if (msg.type === "auth_ok") {
ws.send(JSON.stringify({ action: "subscribe",
ids: ["bist:THYAO", "us:AAPL"] }));
pingTimer = setInterval(
() => ws.send(JSON.stringify({ action: "ping" })), 30_000);
}
if (msg.type === "quote") render(msg.data);
if (msg.type === "error") console.warn(msg.code, msg.message);
};
ws.onclose = () => clearInterval(pingTimer); // reconnect with backoffHatalar ve kapanış kodları
| Alan | Tür | Notlar |
|---|---|---|
| 4400 | close | Protokol ihlali (3 hatalı mesaj, aşırı büyük kare, kimlik doğrulama olmayan ilk mesaj) |
| 4401 | close | Kimlik doğrulama başarısız / zaman aşımı (10sn içinde kimlik doğrulama yok) |
| 4403 | close | Anahtarda live kapsamı yok |
| error{code:"subscription_limit"} | message | 200 aktifi aşardı — abonelik tamamen reddedilir, bağlantı açık kalır |
| error{code:"bad_message"} | message | Bozuk kare / bilinmeyen action — kimlik doğrulamadan sonra 3 ihlal → kapanış 4400 |
| subscribed.invalid | field | Bir abonelikteki bilinmeyen kimlikler burada geri döner — geçerli olanlar yine de uygulanır |
Herhangi bir kapanışta üstel geri çekilmeyle yeniden bağlanın ve kimlik doğrulama + abonelikleri yeniden gönderin; abonelikteki anlık görüntüler sayesinde anlamlı hiçbir şeyi kaçırmazsınız.
İyi uygulamalar ve ipuçları
- Üstel geri çekilmeyle yeniden bağlanın (sıkı döngü değil), ardından yeniden kimlik doğrulayıp aboneliklerinizi yeniden gönderin. Her an kapanış olabilir — dağıtımlar 1001 ile kapatır.
- Yaklaşık 30 sn'de bir ping gönderin. Kenar (edge) ~60 sn sonra atıl bağlantıyı kapatır ve ~60 sn'lik gönderim temposu bununla yarışabilir — sessiz izleme listeleri için ping isteğe bağlı değildir.
- Abonelik, önce en güncel önbellek kotasyonunu anında gönderir, sonra farkları (delta). Sokette geçmiş tekrarı (replay) yoktur — yeniden bağlanınca yeniden abone olur ve anlık görüntüden senkronize olursunuz.
- Teslimat en fazla bir kez (at-most-once) ve enstrümanlar arası sıra garantisi yoktur. Değişmeyen fiyatlar bile gönderilir; böylece akış aynı zamanda bir tazelik sinyali görevi görür.
- Abonelikleri toplu gönderin: mesaj başına ≤100 kimlik, bağlantı başına 200 aktif. Sınır aşılırsa abonelik tamamen reddedilir (kısmi değil) — büyük listeleri parçalayın.
- Her kotasyon data_delay_seconds taşır (bugün 900). Bu, gecikmeli akıştır; REST ile aynı duruş. 'Canlı', istemci bayrağı değil bir lisanslama kararıdır. 'live' kapsamı, gecikmesiz veri değil akış erişimi demektir.
- quote.data, REST Quote biçiminin bayt bayt aynısıdır — her iki taşıma için tek bir model/ayrıştırıcı kullanın.
