SSE Stream
Open one HTTP connection to receive new matching articles with SSE (Server-Sent Events). The API sends articles as they become available, so you do not need to check for updates repeatedly.
Articles arrive when they become available in APITube. They may have been published earlier. See Delivery Order and Freshness to receive only recent articles.
What is SSE Stream?
Server-Sent Events keep an HTTP connection open so a server can send updates. Each update on this stream contains a news article.
Use cases:
- Live news feeds and dashboards
- Real-time monitoring for specific topics, entities, or sentiment
- Breaking news alerts
- Applications that process incoming articles
Benefits:
- Receive articles as soon as they become available, without repeated search requests
- Uses standard SSE protocol — works in any language
- Reconnect with
Last-Event-IDto receive articles missed during a disconnection - All
/everythingfilters supported — language, category, sentiment, entities, and more - Field selection with
flparameter to keep responses smaller
Endpoint
GET https://api.apitube.io/v1/news/streamAuthentication
Pass your API key in one of two ways:
- Header (recommended):
X-API-Key: YOUR_API_KEY - Query parameter:
?api_key=YOUR_API_KEY
Without a valid API key the server returns HTTP 401.
Quick Start
cURL
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?language.code=en"The -N flag disables buffering so events appear in real time.
JavaScript (Browser)
const es = new EventSource(
'https://api.apitube.io/v1/news/stream?api_key=YOUR_API_KEY&language.code=en'
);
es.addEventListener('article', (e) => {
const article = JSON.parse(e.data);
console.log(`[${e.lastEventId}]`, article.title);
});
es.addEventListener('error', (e) => {
if (e.data) {
console.error('Server error:', JSON.parse(e.data));
}
});
// To disconnect:
// es.close();Node.js
import EventSource from 'eventsource';
const es = new EventSource(
'https://api.apitube.io/v1/news/stream?language.code=en',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
es.addEventListener('article', (e) => {
const article = JSON.parse(e.data);
console.log(`[${e.lastEventId}]`, article.title);
});
es.addEventListener('error', (e) => {
if (e.data) {
console.error('Server error:', JSON.parse(e.data));
}
});The eventsource npm package supports custom headers, which makes it the recommended choice for Node.js.
Python
import requests
url = 'https://api.apitube.io/v1/news/stream'
headers = {'X-API-Key': 'YOUR_API_KEY'}
params = {'language.code': 'en'}
with requests.get(url, headers=headers, params=params, stream=True) as r:
for line in r.iter_lines(decode_unicode=True):
if line:
print(line)SSE Event Format
The stream uses standard SSE format with three event types:
article — New Article
event: article
id: 123456
data: {"id":123456,"title":"...","source":{...},...}event: article— event typeid:— article ID (used for reconnection)data:— full article JSON in the same format as the /everything endpoint
error — Server Error
event: error
data: {"code":"ER0301","message":"Balance exhausted"}The API sends an error event when a problem occurs, such as an exhausted balance, then closes the connection. Possible error codes:
| Code | Meaning |
|---|---|
ER0301 | Streaming credits and pay-as-you-go balance are both exhausted. |
ER0177 | The monthly pay-as-you-go spending limit was reached while the stream was billing to your balance. |
ER0361 | The API key was revoked while the stream was open. |
ER0362 | The 6-hour connection lifetime was reached — reconnect (with Last-Event-ID to resume). |
ER0364 | The session was force-closed through the terminate endpoint. |
Heartbeat
: heartbeatThe server sends an SSE comment every 30 seconds to keep the connection open. This message has no event name.
Filtering
All filters available on the /everything endpoint work with SSE Stream:
By language:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?language.code=en"By category:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?category.id=medtop:13000000"By source:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?source.domain=theverge.com"Multiple filters:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?language.code=en&category.id=medtop:13000000&sentiment.overall.polarity=positive"In plain language:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?prompt=breaking%20technology%20news%20in%20English"Use prompt to describe your filters in plain language. It requires Basic or above; Free and Starter return 403 ER0706. An invalid prompt returns 400 ER0800/ER0802 before the stream opens. To inspect the chosen filters, try the prompt on /v1/news/everything first: SSE does not return meta.prompt. A new translation costs 2 points per connection; cached translations are free.
For the full list of available filters, see Parameters.
Field Selection
Use fl to receive only the fields you need and keep responses smaller:
curl -N -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream?language.code=en&fl=id,title,source.domain"The data: object contains only the fields you selected.
Delivery Order and Freshness
Articles arrive as they become available in the API. Within each batch, they are ordered by published_at, oldest first. Some may have been published earlier; use date or age filters to receive only recent news.
published_atis the original publication time when available. Otherwise, it shows when the article became available in APITube.- Delivery time varies by article and publisher. An article may reach the stream after its original publication time.
Skip older articles
Use either of these filters to exclude older articles from delivery and billing:
stream.max_agesets the maximum article age in minutes. At each check, the stream sends only articles published in the last N minutes. Older articles are excluded before delivery and billing. Use this for a feed of recent news:bashcurl -N -H "X-API-Key: YOUR_API_KEY" \ "https://api.apitube.io/v1/news/stream?language.code=en&stream.max_age=15"An invalid value (non-integer or less than 1) is rejected on connect with
400 ER0363.published_at.startexcludes articles published before the date and time you set:bashcurl -N -H "X-API-Key: YOUR_API_KEY" \ "https://api.apitube.io/v1/news/stream?language.code=en&published_at.start=2026-07-03T10:00:00"
Use source.rank.opr.min (Open PageRank) or is_premium_source to select sources. These filters do not sort the stream by source priority. See Parameters.
Reconnection with Last-Event-ID
SSE has built-in reconnection support. If the connection drops, the client can resume from where it left off using the Last-Event-ID header:
- Connect and receive articles — each has a unique
id: - Connection drops (network issue, server restart, etc.)
- Reconnect with the last received ID:
curl -N -H "X-API-Key: YOUR_API_KEY" \
-H "Last-Event-ID: 123456" \
"https://api.apitube.io/v1/news/stream?language.code=en"The server will immediately deliver any articles indexed after ID 123456, then continue streaming new ones.
The browser's EventSource reconnects automatically and sends Last-Event-ID to resume after the last received event.
Parameters
| Parameter | Description |
|---|---|
api_key | API key (alternative to X-API-Key header) |
fl | Field selection (e.g., id,title,source.domain) |
stream.max_age | Maximum article age in minutes. Only articles published within the last N minutes are delivered and billed. An invalid value returns 400 ER0363. |
All /everything filters | language.code, category.id, source.domain, sentiment.overall.polarity, title, organization.name, and more |
Technical Details
| Property | Value |
|---|---|
| Poll interval | Every 30 seconds |
| Heartbeat interval | Every 30 seconds |
| Articles per poll cycle | Up to 50 |
| Delivery order | Within each batch, articles arrive in published_at order, oldest first. Articles are tracked by ID to avoid missing or repeating deliveries. |
| Maximum article age | Set stream.max_age in minutes to exclude older articles before delivery and billing. |
| Billing | 1 credit per delivered article |
| Reconnection | Via Last-Event-ID header |
| Response header | X-Accel-Buffering: no |
Concurrent Connections
Your plan limits how many SSE connections you can keep open at the same time:
| Plan | Max concurrent SSE connections |
|---|---|
| Free | 1 |
| Starter | 2 |
| Basic | 2 |
| Professional | 10 |
| Corporate | 50 |
On Free, you can open 1 SSE connection with 1,000 deliveries per day. Article text is a preview; links, images, descriptions and other fields are full. Articles arrive with a 12-hour delay. Paid plans include full text and more connections: Starter 2, Basic 2, Professional 10 and Corporate 50.
Opening more connections than your plan allows returns HTTP 429 with error code ER0360:
{
"status": "not_ok",
"errors": [
{
"status": 429,
"code": "ER0360",
"message": "Maximum SSE connections (10) reached for your plan."
}
]
}Closing a connection frees one of your allowed sessions. After a crash or forced shutdown, the API may still count the session for a while. If a restart returns ER0360, close the old session with the session-management endpoint or replace your API key to close its sessions.
Connections left open after a client stops
SSE does not exchange ping/pong messages with your application. The API may therefore take time to detect that a client has disconnected:
- On an active feed, the API closes the connection if the client stops reading articles.
- On a quiet feed, the API may keep counting the session until it detects the disconnect or the 6-hour limit ends (
ER0362). Revoking the key (ER0361) or closing the session with the terminate endpoint (ER0364) also frees the connection.
To free the session immediately, call DELETE /v1/news/stream/sessions or replace the API key to close its sessions.
Managing Active Sessions
Use these two free endpoints to list active SSE sessions and close any you no longer need, without replacing your API key.
List active sessions
GET https://api.apitube.io/v1/news/stream/sessionsReturns every SSE session currently open under your account:
{
"count": 2,
"sessions": [
{ "session_id": "req-a1b2c3", "api_key_id": 42, "started_at": "2026-07-03T10:11:04.512Z" },
{ "session_id": "req-d4e5f6", "api_key_id": 42, "started_at": "2026-07-03T10:11:05.973Z" }
]
}Terminate sessions
DELETE https://api.apitube.io/v1/news/stream/sessionsForce-closes your active SSE sessions and returns the number closed. Each closed client receives an error event with code ER0364 and the connection ends:
{ "terminated": 2 }Use optional query parameters to choose which sessions to close:
?session_id=<id>— close only that one session (id from the list endpoint)?api_key_id=<id>— close only sessions opened by that specific key
# Before a scheduled restart: drop every open SSE session for the account
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" \
"https://api.apitube.io/v1/news/stream/sessions"Authenticate both endpoints with your API key. If the key has endpoint restrictions, it must allow stream. You can manage only sessions belonging to that key's account.
Billing
Each article delivered through the stream costs 1 credit. Credits are deducted in real time as articles arrive — not when you open the connection.
How it works:
- When you connect, the server checks your balance. If you have no credits and no paid balance, the connection is rejected with HTTP
402and error codeER0176. - While the stream is active, 1 credit is deducted per article sent to you.
- If your balance runs out mid-stream, the server sends an
errorevent with codeER0301("Balance exhausted") and closes the connection.
Credit source priority:
- If you have available plan credits (points), they are used first.
- If plan credits are exhausted and you have a positive paid balance, the paid balance is used instead.
The stream connection responds with the standard SSE headers only (Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, X-Accel-Buffering: no). It does not return billing state in response headers. To check your remaining plan credits and paid balance, call GET /v1/balance separately.
The stream does not charge for heartbeats or the connection itself — only for actual articles delivered. If no articles match your filters, no credits are spent.
Deduplication and parallel streams
Each connection is billed separately. If the same article matches several of your streams, you pay for each delivery. Removing duplicates in your application does not change those charges.
Reprints from different publishers may arrive as separate articles and are billed separately. Use one stream where possible, or choose filters that do not overlap. In your application, use article id or href to identify duplicates.
Error Handling
Insufficient Balance
If your account has no credits and no paid balance, the server rejects the connection with HTTP 402:
{
"status": "not_ok",
"request_id": "fecf47d8-c90c-4c48-bdf0-bc34f6d41415",
"errors": [
{
"status": 402,
"code": "ER0176",
"message": "You have no SSE points on your account.",
"links": {
"about": "https://docs.apitube.io/platform/news-api/http-response-codes"
},
"timestamp": "2025-05-11T17:02:46Z"
}
]
}Top up your balance or wait for plan credits to renew before reconnecting.
Invalid or Missing API Key
Returns a standard HTTP 401 JSON error response (not SSE):
curl -N -H "X-API-Key: invalid" \
"https://api.apitube.io/v1/news/stream"{
"status": "not_ok",
"request_id": "fecf47d8-c90c-4c48-bdf0-bc34f6d41415",
"errors": [
{
"status": 401,
"code": "ER0202",
"message": "Invalid API key.",
"links": {
"about": "https://docs.apitube.io/platform/news-api/http-response-codes"
},
"timestamp": "2025-05-11T17:02:46Z"
}
]
}A missing API key returns the same response format with code ER0201 (API key is required. Provide it via X-API-Key header or api_key query parameter.).
Balance Exhausted
If your balance runs out during an active stream, the server sends an error event and closes the connection:
event: error
data: {"code":"ER0301","message":"Balance exhausted"}Session Terminated
When you close a session with the terminate endpoint or replace its API key, the client receives an error event and the connection ends:
event: error
data: {"code":"ER0364","message":"SSE session terminated by API"}Reconnect to resume streaming; pass Last-Event-ID to continue from the last article you received.
Next Steps
- Learn about all available Parameters
- Explore common workflow examples
- Check Authentication options
- See HTTP Response Codes for error handling
Support
If you encounter issues:
- Check the Technical FAQ
- Verify your API key on apitube.io
- Contact support through the APITube website