<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: XFINLAB</title>
    <description>The latest articles on DEV Community by XFINLAB (@xfinlab).</description>
    <link>https://dev.to/xfinlab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4106221%2F00a491b4-5d17-470c-83c6-e6b94d2ea972.png</url>
      <title>DEV Community: XFINLAB</title>
      <link>https://dev.to/xfinlab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xfinlab"/>
    <language>en</language>
    <item>
      <title>9 Free Endpoints I Built Into a Financial Data API — With Curl/Python Examples</title>
      <dc:creator>XFINLAB</dc:creator>
      <pubDate>Sat, 12 Sep 2026 13:54:06 +0000</pubDate>
      <link>https://dev.to/xfinlab/9-free-endpoints-i-built-into-a-financial-data-api-with-curlpython-examples-280i</link>
      <guid>https://dev.to/xfinlab/9-free-endpoints-i-built-into-a-financial-data-api-with-curlpython-examples-280i</guid>
      <description>&lt;p&gt;9 Free Endpoints I Built Into a Financial Data API — With Curl/Python Examples&lt;/p&gt;

&lt;p&gt;I've been building XFINLAB, a financial intelligence API — market events, sentiment, technical analysis, macro data — with an MCP server for AI agents on top. Along the way I also built a handful of free, no-key tools directly into the site.&lt;/p&gt;

&lt;p&gt;Sharing the actual working requests here, labeled honestly by which ones you should actually build on vs which are just free site plumbing:&lt;/p&gt;

&lt;p&gt;🔑 Official Intelligence API — versioned, X-API-Key auth, documented, part of the paid product. Safe to build a production integration on.&lt;br&gt;
🌐 Free website tool, no key — powers a public page on xfinlab.com directly. No auth, no versioning guarantee, no SLA. Fine for personal scripts, quick lookups, or prototyping — not recommended for anything you depend on staying stable, since it can change without notice the same way any other part of a website's frontend can.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI Chart Analysis 🔑 (also has a free web version)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Free web tool:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl "&lt;a href="https://api.xfinlab.com/api/chart-search/AAPL?period=6mo&amp;amp;interval=1d" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/chart-search/AAPL?period=6mo&amp;amp;interval=1d&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;Official API (X-API-Key, recommended for real use):&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl "&lt;a href="https://api.xfinlab.com/api/intelligence/v1/technical/AAPL" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/intelligence/v1/technical/AAPL&lt;/a&gt;" \&lt;br&gt;
  -H "X-API-Key: YOUR_KEY"&lt;br&gt;
python&lt;br&gt;
import requests&lt;/p&gt;

&lt;p&gt;r = requests.get(&lt;br&gt;
    "&lt;a href="https://api.xfinlab.com/api/intelligence/v1/technical/AAPL" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/intelligence/v1/technical/AAPL&lt;/a&gt;",&lt;br&gt;
    headers={"X-API-Key": "YOUR_KEY"},&lt;br&gt;
)&lt;br&gt;
data = r.json()["data"]&lt;br&gt;
print(data["confluence"]["direction"], data["confluence"]["confidence_pct"])&lt;br&gt;
print(data["support"], data["resistance"])&lt;/p&gt;

&lt;p&gt;Response includes confluence (direction/confidence/bullish &amp;amp; bearish signal list), trend, support/resistance, decision_levels, and market_structure — all computed from real OHLC history, never AI-guessed. The official API version omits raw OHLC bars (licensing); the free web version includes them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stress Lab 🔑 (also has a free web version)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Free web tool:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl -X POST "&lt;a href="https://api.xfinlab.com/api/stress-lab" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/stress-lab&lt;/a&gt;" \&lt;br&gt;
  -H "Content-Type: application/json" \&lt;br&gt;
  -d '{"symbol": "Stocks/Bonds 60/40", "amount": 100000, "horizon_days": 252}'&lt;/p&gt;

&lt;p&gt;Official API:&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
import requests&lt;/p&gt;

&lt;p&gt;r = requests.post(&lt;br&gt;
    "&lt;a href="https://api.xfinlab.com/api/intelligence/v1/stress-test" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/intelligence/v1/stress-test&lt;/a&gt;",&lt;br&gt;
    headers={"X-API-Key": "YOUR_KEY"},&lt;br&gt;
    json={"symbol": "AAPL", "amount": 100000, "horizon_days": 252},&lt;br&gt;
)&lt;br&gt;
d = r.json()["data"]&lt;br&gt;
print(f"Median outcome: ${d['ending_value_p50']:,.0f}")&lt;br&gt;
print(f"5th percentile (bad case): ${d['ending_value_p5']:,.0f}")&lt;br&gt;
print(f"Median max drawdown: {d['max_drawdown_p50_pct']}%")&lt;/p&gt;

