Browser WebSocket
اتصل بواجهة finlight.me WebSocket API مباشرةً من متصفّح الويب باستخدام واجهة WebSocket الأصلية. وهذا مثالي للوحات التحكم ومنصّات التداول وأي تطبيق واجهة أمامية يحتاج إلى تحديثات مقالات في الوقت الفعلي دون وكيل من جانب الخادم.
لا تدعم واجهة WebSocket في المتصفّح الترويسات المخصّصة. وتُعالَج المصادقة عبر معاملات الاستعلام بدلًا من ترويسة x-api-key. وسيكون مفتاح API الخاص بك مرئيًا في عنوان URL لـ WebSocket — لذا استخدم هذا النهج فقط في البيئات التي يكون فيها ذلك مقبولًا (مثل لوحات التحكم المُصادَق عليها). لا تكشف مفتاح API أبدًا في كود من جانب العميل متاح للعامّة.
كيف يعمل
- اتصل بـ
wss://wss.finlight.me(مُثرى) أوwss://wss.finlight.me/raw(raw) مع مفتاح API الخاص بك كمعامل استعلام - اشترك بإرسال رسالة JSON تتضمّن معايير التصفية و
clientNonce - استقبِل رسالة
admitتؤكّد اتصالك، تليها رسائلsendArticleفور وصول المقالات - حافظ على الاتصال حيًّا بإرسال رسائل
pingكل 25 ثانية - اقطع الاتصال باستدعاء
ws.close()
عناوين URL للاتصال
- Name
مُثرى- Type
- wss://wss.finlight.me
- Description
مقالات بإثراء كامل: تحليل المشاعر، واستخراج الكيانات، والفئات، والمحتوى الكامل (حسب فئة اشتراكك).
- Name
Raw- Type
- wss://wss.finlight.me/raw
- Description
مقالات raw منخفضة الكمون دون إثراء. الأفضل لحالات الاستخدام التي تكون فيها السرعة أولوية وتحتاج إلى المقالات بأسرع ما يمكن.
معاملات الاستعلام
- Name
apiKey- Type
- string
- Description
مفتاح finlight API الخاص بك. يُستخدم للمصادقة لأن WebSocket المتصفّح لا يمكنه تعيين ترويسات مخصّصة.
- Name
takeover- Type
- string
- Description
عيّنه إلى
"true"لاستبدال أقدم اتصال تلقائيًا عند بلوغ حدّ الاتصالات المتزامنة.
- Name
clientVersion- Type
- string
- Description
معرّف اختياري لتطبيق العميل الخاص بك. مثل
"my-dashboard/1.0"
رسالة الاشتراك
بعد فتح الاتصال، أرسل رسالة JSON للاشتراك في المقالات. سيردّ الخادم برسالة admit ثم يبدأ بدفع المقالات المطابقة.
- Name
clientNonce- Type
- string
- Description
معرّف فريد (مثل UUID) لطلب الاشتراك هذا. يعيده الخادم في استجابة
admit.
- Name
query- Type
- string
- Description
استعلام البحث للعثور على المقالات ذات الصلة. يدعم الاستعلامات المتقدمة.
- Name
sources- Type
- string[]
- Description
التصفية حسب نطاقات المصادر. مثل
["www.reuters.com", "www.cnbc.com"]
- Name
excludeSources- Type
- string[]
- Description
يستبعد نطاقات مصادر محدّدة.
- Name
tickers- Type
- string[]
- Description
التصفية حسب رموز التداول. مثل
["AAPL", "NVDA"](المُثرى فقط)
- Name
countries- Type
- string[]
- Description
التصفية حسب رموز الدول بصيغة ISO 3166-1 alpha-2. مثل
["US", "DE"](المُثرى فقط)
- Name
language- Type
- string
- Description
التصفية حسب اللغة (ISO 639-1). القيمة الافتراضية هي
en، التي تُرجع الإنجليزية فقط وتستبعد اللغات الأخرى — راجع اللغة والتغطية.
رسائل الخادم
يرسل الخادم رسائل JSON تتضمّن حقل action يشير إلى نوع الرسالة:
- Name
admit- Type
- object
- Description
تُرسَل بعد نجاح المصافحة. تتضمّن
leaseIdوserverNow(طابع زمني) وclientNonceالخاص بك.
- Name
sendArticle- Type
- object
- Description
مقال جديد يطابق اشتراكك. توجد بيانات المقال في حقل
data.
- Name
pong- Type
- object
- Description
ردّ على نبضة
pingالخاصة بك.
- Name
preempted- Type
- object
- Description
استُبدِل اتصالك بجلسة أخرى (عندما اتصل عميل آخر بـ
takeover: true).
- Name
error- Type
- object
- Description
حدث خطأ. تحقّق من حقل
dataأوerrorللتفاصيل.
مثال كامل
عميل WebSocket للمتصفّح بسيط ومستقلّ عن أُطر العمل، مع إعادة اتصال تلقائية ونبضة قلب:
- يصادِق عبر معاملات الاستعلام
- يرسل رسالة اشتراك عند الاتصال
- يحافظ على فاصل نبضة قلب مدّته 25 ثانية
- يعيد الاتصال بتراجع أسّي (من 500 مللي ثانية إلى 10 ثوانٍ)
- يعالج جميع أنواع رسائل الخادم
Browser Client
const API_KEY = 'YOUR_API_KEY'
const WSS_URL = 'wss://wss.finlight.me' // Use '/raw' path for raw articles
let ws = null
let pingInterval = null
let reconnectTimeout = null
let reconnectAttempt = 0
function connect(filters = {}) {
const params = new URLSearchParams({
apiKey: API_KEY,
takeover: 'true',
clientVersion: 'my-app/1.0',
})
const url = `${WSS_URL}?${params}`
ws = new WebSocket(url)
ws.onopen = () => {
console.log('Connected')
reconnectAttempt = 0
// Send subscription with filters
ws.send(JSON.stringify({
clientNonce: crypto.randomUUID(),
query: filters.query || '',
language: filters.language || 'en',
sources: filters.sources || [],
tickers: filters.tickers || [],
countries: filters.countries || [],
}))
// Start heartbeat
pingInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({
action: 'ping',
t: Date.now(),
}))
}
}, 25000)
}
ws.onmessage = (event) => {
const msg = JSON.parse(event.data)
switch (msg.action) {
case 'admit':
console.log('Admitted, lease:', msg.leaseId)
break
case 'sendArticle':
console.log('Article:', msg.data.title)
// Handle the article here
break
case 'pong':
break // Heartbeat OK
case 'preempted':
console.warn('Connection replaced')
break
case 'error':
console.error('Server error:', msg.data || msg.error)
break
}
}
ws.onclose = (event) => {
clearInterval(pingInterval)
// Don't reconnect on policy violations
if (event.code === 1008 || event.code === 4002) {
console.error('Connection blocked')
return
}
// Exponential backoff reconnect
const delay = Math.min(500 * 2 ** reconnectAttempt, 10000)
reconnectAttempt++
console.log(`Reconnecting in ${delay}ms...`)
reconnectTimeout = setTimeout(() => connect(filters), delay)
}
ws.onerror = () => console.error('WebSocket error')
}
function disconnect() {
clearInterval(pingInterval)
clearTimeout(reconnectTimeout)
if (ws) ws.close(1000)
}
// Usage
connect({ query: 'Nvidia', language: 'en', countries: ['US'] })
admit Response
{
"action": "admit",
"leaseId": "a1b2c3d4-e5f6-4789-abcd-ef0123456789",
"serverNow": 1708185600000,
"clientNonce": "your-uuid-here"
}
sendArticle Response
{
"action": "sendArticle",
"data": {
"link": "https://www.reuters.com/technology/nvidia-2026-02-17",
"source": "www.reuters.com",
"title": "Nvidia Reports Record Revenue",
"summary": "Nvidia announced record quarterly revenue...",
"publishDate": "2026-02-17T10:30:00Z",
"language": "en",
"sentiment": "positive",
"confidence": 0.92,
"countries": ["US"],
"categories": ["markets", "technology"],
"companies": [
{
"name": "NVIDIA Corporation",
"ticker": "NVDA",
"country": "US"
}
]
}
}
المُثرى مقابل Raw
| الميزة | المُثرى (/) | Raw (/raw) |
|---|---|---|
| تحليل المشاعر | نعم | لا |
| استخراج الكيانات (الشركات) | نعم (حسب الفئة) | لا |
| الفئات | نعم | لا |
| المحتوى الكامل | نعم (حسب الفئة) | لا |
| الكمون | قياسي | الأدنى |
المرشّح: tickers | نعم | لا |
المرشّح: countries | نعم | لا |
المرشّح: query وsources وlanguage | نعم | نعم |
لا تدعم اشتراكات Raw WebSocket سوى مرشّحات query وsources وexcludeSources وlanguage. ويتم تجاهل مرشّحات الرموز والدول بصمت على نقطة نهاية raw.
ما الخطوة التالية؟
- راجع صفحة الاشتراك المُثرى للاطّلاع على نموذج المقال الكامل وجميع الحقول المتاحة
- راجع الاشتراك الخام (Raw) للتفاصيل الخاصة بـ raw
- تعرّف على إنشاء الاستعلامات المتقدمة لتنقيح مرشّحاتك
- استخدم REST API للبحث في المقالات التاريخية إلى جانب بثّك في الوقت الفعلي