Developer guide · June 29, 2026

Options Flow API: How to Access Unusual Options Data Programmatically

Options flow data is most powerful when it feeds into automated systems: alerting bots, portfolio monitors, quantitative screens. This page covers the data fields that matter, REST vs. WebSocket, and working integrations in Python, JavaScript, and cURL.

What an Options Flow API Does

An options flow API is a programmatic interface to unusual options activity data: the same prints that flow platforms surface in their dashboards, but delivered as structured JSON you can consume in code. Instead of watching a browser dashboard, your application receives flow data and acts on it: sends a Discord alert, logs to a database, evaluates a trading rule, or triggers a webhook.

The API layer sits on top of the same underlying pipeline: raw OPRA tape → filter for unusual prints → score and classify → deliver. What changes is the delivery mechanism: JSON over HTTP (REST) or a persistent connection that pushes prints as they arrive (WebSocket).

REST vs. WebSocket: Which to Use

The choice between REST and WebSocket depends on what you're building:

TransportUse whenLatencyServer load
WebSocket (stream)Live tape, real-time alerts, intraday botsMillisecondsLow (one persistent connection)
REST (/flow/top)Dashboard snapshots, periodic polling, morning scansSecondsModerate (one request per poll)
REST (/flow/heatmap)Sector analysis, batch reportingSecondsLow (occasional reads)
REST (/flow/historical)Backtesting, post-session analysisN/ALow (infrequent)

For a live Discord alert bot, use WebSocket. Polling a REST endpoint every second both misses prints between polls and creates server load for nothing. For a morning scanner that runs at open and reports the top signals, REST is simpler and sufficient.

The Data Fields That Matter

A quality options flow API response includes these fields at minimum. If a provider's response is missing more than two or three of these, the API is not suitable for serious flow research:

FieldWhy it mattersRed flag if missing
tickerSymbol identifier
typeCALL or PUT
strikeContract strike price
expiry / expiryDateContract expiration
dteDays to expiry, high-signal for urgency (0DTE, weekly)High
volumeContracts traded this print
openInterest / oiExisting book for this contractHigh
volOIvolume / openInterest, the core unusualness metricCritical
premiumTotal dollar value of the trade
sideASK / BID / MID, the aggressor direction flagHigh
kindSWEEP / BLOCK / SPLIT, the execution urgency flagCritical
otmPctPercent out-of-the-money; filters lottery ticketsMedium
spotUnderlying price at time of printMedium
ivImplied volatilityMedium
scoreComposite unusualness score (0–100)High if absent
biasBULL / BEAR / NEUTRAL, a computed directional labelUseful for bots
sectorGICS sector classification of underlyingUseful for screening
timestampUnix ms or ISO 8601 print time

Authentication

Most options flow APIs use API key authentication via an HTTP header. Two common patterns:

# Pattern 1 — x-api-key header (most common)
curl -H "x-api-key: YOUR_KEY" \
  https://api.radarpulse.io/v1/flow/top

# Pattern 2 — Bearer token
curl -H "Authorization: Bearer YOUR_KEY" \
  https://api.radarpulse.io/v1/flow/top

Never hardcode an API key in source code. Store it as an environment variable and load it at runtime:

# .env file (never commit to git)
RADARPULSE_API_KEY=frk_your_key_here

# Python: load with python-dotenv
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["RADARPULSE_API_KEY"]

REST API: Fetching Top Flow

The most common REST endpoint is /flow/top, which returns the top-N highest-scoring unusual prints for the current (or a specified) session.

Python example

import os, requests

API_KEY = os.environ["RADARPULSE_API_KEY"]
BASE = "https://api.radarpulse.io/v1"

def get_top_flow(limit=25, min_score=70):
    resp = requests.get(
        f"{BASE}/flow/top",
        headers={"x-api-key": API_KEY},
        params={"limit": limit, "minScore": min_score},
        timeout=10,
    )
    resp.raise_for_status()
    return resp.json()["data"]

for print_ in get_top_flow():
    print(
        f"{print_['ticker']:6} {print_['type']:4} "
        f"${print_['strike']} exp {print_['expiry']} "
        f"vol/OI={print_['volOI']:.1f} "
        f"prem=${print_['premium']:,.0f} "
        f"score={print_['score']}"
    )

JavaScript (Node.js) example

const API_KEY = process.env.RADARPULSE_API_KEY;
const BASE = "https://api.radarpulse.io/v1";

