# Financial Data API: 1,255 Daily Bars, Both Closes (https://www.socialcrawl.dev/blog/financial-data-api) > Financial data API: 1,255 AAPL daily bars with both closes, plus statements, an 81-contract options chain, and ticker news. Live from GET /v1/finance/. A financial data API in 2026 is four joinable surfaces, not a quote panel. Quote, ticker-search, and markets paint a panel. A client does not buy a panel. It buys daily OHLCV with corporate actions on the same row, statements that reuse the field names already on a quote, an options chain you can filter, and ticker news that concats with a web news-search row. History APIs usually make you pick adjusted *or* unadjusted close. Statements live under different field names than the quote, so you write a second mapper. News is a proprietary object that will not concat with a web news-search row. Korean filings need a different parser again. Then I measured. One `GET /v1/finance/history` on AAPL over 2021-09-05 through 2026-09-05 returned **1,255 daily bars**, `close` and `adj_close` on the same row, **20** dated dividend rows, **0** splits, **1 credit**. That number is why this post exists. So I shipped four new reads under `GET /v1/finance/`: history, statements, options, news. I left quote, ticker-search, and markets unchanged on purpose. Moving them would have dropped fields already populated. Old `/v1/google_finance/` paths still resolve. Below is the live harvest from 2026-09-05 — real curl, trimmed JSON, 15 credits billed — plus the Korean supporting cut and the limits I will not paper over. A row of daily candlestick bars from a stock price history API, each session marked with stacked discs for close and adjusted close. ## How do you pull stock price history (1,255 daily bars, both closes) from the API? Most stock price history APIs make you pick a close. This one does not. [`GET /v1/finance/history`](/platforms/finance/history) returns daily bars with `close` and `adj_close` on the same row, and corporate actions as dated rows in the same list. Default `interval` is `1d`. No second call for the adjustment. No third call for the dividend calendar. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/history?keyword=AAPL&start_date=2021-09-05&end_date=2026-09-05" ``` Pulled 2026-09-05, 00:46–00:49 UTC. **1,255** daily bars. Range returned 2021-09-07 → 2026-09-04 (weekends and unlisted sessions omitted). `currency=USD` on 1,255/1,255. **1,254** rows have both `close` and `adj_close`. **19** rows where they are equal. **20** dividend rows. **0** split rows. **1 credit**. First bar, `2021-09-07T13:30:00Z`: ```json { "id": "AAPL:2021-09-07T13:30:00Z", "symbol": "AAPL", "date": "2021-09-07T13:30:00Z", "open": 154.97000122070312, "high": 157.25999450683594, "low": 154.38999938964844, "close": 156.69000244140625, "adj_close": 152.83091735839844, "volume": 82278300, "dividend": null, "split_ratio": null, "currency": "USD", "interval": "1d" } ``` Open 154.97, high 157.26, low 154.39, close **156.69**, adj_close **152.83**. That is a $3.86 gap on day one of a five-year window. Substituting one for the other compounds that gap the further back you go. Use `adj_close` for total return. Use `close` when you want the print close that actually traded that session. Dividends sit on the session they take effect, same list, not a second endpoint. First captured: **0.22** on 2021-11-05. Last captured, `2026-08-10T13:30:00Z`: ```json { "id": "AAPL:2026-08-10T13:30:00Z", "symbol": "AAPL", "date": "2026-08-10T13:30:00Z", "open": 306.8299865722656, "high": 308.260009765625, "low": 304.6099853515625, "close": 308.260009765625, "adj_close": 308.260009765625, "volume": 44812500, "dividend": 0.27, "split_ratio": null, "currency": "USD", "interval": "1d" } ``` On 2026-08-10, `close` equals `adj_close` (308.26) because the dividend is already on the row as `dividend: 0.27`. This pull found **zero** `split_ratio` rows. Do not write a split that is not there. Last bar, `2026-09-04T13:30:00Z`: ```json { "id": "AAPL:2026-09-04T13:30:00Z", "symbol": "AAPL", "date": "2026-09-04T13:30:00Z", "open": 328.30499267578125, "high": 328.92999267578125, "low": 317.8599853515625, "close": null, "adj_close": null, "volume": 38272821, "dividend": null, "split_ratio": null, "currency": "USD", "interval": "1d" } ``` Open 328.305, high 328.930, low 317.860, volume 38,272,821, **close null**, **adj_close null**. Volume showed up. The close did not. The session is not finalized. Do not treat ticker-search's 319.97 as that bar's close — 319.97 is `price.current` from a different read, timestamped `2026-09-05 00:30:00 +00:00`. In a stock data API pipeline, join on `date`. The dividend is already on the bar. ## Can one financial statements API call return income, balance sheet, and cash flow? Yes. One [`GET /v1/finance/statements`](/platforms/finance/statements) call returns income, balance sheet, and cash flow as a single `statement: "combined"` object per period. Field names match the financials block on a quote (`revenue`, `net_income`, `earnings_per_share`, `free_cash_flow`). You parse the quote financials block and this list with the same mapper. `_delta` is the period-over-period **fractional** change, not a percentage point: `revenue_delta: 0.064` is +6.4%, not 0.064%. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/statements?keyword=AAPL" ``` Default `type=annual`. **5 credits**. **5** reporting periods (`2021-09-30` … `2025-09-30`). **4** populated. FY2021 is identity-only: the oldest period has nothing to compare against, so the numeric leaves are null. "5 periods" is not "5 complete statements". | period_end | revenue | net_income | EPS | free_cash_flow | |---|---:|---:|---:|---:| | 2021-09-30 | — | — | — | — (identity only) | | 2022-09-30 | 394,328,000,000 | 99,803,000,000 | 6.11 | 111,443,000,000 | | 2023-09-30 | 383,285,000,000 | 96,995,000,000 | 6.13 | 99,584,000,000 | | 2024-09-30 | 391,035,000,000 | 93,736,000,000 | 6.08 | 108,807,000,000 | | 2025-09-30 | **416,161,000,000** | **112,010,000,000** | **7.46** | 98,767,000,000 | Latest populated period, trimmed: ```json { "symbol": "AAPL", "statement": "combined", "period_type": "annual", "period_end": "2025-09-30T00:00:00Z", "revenue": 416161000000, "revenue_delta": 0.0642551178283274, "net_income": 112010000000, "net_income_delta": 0.19495177946573355, "earnings_per_share": 7.46, "free_cash_flow": 98767000000, "free_cash_flow_delta": -0.09227347505215656 } ``` FY2025 revenue 416,161,000,000 against FY2024's 391,035,000,000 is that 0.064 fraction. Net income 112,010,000,000 is the 0.195 jump. Free cash flow 98,767,000,000 is the −0.092 move. All three statements, one object. **31 populated financial leaves** — canonical keys that were non-null in at least one period, identity keys (`id`, `symbol`, `statement`, `period_type`, `period_end`) excluded. Always null on this surface, every period: `currency`, `price_to_book`, `return_on_assets`, `return_on_capital`. That 31 is the honest count. It is not a 143-item chart of accounts. `period_end` is fiscal period end, not filing date. Filing dates live on [SEC EDGAR](https://www.sec.gov/edgar/browse/?CIK=320193), not on this row. Restatements overwrite. This surface cannot reconstruct what was known on a past date. Delay and point-in-time limits sit two sections down. Samsung quarterly `005930.KS` is the same combined shape in won-scale magnitudes. Full numbers in the Korean section. Call and put contract tiles fanned around one strike peg, the same calls-and-puts list an options chain API returns. ## How do you fetch an options chain — 81 contracts, calls and puts, IV — for one expiry? [`GET /v1/finance/options`](/platforms/finance/options) is an options chain API: calls and puts in one flat list. Filter on `option_contract.type`. Default `keyword=AAPL` is the **nearest** expiry, not every listed expiry. Pass a different expiry when you want a later one; this harvest did not walk the rest of the calendar. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/options?keyword=AAPL" ``` First attempt returned 503 `SERVICE_UNAVAILABLE` ("retry after 30s") and billed **0** — auto-refunded. The retry ~90 seconds later billed **5** and succeeded. The first attempt was not clean. The refund was. **81** contracts (**39 calls / 42 puts**). **1** expiry in the default response (`2026-09-09T00:00:00Z`). Strike 240–405. 77 with bid and ask. 76 with open interest. **81 with implied volatility**. 21 ITM calls / 17 ITM puts. Three rows from the same response: | contract_symbol | type | strike | last | bid | ask | volume | OI | IV | ITM | |---|---|---:|---:|---:|---:|---:|---:|---:|---| | `AAPL260909C00250000` | call | 250 | 61.42 | 69.05 | 71.85 | — | 1 | 1.143 | true | | `AAPL260909C00320000` | call | 320 | 3.74 | 3.80 | 3.90 | 14,431 | 6,926 | 0.262 | false | | `AAPL260909P00320000` | put | 320 | 3.85 | 3.75 | 3.85 | 8,621 | 2,721 | 0.257 | true | ```json [ { "contract_symbol": "AAPL260909C00250000", "type": "call", "strike": 250, "expiry": "2026-09-09T00:00:00Z", "last_price": 61.42, "bid": 69.05, "ask": 71.85, "volume": null, "open_interest": 1, "implied_volatility": 1.142582412109375, "in_the_money": true }, { "contract_symbol": "AAPL260909C00320000", "type": "call", "strike": 320, "expiry": "2026-09-09T00:00:00Z", "last_price": 3.74, "bid": 3.8, "ask": 3.9, "volume": 14431, "open_interest": 6926, "implied_volatility": 0.26197027099609377, "in_the_money": false }, { "contract_symbol": "AAPL260909P00320000", "type": "put", "strike": 320, "expiry": "2026-09-09T00:00:00Z", "last_price": 3.85, "bid": 3.75, "ask": 3.85, "volume": 8621, "open_interest": 2721, "implied_volatility": 0.2567213000488281, "in_the_money": true } ] ``` Ticker-search had AAPL at 319.97, so the 320-strike pair is the near-the-money row. The 320 call is out of the money (IV 0.262, volume 14,431). The 320 put is in the money (IV 0.257, volume 8,621). The 250 call is deep ITM with `volume: null` and open interest 1 — a contract that exists, not a contract that traded that session. Calls and puts share one list. Contract symbols follow [OCC OSI](https://www.theocc.com/) (`AAPL260909C00250000` is AAPL, 2026-09-09, call, strike 250). Fields present: strike, bid, ask, open_interest, implied_volatility. This is not an execution feed. The delay is in the limits section. ## How do you get ticker news in the same row shape as Google News search? [`GET /v1/finance/news`](/platforms/finance/news) is a ticker news API that returns a `NewsArticleList`. Article fields match [the Google News search row](/platforms/google_news): `id`, `title`, `url`, `source`, `domain`, `snippet`, `image_url`, `published_at`, `rank`, `placement`. Only `placement` differs (`ticker_news` vs `news_search` / `top_stories`). Concat the two arrays. The unified schema is the point: you do not write a second news parser. It is stock market data API output you can join, not a second news object to special-case. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/news?keyword=AAPL" ``` **10** articles. **1 credit**. `page_size=10`, `dropped=0`, every row `placement=ticker_news`. `snippet` was null on the captured rows. Rank 1, full article object: ```json { "id": "6571f3fe-4381-306c-9df3-a7b8ebcdf27c", "title": "Why Apple (AAPL) Dipped More Than Broader Market Today", "url": "https://finance.yahoo.com/markets/stocks/articles/why-apple-aapl-dipped-more-214503780.html", "source": "Zacks", "domain": "finance.yahoo.com", "snippet": null, "image_url": "https://s.yimg.com/uu/api/res/1.2/G.Op7E_jldj.32ijwZluBQ--~B/aD03NDE7dz05MDA7YXBwaWQ9eXRhY2h5b24-/https://media.zenfs.com/en/zacks.com/7853de8d69faeccb7d1ad6ebba40b8a2.jpg", "published_at": "2026-09-04T21:45:03Z", "rank": 1, "placement": "ticker_news" } ``` Rank 1 is the [Zacks piece carried on Yahoo Finance](https://finance.yahoo.com/markets/stocks/articles/why-apple-aapl-dipped-more-214503780.html) (`published_at` 2026-09-04T21:45:03Z). This is ticker news, not a filings feed. Rank 8 is a broad-market futures headline that merely mentions Apple. Sources in the 10: Zacks, MT Newswires, Yahoo Finance Video, Motley Fool, 24/7 Wall St., Investor's Business Daily, Proactive. ## Do Korean instruments return the same shapes in won? Same schema. Same reads. Won magnitudes. That is the stock market API test I actually ran: a US-only combined object is a US object with extra fields, not a schema that held. Hangul is locale-sensitive. Live, this harvest: - `keyword=삼성전자` under the default US/English locale → **0 items**, 0 credits. - `keyword=삼성전자` with `language=ko` and `location=South Korea` → **5 hits**, #1 `005930:KRX` 삼성전자 at **255,500 KRW**. Also preferred `005935:KRX` (삼성전자우, 191,600). - Numeric `keyword=005930` (English locale) → **4 hits**, #1 `005930:KRX` 255,500 KRW, then unrelated Israeli-bank collisions (`FBKIF` / `FIBI`). Take rank 1 and stop, or use Hangul plus locale. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/ticker-search?keyword=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90&language=ko&location=South%20Korea" ``` Identifier rule, said plainly: ticker-search returns `TICKER:EXCHANGE` (`005930:KRX`). History and statements that succeeded in this pull used **`005930.KS`**. Those two strings are not the same. This harvest did not re-paste `005930:KRX` into history. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/history?keyword=005930.KS&start_date=2021-09-05&end_date=2026-09-05" ``` **1,220** daily bars. `currency=KRW` on every bar. 20 dividend rows, 0 splits. Last close **255,500**. Cache hit (0 credits this run). First bar, `2021-09-06`: ```json { "id": "005930.KS:2021-09-06T00:00:00Z", "symbol": "005930.KS", "date": "2021-09-06T00:00:00Z", "open": 76800, "high": 77600, "low": 76600, "close": 77300, "adj_close": 69932.9609375, "volume": 12861180, "dividend": null, "split_ratio": null, "currency": "KRW", "interval": "1d" } ``` Close **77,300**, adj_close **69,932.96**. Same close-versus-adjusted trap as AAPL, five years earlier, in won. ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/statements?keyword=005930.KS&type=quarterly" ``` **6** periods (5 populated). `2024-12-31` is identity-only. Latest `2026-03-31`: revenue **133,873,444,000,000**, net income **47,101,190,000,000**, EPS **7,056**. **29** populated leaves. Statements `currency` leaf is **always null** — read the unit off history `bar.currency=KRW`. Magnitudes are won-scale (10¹³–10¹⁴). ```json { "symbol": "005930.KS", "statement": "combined", "period_type": "quarterly", "period_end": "2026-03-31T00:00:00Z", "currency": null, "revenue": 133873444000000, "revenue_delta": 0.42665382217496267, "net_income": 47101190000000, "earnings_per_share": 7056, "free_cash_flow": 22097151000000 } ``` I did not pull Samsung options or Samsung news this harvest. Those rows are not below. ## What does this financial data API not do? Prices are delayed. Documented on the [changelog](/changelog), not re-measured this harvest. Korea / London / Tokyo **~20 minutes**. US options **~15 minutes**. This is not a trading feed. The last AAPL history bar has volume and a null close — consistent with an unfinalized session, not proof of the delay table. | Venue | Documented delay | |---|---| | Korea | 20 minutes | | London | 20 minutes | | Tokyo | 20 minutes | | US options | 15 minutes | Product-documented, not independently timed on 2026-09-05. Statements are keyed by fiscal period end, not filing date. No point-in-time reconstruction. Restatements overwrite. The oldest period is identity-only (AAPL FY2021; Samsung 2024-12-31). Delisted companies return nothing. A recycled ticker returns whoever holds the symbol today. First-trade date is product-documented so you can detect the recycle yourself, but it was **not re-measured** this harvest — ticker-search `metrics` was null on the captured rows. I am not going to claim I proved it live. **31 ≠ 143.** I counted canonical populated leaves, not raw upstream line items. Options: one expiry per default call, not a walk of every listed expiry. A 503 happened; credits refunded; retry worked. Quote and markets were **not called** this harvest. They exist. I left them unchanged on purpose. There is no sample payload for them in this post, because there was no pull. ## How do you start using this financial data API? Get a key. Free credits land on signup. The smallest first call under `GET /v1/finance/` is ticker-search: ```bash curl -s -H "x-api-key: $SOCIALCRAWL_API_KEY" \ "https://www.socialcrawl.dev/v1/finance/ticker-search?keyword=Apple" ``` **5** hits. **1 credit**. Rank 1 is `AAPL:NASDAQ` at **319.97 USD** (timestamp `2026-09-05 00:30:00 +00:00`). Hit 5 is a name collision: Apple Hospitality REIT (`APLE:NYSE`) at 15.60. Feed bare `AAPL` into history, statements, options, and news. Downstream reads in this pull used `AAPL`, not `AAPL:NASDAQ`. The current prefix is `/v1/finance/`. I moved it because the surface is no longer a Google Finance panel emulator. Old `/v1/google_finance/` paths **still resolve**. Existing keys keep working. I did not break them. Seven reads, one API key: | Read | Path | Status | Credits this harvest | What came back | |---|---|---|---:|---| | quote | [`/v1/finance/quote`](/platforms/finance/quote) | unchanged | — (not pulled) | same fields as before (the stock quote API you already have) | | ticker-search | [`/v1/finance/ticker-search`](/platforms/finance/ticker-search) | unchanged | 1 | 5 Apple listings | | markets | [`/v1/finance/markets`](/platforms/finance/markets) | unchanged | — (not pulled) | same fields as before | | history | [`/v1/finance/history`](/platforms/finance/history) | new | 1 | 1,255 AAPL bars | | statements | [`/v1/finance/statements`](/platforms/finance/statements) | new | 5 | 5 annual periods, 31 leaves | | options | [`/v1/finance/options`](/platforms/finance/options) | new | 5 | 81 contracts, 1 expiry | | news | [`/v1/finance/news`](/platforms/finance/news) | new | 1 | 10 articles | Harvest billed **15**. The other 2 credits were Korean ticker-search lookups (Hangul plus locale, and numeric `005930`). Cache hits and the 503 refund billed 0. [Per-endpoint credit costs](/docs/endpoint-pricing) are the live table. Where next: [the visual explorer](/explorer) if you want to see the envelope before writing a single line, and [the finance platform reference](/platforms/finance) for params. Pricing-versus-panel is a different post. ## Frequently asked questions ### Are quotes on this financial data API delayed, and by how much per exchange? Yes. Documented on the [changelog](/changelog), not re-timed this harvest: Korea / London / Tokyo ~20 minutes; US options ~15 minutes. This is not a trading feed. The last AAPL history bar had volume 38,272,821 with a null close, which is consistent with an unfinalized session, not a stopwatch on the delay table. ### What happens if I query a delisted ticker? Product-documented: empty. A recycled symbol returns whoever holds it today. First-trade date is the documented way to detect the recycle. It was not re-measured on this pull — ticker-search `metrics` was null — so I am not pasting a field I did not capture. ### Does the API cover Korean instruments, including statements in won? Yes. Same shapes. Live cut: 1,220 KRW daily bars; 6 quarterly periods; Q1 2026 revenue 133,873,444,000,000. Hangul needs `language=ko` and `location=South Korea`. History and statements used `005930.KS`, not the search id `005930:KRX`. The statements `currency` leaf is null; the unit is on the history bar (`currency=KRW`). ### How many credits does each finance read cost? This harvest: ticker-search 1, history 1, statements 5, options 5, news 1. Quote and markets were not pulled (unchanged). Korean ticker-search added 2. Total billed **15**. The 503 on options refunded. Cache hits billed 0. See [per-endpoint credit costs](/docs/endpoint-pricing) for the live ladder. ### Do the old `/v1/google_finance/` paths still resolve? Yes. Current prefix is `/v1/finance/`. Existing integrations keep working. I moved the prefix because the surface is seven reads, not a three-read panel. ### Can I use this as a Google Finance API without changing parsers? Old paths still resolve, same envelope. For the provider roundup, the pricing table, and "is there an official Google Finance API?", that is [Google Finance API pricing compared](/blog/best-google-finance-apis-2026) — the July 2026 comparison. This post is the four new reads, measured. ### How do I detect a recycled ticker if the symbol still returns data? Product-documented: a first-trade date on the row. **Not re-measured** this harvest. Ticker-search `metrics` was null on every captured Apple and Samsung row. Do not copy a field I did not capture. I used to ship three finance reads and call it done. Four more does not make this a tape. The delay table is the point of saying that out loud. If a market or identifier is missing — especially a non-US listing — tell me and I'll try to add it. Korean was the test that the schema had to hold. The explorer and the key form are linked above. Happy hacking. — Oscar