&lt;p&gt;This runs a real bootstrap Monte Carlo over actual historical returns (n_real_observations tells you exactly how much real history backed the simulation) — not a fabricated volatility assumption.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Free Signals 🌐 (no key, no official API equivalent)
bash
curl "&lt;a href="https://api.xfinlab.com/api/free-signals" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/free-signals&lt;/a&gt;"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Returns today's top confluence-ranked signals across stocks/futures/crypto: {date, signals:[{ticker, label, price, confluence_direction, confluence_confidence_pct, ...}], locked_count, plan}. locked_count tells you how many additional rows exist behind a login — this endpoint intentionally rations rows for non-logged-in callers, so don't build anything that assumes a fixed row count.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Opportunity Radar 🔑 (also has a free web version)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Free web tool:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl "&lt;a href="https://api.xfinlab.com/api/free-tools-demo/opportunity-radar" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/free-tools-demo/opportunity-radar&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;Official API:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
curl "&lt;a href="https://api.xfinlab.com/api/intelligence/v1/opportunity-radar" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/intelligence/v1/opportunity-radar&lt;/a&gt;" \&lt;br&gt;
  -H "X-API-Key: YOUR_KEY"&lt;/p&gt;

&lt;p&gt;Both return the same shape: real % change per indicator across real_estate, supply_chain, consumer_demand, energy, agriculture — each indicator reports its own trailing change against itself, never a fabricated cross-industry composite score (see methodology_note in the response for the exact math).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stock Screener 🌐 (no key, no official API equivalent)
bash
curl -X POST "&lt;a href="https://api.xfinlab.com/api/ai-analysis" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/ai-analysis&lt;/a&gt;" \
-H "Content-Type: application/json" \
-d '{"filters": {"sector": "Technology", "growth": "high"}}'&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Returns AI-written commentary (conclusion, analysis) grounded in the filter criteria you pass — this is a free-text research aid, not a structured list-of-tickers-with-scores endpoint. If you need a structured, code-friendly screen, this isn't it yet (flagging as a real gap, not glossing over it).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pairs Statistical Arbitrage Scanner 🌐 (no key, no official API equivalent)
bash
curl -X POST "&lt;a href="https://api.xfinlab.com/api/pairs-scan" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/pairs-scan&lt;/a&gt;" \
-H "Content-Type: application/json" \
-d '{"symbol_a": "KO", "symbol_b": "PEP", "period": "6mo"}'&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Returns z_score, correlation, divergence, and which side of the pair is richer_symbol/cheaper_symbol — a correlation + z-score divergence read on the real historical spread, explicitly not a formal cointegration test (the page says so, and so does the API).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Probability Scan 🌐 (no key, no official API equivalent)
bash
curl "&lt;a href="https://api.xfinlab.com/api/pipeline/AAPL" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/pipeline/AAPL&lt;/a&gt;"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Combines real market data, technicals, and news sentiment into bullish_probability/bearish_probability. The page itself carries a disclaimer that the underlying scoring formulas aren't yet backtested — treat this as a reference number, not a calibrated probability, same as the site does.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;News Denoise Analysis 🌐 (no key, no official API equivalent)
bash
curl -X POST "&lt;a href="https://api.xfinlab.com/api/news-denoise" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/news-denoise&lt;/a&gt;" \
-H "Content-Type: application/json" \
-d '{"topic": "AAPL"}'&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Returns an AI-generated summary (analysis, conclusion) that filters sensationalized language out of recent headlines for a ticker or topic — this is generated live per-request, not pulled from a structured news database, so wording will vary call to call even for the same topic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Portfolio Allocation Analysis 🌐 (no key, no official API equivalent)
bash
curl "&lt;a href="https://api.xfinlab.com/api/portfolio" rel="noopener noreferrer"&gt;https://api.xfinlab.com/api/portfolio&lt;/a&gt;"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without a login token this returns a default basket; with a site-login token query param it personalizes to that user's actual watchlist. Returns suggested allocation weights per ticker based on each ticker's real market score — not equal-weighted, not user-set.&lt;/p&gt;

&lt;p&gt;Which one should you actually build on?&lt;/p&gt;

&lt;p&gt;If you're evaluating XFINLAB as a data provider for something you'll maintain long-term, start with the 3 🔑 endpoints — those are the ones with a documented contract and a reason to expect they won't move under you. The 6 🌐 endpoints are genuinely useful for quick scripts and one-off research, and I'm not hiding them, but they're free-tier site plumbing, not a product commitment.&lt;/p&gt;

&lt;p&gt;Free API key (no card, instant): &lt;a href="https://www.xfinlab.com/intelligence-api.html" rel="noopener noreferrer"&gt;https://www.xfinlab.com/intelligence-api.html&lt;/a&gt; Repo (SDKs + MCP server source): &lt;a href="https://github.com/lnanology/Xfinlab" rel="noopener noreferrer"&gt;https://github.com/lnanology/Xfinlab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Curious what other free-tier financial APIs people here have built — what's your split between "documented product" vs "free site tooling"?&lt;/p&gt;

