Skip to content

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-ID to receive articles missed during a disconnection
  • All /everything filters supported — language, category, sentiment, entities, and more
  • Field selection with fl parameter to keep responses smaller

Endpoint ​

http
GET https://api.apitube.io/v1/news/stream

Authentication ​

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 ​

bash
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) ​

javascript
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 ​

javascript
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));
    }
});
TIP

The eventsource npm package supports custom headers, which makes it the recommended choice for Node.js.

Python ​

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 ​

text
event: article
id: 123456
data: {"id":123456,"title":"...","source":{...},...}
  • event: article — event type
  • id: — article ID (used for reconnection)
  • data: — full article JSON in the same format as the /everything endpoint

error — Server Error ​

text
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:

CodeMeaning
ER0301Streaming credits and pay-as-you-go balance are both exhausted.
ER0177The monthly pay-as-you-go spending limit was reached while the stream was billing to your balance.
ER0361The API key was revoked while the stream was open.
ER0362The 6-hour connection lifetime was reached — reconnect (with Last-Event-ID to resume).
ER0364The session was force-closed through the terminate endpoint.

Heartbeat ​

text
: heartbeat

The 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:

bash
curl -N -H "X-API-Key: YOUR_API_KEY" \
  "https://api.apitube.io/v1/news/stream?language.code=en"

By category:

bash
curl -N -H "X-API-Key: YOUR_API_KEY" \
  "https://api.apitube.io/v1/news/stream?category.id=medtop:13000000"

By source:

bash
curl -N -H "X-API-Key: YOUR_API_KEY" \
  "https://api.apitube.io/v1/news/stream?source.domain=theverge.com"

Multiple filters:

bash
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:

bash
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:

bash
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_at is 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_age sets 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:

    bash
    curl -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.start excludes articles published before the date and time you set:

    bash
    curl -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:

  1. Connect and receive articles — each has a unique id:
  2. Connection drops (network issue, server restart, etc.)
  3. Reconnect with the last received ID:
bash
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.

TIP

The browser's EventSource reconnects automatically and sends Last-Event-ID to resume after the last received event.

Parameters ​

ParameterDescription
api_keyAPI key (alternative to X-API-Key header)
flField selection (e.g., id,title,source.domain)
stream.max_ageMaximum article age in minutes. Only articles published within the last N minutes are delivered and billed. An invalid value returns 400 ER0363.
All /everything filterslanguage.code, category.id, source.domain, sentiment.overall.polarity, title, organization.name, and more

Technical Details ​

PropertyValue
Poll intervalEvery 30 seconds
Heartbeat intervalEvery 30 seconds
Articles per poll cycleUp to 50
Delivery orderWithin each batch, articles arrive in published_at order, oldest first. Articles are tracked by ID to avoid missing or repeating deliveries.
Maximum article ageSet stream.max_age in minutes to exclude older articles before delivery and billing.
Billing1 credit per delivered article
ReconnectionVia Last-Event-ID header
Response headerX-Accel-Buffering: no

Concurrent Connections ​

Your plan limits how many SSE connections you can keep open at the same time:

PlanMax concurrent SSE connections
Free1
Starter2
Basic2
Professional10
Corporate50

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:

json
{
    "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 ​

http
GET https://api.apitube.io/v1/news/stream/sessions

Returns every SSE session currently open under your account:

json
{
    "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 ​

http
DELETE https://api.apitube.io/v1/news/stream/sessions

Force-closes your active SSE sessions and returns the number closed. Each closed client receives an error event with code ER0364 and the connection ends:

json
{ "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
bash
# 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:

  1. When you connect, the server checks your balance. If you have no credits and no paid balance, the connection is rejected with HTTP 402 and error code ER0176.
  2. While the stream is active, 1 credit is deducted per article sent to you.
  3. If your balance runs out mid-stream, the server sends an error event with code ER0301 ("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.

TIP

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:

json
{
    "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):

bash
curl -N -H "X-API-Key: invalid" \
  "https://api.apitube.io/v1/news/stream"
json
{
    "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:

text
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:

text
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 ​

Support ​

If you encounter issues:

  1. Check the Technical FAQ
  2. Verify your API key on apitube.io
  3. Contact support through the APITube website