APITube Help Center

How to Stream News over WebSocket

Open a wss connection to /v1/news/ws and receive matching articles the moment they are published

Erick Horn

Written by Erick Horn

June 27, 2026

How to stream news over WebSocket

To stream news over WebSocket, open one connection to wss://api.apitube.io/v1/news/ws and pass your filters in the query string. APITube holds the socket open and pushes each new article that matches as a JSON message — no polling on your side. The quickest way to try it is the wscat client:

# npm install -g wscat
wscat -c "wss://api.apitube.io/v1/news/ws?api_key=YOUR_API_KEY&language.code=en"

Authenticate with your key in the X-API-Key header or, for browser and most WebSocket clients that cannot set custom headers, as the ?api_key= query parameter. A missing or invalid key closes the socket immediately with close code 1008 (Unauthorized).

How does the WebSocket stream work?

The server checks for new matching articles about every 10 seconds and sends up to 50 articles per cycle. It also emits a heartbeat message roughly every 30 seconds so idle connections stay alive. A single connection lasts up to 6 hours; at that point the server sends error code ER0362 and closes with code 4005, asking you to reconnect.

The stream delivers new articles, not a history dump. On connect, APITube anchors to the single most recent article that matches your filters and then streams everything published after it. To pull older articles, run a normal search against /v1/news/everything instead — the WebSocket is purely for what arrives next.

What messages does the WebSocket send?

Every message is a JSON object with a type field, so you tell them apart by type:

  • Articlestype: "article"; the article itself is in the data field (the same object a news search returns — id, title, source, and so on, read as msg.data.id, msg.data.title, …).
  • Control messagesconnected (sent once on connect, with a session_id), subscribed (echoes your active filters), heartbeat (with a timestamp), pong (reply to your ping), and error (with a code and message).

A browser client that branches on type handles them cleanly:

const ws = new WebSocket('wss://api.apitube.io/v1/news/ws?api_key=YOUR_API_KEY&language.code=en');

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === 'error') { console.error(msg.code, msg.message); return; }
  if (msg.type !== 'article') return;              // connected / subscribed / heartbeat / pong — ignore
  const article = msg.data;                        // the article object lives under data
  console.log('new article', article.id, article.title);
};

How do I filter the stream and keep it alive?

Every filter that works on a normal news search works here — append it to the query string. Language, category, source, sentiment, entities, sorting, and field selection all apply:

wscat -c "wss://api.apitube.io/v1/news/ws?api_key=YOUR_API_KEY&language.code=en&category.id=medtop:15000000&source.domain=reuters.com&fl=id,title,source.domain"

Use fl to trim each message to the fields you actually use — see how to select specific response fields. To keep a quiet connection healthy behind proxies, send a ping and the server replies with a pong:

{"action":"ping"}

The server answers {"type":"pong","timestamp":...}. Any other client message is ignored, so you cannot change filters on a live socket — reconnect with new query parameters instead. The official endpoints reference on docs.apitube.io lists /v1/news/ws alongside the rest of the API.

What does WebSocket streaming cost?

You are billed 1 credit per article actually delivered — never for the open connection, heartbeats, or pongs. A credit is deducted only after the article is successfully written to an open socket, so if nothing matches your filters, nothing is spent. WebSocket deliveries draw from a separate WebSocket credit pool on your account, distinct from your regular request credits; when that pool is empty, a positive pay-as-you-go balance is used instead.

If you connect with no WebSocket credits and no paid balance, the server sends error code ER0404 and closes with code 4002. If the balance runs out mid-stream, you get an error message with code ER0402 and the socket closes — reconnect after topping up or when your plan credits renew.

Common Questions

How is WebSocket different from SSE?

Both push the same article objects in real time and both bill per delivered article. The difference is the transport: WebSocket is a two-way socket, so your client can send a ping and the server can reply, while Server-Sent Events are one-way and resume automatically with a Last-Event-Id header. Choose WebSocket when you already speak wss or want client-to-server pings; choose SSE when you want built-in reconnection and the simplicity of the browser EventSource API. For server-to-server delivery without holding any socket open, use a webhook instead.

How many WebSocket connections can I open at once?

The number of simultaneous WebSocket connections depends on your plan. Streaming is not available on the Free plan; paid plans allow 2 simultaneous connections on Basic, 10 on Professional, and 50 on Corporate. Opening one more than your plan allows sends error code ER0403 and closes that attempt with code 4003. Closing a socket frees its slot, so close connections you no longer need rather than leaving them idle.

Do test keys work over WebSocket?

Yes. A test key streams live events, but the article content is masked for preview and deliveries do not consume your quota. Use a test key to confirm your client connects, parses the article and control messages, and handles reconnection, then switch to a live key on a paid plan for full content and real billing (streaming is not available on the Free plan).

What happens when my key is revoked?

A WebSocket connection can stay open for hours, so APITube re-checks your key on every poll cycle. If you revoke the key while a stream is running, the server sends error code ER0361 and closes the socket with code 4004 within the next cycle. Reconnect with a valid key to resume. The same re-check keeps your credit balance in sync across multiple connections, so concurrent sockets cannot bill past zero.


Related Articles