async function getTopFlow({ limit = 25, minScore = 70 } = {}) {
  const url = new URL(`${BASE}/flow/top`);
  url.searchParams.set("limit", limit);
  url.searchParams.set("minScore", minScore);
  const res = await fetch(url, { headers: { "x-api-key": API_KEY } });
  if (!res.ok) throw new Error(await res.text());
  const { data } = await res.json();
  return data;
}

const prints = await getTopFlow({ minScore: 80 });
prints.forEach(p =>
  console.log(`${p.ticker} ${p.type} $${p.strike} score=${p.score} prem=$${p.premium.toLocaleString()}`)
);

WebSocket: Building a Live Alert Bot

For a Discord or Slack bot, connect to the WebSocket endpoint and push formatted alerts as prints arrive. The pattern is: connect → authenticate → receive prints → filter → post to webhook.

Python Discord bot (websockets + aiohttp)

import asyncio, json, os
import websockets
import aiohttp

API_KEY = os.environ["RADARPULSE_API_KEY"]
WS_URL = "wss://api.radarpulse.io/v1/stream"
DISCORD_WEBHOOK = os.environ["DISCORD_WEBHOOK_URL"]

MIN_SCORE = 85      # EXTREME signals only
MIN_PREM  = 500_000 # $500K+ premium

async def post_discord(session, print_):
    bias_emoji = "🐂" if print_.get("bias") == "BULL" else "🐻"
    kind_tag = " ⚡ SWEEP" if print_.get("kind") == "SWEEP" else ""
    msg = (
        f"**{print_['ticker']} {print_['type']} ${print_['strike']} "
        f"exp {print_['expiry']}**{kind_tag}\n"
        f"Premium: ${print_['premium']:,.0f} | Vol/OI: {print_['volOI']:.1f}× | "
        f"Score: {print_['score']} {bias_emoji}"
    )
    await session.post(DISCORD_WEBHOOK, json={"content": msg})

async def stream_flow():
    async with aiohttp.ClientSession() as session:
        async with websockets.connect(
            WS_URL,
            extra_headers={"x-api-key": API_KEY},
        ) as ws:
            async for raw in ws:
                print_ = json.loads(raw)
                if (
                    print_.get("score", 0) >= MIN_SCORE
                    and print_.get("premium", 0) >= MIN_PREM
                    and print_.get("side") == "ASK"  # bought at ask
                ):
                    await post_discord(session, print_)

asyncio.run(stream_flow())

REST API: Score Explanation Endpoint

A quality flow API exposes a score explanation endpoint that tells you which factors (Vol/OI, premium size, DTE, OTM distance) drove the composite score for a specific print. Useful for building "why this signal" features in your application.

# GET /v1/score-explain?ticker=NVDA&strike=200&type=CALL&expiry=2026-07-18

{
  "score": 91,
  "flag": "EXTREME",
  "scoreParts": {
    "volOI": 34,    // out of 40 — highest weight
    "premium": 28,  // out of 30
    "dte": 16,      // out of 20 — 14 DTE is "hot"
    "otm": 13       // out of 10 — slightly OTM
  }
}

Outbound Webhooks (Server-to-Server)

Instead of maintaining a persistent WebSocket connection in your application, some APIs offer outbound webhooks: you register a URL and the API POSTs each qualifying print to it. This is simpler to operate (no persistent connection to maintain) and works well for serverless architectures.

# Register a webhook (POST /v1/webhooks)
curl -X POST \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server.com/flow-hook","minScore":75,"events":["flow.extreme","flow.elevated"]}' \
  https://api.radarpulse.io/v1/webhooks

# Response
{
  "id": "wh_abc123",
  "secret": "whsec_..."  // use to verify HMAC-SHA256 signature
}

Validate the webhook signature on every incoming request to prevent spoofed payloads:

import hmac, hashlib

def verify_webhook(payload_bytes, signature_header, secret):
    expected = hmac.new(
        secret.encode(), payload_bytes, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature_header)