</description>
      <category>api</category>
      <category>python</category>
      <category>fintech</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why I Made My Financial Data API Return `null` Instead of Guessing</title>
      <dc:creator>XFINLAB</dc:creator>
      <pubDate>Wed, 02 Sep 2026 13:07:44 +0000</pubDate>
      <link>https://dev.to/xfinlab/why-i-made-my-financial-data-api-return-null-instead-of-guessing-2nl7</link>
      <guid>https://dev.to/xfinlab/why-i-made-my-financial-data-api-return-null-instead-of-guessing-2nl7</guid>
      <description>&lt;p&gt;I spent the last several months building out a financial data API&lt;br&gt;
(XFINLAB) that pulls from about 20 different government/exchange sources&lt;br&gt;
— SEC EDGAR, FINRA, CFTC, FDIC, USDA, CBOE, EIA, openFDA, CPSC, a couple&lt;br&gt;
of crypto exchanges. Along the way I made one architectural rule that&lt;br&gt;
ended up shaping almost every collector module: &lt;strong&gt;a field is either a&lt;br&gt;
real value with a source, or it's &lt;code&gt;null&lt;/code&gt; with an explicit reason. Never&lt;br&gt;
an estimate presented as if it were real.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This sounds obvious written down. In practice it's a real design tax.&lt;/p&gt;
&lt;h2&gt;
  
  
  The tempting shortcut
&lt;/h2&gt;

&lt;p&gt;Say you're building a collector for USDA agricultural commodity prices.&lt;br&gt;
The USDA Quick Stats API doesn't always have this year's data yet for a&lt;br&gt;
given commodity — sometimes the most recent real observation is from 8&lt;br&gt;
months ago. The tempting move is to interpolate: draw a line between the&lt;br&gt;
last two known points, guess where "now" would sit on it, ship a number.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;looks&lt;/em&gt; like better data. It demos better. And it's fabricated.&lt;/p&gt;
&lt;h2&gt;
  
  
  What we did instead
&lt;/h2&gt;

&lt;p&gt;Every collector in this codebase follows the same shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_for_ticker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_TICKER_TO_SOURCE_MAPPING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# no linkage, not a guess
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fetch_failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;_load_persisted_fallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# last REAL value we saw, honestly dated
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;real_fresh_value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No collector has a code path that produces a plausible-looking number&lt;br&gt;
that isn't traceable to an actual source and an actual fetch timestamp.&lt;br&gt;
When a value truly isn't available, the API returns an explicit&lt;br&gt;
"unavailable" with a reason (not configured / rate-limited / genuinely&lt;br&gt;
no match for this ticker) — not a zero that looks like a real zero, and&lt;br&gt;
not last year's number silently relabeled as current.&lt;/p&gt;
&lt;h2&gt;
  
  
  Making it checkable, not just claimed
&lt;/h2&gt;

&lt;p&gt;Every collector self-registers into a small SQLite-backed registry at&lt;br&gt;
import time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;register_source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;usda_agriculture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USDA Agricultural Commodity Prices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agriculture&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with &lt;code&gt;record_run_start&lt;/code&gt; / &lt;code&gt;record_run_success&lt;/code&gt; / &lt;code&gt;record_run_error&lt;/code&gt;&lt;br&gt;
wrapping the actual fetch calls. That registry backs a public,&lt;br&gt;
unauthenticated status page — &lt;a href="https://www.xfinlab.com/trust.html" rel="noopener noreferrer"&gt;https://www.xfinlab.com/trust.html&lt;/a&gt; — so&lt;br&gt;
"this data source is honestly reporting, not guessing" isn't just a&lt;br&gt;
claim in the docs, it's something anyone can go check live, updated in&lt;br&gt;
real time, including which sources are currently down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters more in 2026 than it used to
&lt;/h2&gt;

&lt;p&gt;Q1 2026 reportedly saw $2.3B in trading losses tied to AI-generated&lt;br&gt;
misstated earnings figures, and FINRA's 2026 Annual Oversight Report&lt;br&gt;
devoted its first-ever dedicated section to AI/hallucination risk for&lt;br&gt;
broker-dealers. 62% of enterprise AI users now cite hallucinations as&lt;br&gt;
their top deployment barrier. None of that is about financial data APIs&lt;br&gt;
specifically, but it's the same underlying failure mode: a plausible&lt;br&gt;
number that isn't real, presented with no way to tell the difference.&lt;/p&gt;

&lt;p&gt;The fix isn't really an AI problem to solve with a better model — it's&lt;br&gt;
an interface design problem. Make the "I don't know" path a first-class,&lt;br&gt;
explicit response, not a bug to route around.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you want to see it live
&lt;/h2&gt;

&lt;p&gt;The API's free tier is instant, no card — 20+ endpoints, Python/JS SDKs,&lt;br&gt;
and an MCP server if you're wiring this into an agent:&lt;br&gt;
&lt;a href="https://www.xfinlab.com/intelligence-api.html" rel="noopener noreferrer"&gt;https://www.xfinlab.com/intelligence-api.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Curious how other API builders here handle this same tradeoff —&lt;br&gt;
especially anyone working with genuinely gappy upstream sources. Do you&lt;br&gt;
interpolate, forward-fill, or null-and-explain?&lt;/p&gt;

</description>
      <category>api</category>
      <category>python</category>
      <category>fastapi</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
