A tour of RTPR Wire
Wire is the real-time PR newswire dashboard you log into to read, filter, and alert on press releases the second they hit the wire. This page walks through every section of the app, with a deep focus on filter rules and a separate technical section for connecting to the alerts WebSocket.
What you get
When you sign in, you land on /wire. The header shows your plan, a live connection indicator, and four tabs:
- Live — the firehose plus your ticker spotlight and watchlist.
- Rules — your saved filter rules and the articles they've matched.
- Connect — your API key and the real-time alerts WebSocket details (Pro only).
- Account — billing, plan, cancellation.
The Live Wire
The center of the dashboard is the live firehose: every press release from Business Wire, PR Newswire, GlobeNewswire and AccessWire as it crosses the tape. New rows fade in at the top with a gentle pulse so your eye catches movement without the page feeling chaotic.
Each row shows the ticker, the headline, the wire source, and a latency pill telling you how fast we delivered it. Click any row to open the full article — body text, tickers mentioned, and a permalink you can share.
Ticker Spotlight
The left panel on the Live tab is the spotlight. Type a ticker (e.g. AAPL) and the panel pivots to show every article RTPR has stored for that ticker over the last 365 days, newest first. Useful for checking the recent news context before placing a trade.
Articles in the spotlight are clickable and open the same full-article view as the firehose.
Watchlist
The bottom-right panel is your watchlist. Add tickers you care about and the panel filters down to only those tickers as new articles arrive on the firehose. Think of it as an attention spotlight for your own portfolio without losing the broader feed.
The watchlist lives in your browser, so it's instant and free. To get a server-side push when something matches, use Filter Rules.
Filter Rules
Rules are the heart of Wire. A rule is a saved condition that evaluates against every press release in real time. When an article matches, the row appears in your Rules tab feed and a real-time alert fires (in-app, by email, and on the alerts WebSocket if you're connected).
There are three ways to build a rule, and they all produce the same underlying JSON definition — pick whichever fits how you think:
- AI builder (recommended) — describe what you want in plain English (e.g. "FDA approvals for small-cap biotech, skip earnings") and RTPR generates a validated rule plus a plain-English explanation of what it does. Refine it with one-tap chips — tighten, broaden, add a condition, start over — and test it inline. It's the default tab when you create a rule and the fastest way to a working rule.
- Visual builder — add and edit conditions field-by-field with dropdowns. Best for fine-tuning an AI-generated rule or hand-building a simple one without touching JSON.
- JSON — write the rule definition directly. The full power of the DSL (nested groups,
not, proximity, numeric thresholds) lives here, and everything below documents this format.
A Test tab lets you run any rule against a sample article before you save. You can switch tabs at any time — generate with AI, fine-tune in the visual builder, and drop to JSON for the last 10%.
The basic shape
Every rule is a boolean tree of conditions. The root is one of three combinators:
all— every child must match (AND).any— at least one child must match (OR).not— exactly one child, inverted.
Leaves are conditions that look at one field of the article (title, body, ticker, exchange, etc.) using one operator (contains, equals, in, proximity, numeric_match, etc.).
Example 1 — A single keyword in the title
The simplest possible rule: alert on every article with the word bankruptcy in the title.
{
"field": "title",
"op": "keyword",
"value": "bankruptcy"
}`keyword` does case-insensitive word-boundary matching, so it won't match the word `bankruptcy` if it appears as part of a longer word.
Example 2 — Two keywords, either one is fine
Use any when more than one phrase should trigger the same alert.
{
"any": [
{ "field": "title_or_body", "op": "keyword", "value": "FDA approval" },
{ "field": "title_or_body", "op": "keyword", "value": "FDA authorization" },
{ "field": "title_or_body", "op": "keyword", "value": "FDA clearance" }
]
}`title_or_body` searches the headline and the article text in one pass.
Example 3 — Keyword AND a watchlist of tickers
Use all when several conditions must all be true.
{
"all": [
{
"field": "tickers",
"op": "in",
"value": ["AAPL", "MSFT", "NVDA", "GOOGL", "AMZN", "META"]
},
{ "field": "title", "op": "keyword", "value": "upgrade" }
]
}Example 4 — Numeric thresholds in the body
numeric_match parses currency, percentages and counts directly out of the article text, including suffixes like "5B" for $5 billion. You only need to give it a min or max bound.
{
"all": [
{
"field": "title_or_body",
"op": "keyword",
"value": "share repurchase"
},
{
"field": "title_or_body",
"op": "numeric_match",
"kind": "currency",
"min": 5000000000
}
]
}Supported `kind` values: `currency`, `percentage`, `count`.
Example 5 — Words near each other (proximity)
Sometimes the words you care about have to appear close to each other to mean what you think they mean. proximity matches when every term in terms appears in the field within within tokens of each other.
{
"all": [
{
"field": "title_or_body",
"op": "in",
"value": ["phase 2", "phase 3", "phase ii", "phase iii"]
},
{
"field": "body",
"op": "proximity",
"terms": ["primary", "endpoint"],
"within": 4
}
]
}Example 6 — Excluding noise with `not`
Use not to subtract: alert on contract wins for biotech tickers, but skip earnings noise.
{
"all": [
{ "field": "exchange", "op": "in", "value": ["NASDAQ", "NYSE"] },
{
"field": "title_or_body",
"op": "any",
"value": ["contract award", "supply agreement", "DOD contract"]
},
{
"not": {
"field": "title",
"op": "contains",
"value": "earnings"
}
}
]
}Example 7 — A complex multi-leg rule
Putting it all together — a small-cap FDA approval that triggers only during market hours, capped at 30 alerts per hour with a friendly display name and a throttle.
{
"name": "Small-biotech FDA, market hours",
"active": true,
"definition": {
"all": [
{
"any": [
{ "field": "title_or_body", "op": "keyword", "value": "FDA approval" },
{ "field": "title_or_body", "op": "keyword", "value": "FDA clearance" },
{
"field": "body",
"op": "proximity",
"terms": ["Phase", "3", "endpoint"],
"within": 6
}
]
},
{ "field": "exchange", "op": "in", "value": ["NASDAQ", "NYSE"] },
{ "field": "tickers_length", "op": "lte", "value": 2 },
{ "field": "session", "op": "in", "value": ["pre_market", "regular"] }
]
},
"throttle": { "max_per_hour": 30 }
}`session` recognises `pre_market`, `regular`, `after_hours`, `overnight`, `weekend`. `tickers_length` is the number of tickers mentioned — useful to avoid round-up press releases.
Quick reference
Available fields:
title,body,title_or_body— the article textticker,tickers,tickers_length— the symbols mentionedexchange— NASDAQ, NYSE, OTC, etc.author— the wire sourcecreated— publish timestampsession— market session at publish time
Common operators:
contains,keyword— substring vs. whole-word matchstarts_with,ends_with,equalsin,not_in— membership in a listgt,gte,lt,lte— numeric comparisonsproximity— terms near each othernumeric_match— currency / percentage / count thresholds
Real-time Alerts
When a rule matches, RTPR delivers the alert through three channels:
- In the dashboard — a row appears in the Rules tab matched-feed within milliseconds, even on tabs you're not looking at.
- In your inbox — optional email per rule (Pro).
- On your personal socket — a coalesced JSON frame on the alerts WebSocket, ready to be piped into your own trading system.
All three fire from the same backend evaluation, so they stay in sync. If three rules match a single article, the dashboard shows three rows but the WebSocket emits a single coalesced frame with all three rule names — your downstream code stays simple.
Alerts WebSocket Reference
The alerts WebSocket is for programmatic use — your trading bot, your own dashboard, a notification bridge. It's available on the Pro plan; the API key and connection snippet for your account live in the Connect tab.
Endpoint
wss://ws.rtpr.io/ws-alerts?apiKey=YOUR_API_KEY
Authentication
Pass your API key as a query string parameter. The server closes the connection with code 4001 if the key is invalid, or 4004 if your subscription is no longer active. Treat any close as a cue to re-authenticate (refresh the key from the Connect tab) and reconnect with backoff.
Payload
When one of your rules matches an article, the gateway emits a single coalesced frame for that customer + article pair, even if several rules fired. Programmatic clients route on rule_name.
{
"type": "alert",
"ticker": "AAPL",
"rules": [
{ "rule_name": "Apple guidance" },
{ "rule_name": "Big tech FOMC" }
],
"article_published_at": "2026-04-29T18:30:00Z",
"article_url": "https://rtpr.io/a/lseg_n123?exp=1777497120&sig=ab12..."
}The frame is intentionally minimal: it tells you which ticker, which rules, and where to read the article. Use article_url exactly as sent.
Signed permalink URL (hot window)
Alerts include a signed permalink in article_url with exp and sig query parameters. This token is short-lived (hot window, currently 2 minutes after publish) and speeds first-access fetching.
Single URL contract: clients should always request the same article_url they received. During the hot window the signature can authorize access directly; after expiry the same URL continues to work when the request includes your API key (or an authenticated dashboard session).
curl -H "X-API-Key: YOUR_API_KEY" \ "https://rtpr.io/a/lseg_n123?exp=1777497120&sig=ab12..." # same URL after expiry -> falls back to key/session auth curl -H "X-API-Key: YOUR_API_KEY" \ "https://rtpr.io/a/lseg_n123?exp=1777497120&sig=ab12..."
Best practice for newer builders: keep your HTTP connection warm (HTTP keep-alive). In plain English: reuse one request session/client instead of opening a brand-new HTTPS connection for every article. During bursts, this is often one of the biggest reasons fetches stay fast.
Heartbeat
The server sends a JSON {"type":"ping"} every 30 seconds. Reply with {"type":"pong"}. If the server doesn't see your pong within 90 seconds it will close the connection.
Minimal Python client
# pip install websockets
import asyncio, json, websockets
URL = "wss://ws.rtpr.io/ws-alerts?apiKey=YOUR_API_KEY"
async def run():
async with websockets.connect(URL) as ws:
async for raw in ws:
msg = json.loads(raw)
if msg.get("type") == "alert":
names = [r["rule_name"] for r in msg["rules"]]
print(f"{msg['ticker']} matched: {', '.join(names)}")
print(f" -> {msg['article_url']}")
elif msg.get("type") == "ping":
await ws.send(json.dumps({"type": "pong"}))
asyncio.run(run())Minimal Node.js client
// npm install ws
const WebSocket = require('ws');
const ws = new WebSocket(
'wss://ws.rtpr.io/ws-alerts?apiKey=YOUR_API_KEY'
);
ws.on('message', (raw) => {
const msg = JSON.parse(raw);
if (msg.type === 'alert') {
const names = msg.rules.map((r) => r.rule_name).join(', ');
console.log(`${msg.ticker} matched: ${names}`);
console.log(` -> ${msg.article_url}`);
} else if (msg.type === 'ping') {
ws.send(JSON.stringify({ type: 'pong' }));
}
});
ws.on('close', (code) => {
console.log('Closed', code, '— reconnect with backoff');
});Article Feed API
The Article Feed API is the REST counterpart to the alerts WebSocket — a pull surface for fetching recent articles on demand instead of waiting for a push. Use it to backfill on startup, build an API-driven version of Ticker Spotlight, or poll the wire from a server. It's available on the Pro plan and authenticates with the same API key as the WebSocket.
article_url with your API key to read full content. This is the recommended programmatic surface; the older full-payload endpoints are being phased out.Endpoints
# All articles for one ticker, newest first (API version of Spotlight)
GET https://api.rtpr.io/feed/articles/{ticker}
# Most recent across every ticker, newest first (body-free firehose)
GET https://api.rtpr.io/feed/articlesAuthentication
Pass your API key as a bearer token. The same key from the Connect tab works for both REST and the WebSocket.
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.rtpr.io/feed/articles/AAPL?limit=50"
Query parameters
limit— page size, 1–500. Defaults to 20 for/feed/articlesand 50 for the per-ticker endpoint.next_token— opaque pagination cursor returned in each response. Pass it back to fetch the next page.
Response
The same body-free shape as a WebSocket alert frame: each item is a ticker, a publish time, and a permalink you follow with your API key.
{
"count": 2,
"articles": [
{
"ticker": "AAPL",
"article_published_at": "2026-04-29T18:30:00Z",
"article_url": "https://rtpr.io/a/lseg_n123"
},
{
"ticker": "AAPL",
"article_published_at": "2026-04-28T13:05:00Z",
"article_url": "https://rtpr.io/a/lseg_n119"
}
],
"next_token": "eyJ0aWNrZXIiOiJBQVBMI..."
}Pagination
Keep requesting with the next_token from the previous response until it comes back null — that's the last page. Articles are retained for 365 days.
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.rtpr.io/feed/articles/AAPL?limit=50&next_token=eyJ0aWNrZXIiOiJBQVBMI..."
Plans & Limits
- Free — Live firehose with a 5-minute delay. Read-only access to rules and alerts (so you can see what Pro gets). Ticker spotlight and watchlist work with full functionality.
- Pro ($139/month) — Real-time firehose, create up to 25 filter rules, real-time alerts in-app, by email and on the dedicated WebSocket. Includes a 7-day free trial.
Hard caps per rule: 200 conditions, 50 KB serialized JSON, 20 keywords or tickers per in list. Throttle ranges from 1 to 10,000 alerts per hour. Articles are retained for 365 days.