Rate Limits and Best Practices

  • Cache aggressively. /flow/top data doesn't change more than once per print (every few seconds live, slower for delayed feeds). Cache the response for 5–10 seconds before re-fetching rather than polling as fast as possible.
  • Use exponential backoff on 429 responses. If the API returns 429 (rate limit), wait 2s, then 4s, then 8s before retrying. Don't retry immediately.
  • Prefer WebSocket for live use. One persistent connection uses far fewer resources than polling REST every few seconds and provides lower latency.
  • Filter server-side when available. Pass minScore, ticker, or minPremium query parameters so the server filters before sending, reducing payload size and your parsing overhead.
  • Store API keys in environment variables. Never commit an API key to source code, even private repositories. Use .env files locally and secrets management in production (AWS Secrets Manager, Railway Secrets, Doppler).

What to Look for in a Quality Options Flow API

  • Sweep and block flags are non-negotiable. An API that doesn't flag execution type is missing the most important signal in the flow.
  • Vol/OI computed per-contract. Ticker-level OI ratios dilute the signal; you need the ratio at the specific strike and expiry.
  • HMAC-signed webhooks. Any webhook provider that doesn't sign payloads exposes you to spoofed requests. The signature header should use HMAC-SHA256.
  • Historical endpoint for backtesting. A live-only API limits your ability to build and validate filters on past sessions.
  • Clear tier documentation. The API documentation should state precisely which data is available at each tier (Elite vs. Pro) and what latency each tier provides.

RadarPulse Developer API

RadarPulse's API layer is built on the same scoring engine the app uses. Every print you'd see in the Top 25 view or Whale Detector is available programmatically. The endpoint set includes:

  • GET /v1/flow: paginated scored flow for the current session
  • GET /v1/flow/top: top-N highest-scoring prints
  • GET /v1/score-explain: factor breakdown for any scored print
  • GET /v1/heatmap: sector and ticker flow aggregates
  • GET /v1/congress: Congressional STOCK Act disclosures (Pro+)
  • WebSocket /v1/stream: live scored prints as they arrive
  • POST /v1/webhooks: register outbound webhook endpoints

All REST endpoints accept x-api-key header authentication. API keys are generated in-app under the Developer Console (Elite tier). Outbound webhooks are HMAC-SHA256 signed. SSRF protection is enforced on webhook URLs: private IP ranges and localhost are blocked.

Join the waitlist → to get early Elite access and a developer API key when the API launches.

Frequently Asked Questions

What is an options flow API?

An options flow API is a programmatic interface that provides access to unusual options activity data without a browser. Developers use it to build alerting bots, automate trading research, integrate flow signals into existing tools, and send alerts to Discord, Slack, or custom webhooks.

What data fields does an options flow API return?

A quality API returns: ticker, type (CALL/PUT), strike, expiry, DTE, volume, open interest, Vol/OI ratio, premium, aggressor side (bid/ask/mid), execution type (sweep/block/split), implied volatility, OTM%, spot price, and a composite score. Sector classification and directional bias are useful additions for bot filtering.

Should I use REST or WebSocket for options flow?

Use WebSocket for real-time streaming (alerts fire the moment a print arrives) and REST for snapshot reads, periodic polls, or historical queries. Live alert bots need WebSocket; polling REST every second misses prints and creates unnecessary load.

How do I verify an options flow webhook signature?

Compute an HMAC-SHA256 of the raw request body using your webhook secret, then compare it to the signature in the request header (typically X-Signature or X-Webhook-Signature). Use constant-time comparison (hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js) to prevent timing attacks. Reject any request where the signatures don't match.

What's the minimum API tier for live options flow data?

Real-time flow (sub-second) typically requires an Elite-tier API key. 15-minute delayed flow is usually available at Pro tier. Free API access, when offered, provides end-of-day or sample data only. The data latency tier is the primary pricing axis for options flow APIs.

Can I use the API for high-frequency or automated trading?

Options flow APIs are designed for research and signal generation, not order routing. They provide analytical data (unusual activity, unusualness scores, sector flow) that you integrate into your trading workflow. Order execution is handled separately through your broker's API. Most provider terms of service prohibit using the API for automated order routing without explicit permission.

What programming languages can I use?

Any language with HTTP and WebSocket libraries works. Python is most common for trading automation (requests, websockets, pandas). JavaScript/Node.js is popular for Discord/Slack bots (ws library, Discord.js). Go and Rust are used in latency-sensitive applications. All examples in this guide can be adapted to any language with standard networking support.

Access the RadarPulse API

Elite members get an API key, WebSocket stream access, and webhook management in the in-app Developer Console. All endpoints include scored flow with sweep/block flags, Vol/OI, and sector classification.

Join the waitlist →