shredio / fmp-client
Requires
- php: >=8.4
- halaxa/json-machine: ^1.2
- league/csv: ^9.27
- psr/simple-cache: >=1.0
- shredio/type-schema: ^0.10.1
- symfony/http-client: ^7.2 || ^8.0
Requires (Dev)
- nette/utils: ^4.0
- phpstan/phpstan: ^2.1
- phpstan/phpstan-webmozart-assert: ^2.0
- phpunit/phpunit: ^12.2
- shredio/type-schema-compiler: ^0.11
- symfony/cache: ^7.4 || ^8.0
- symfony/translation: ^7.3 || ^8.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-13 18:17:21 UTC
README
A high-performance PHP client library for the Financial Modeling Prep (FMP) API, designed to handle large financial datasets efficiently with memory-conscious streaming and asynchronous processing.
Key Features
- Memory Efficient: Large JSON/CSV responses are streamed using JsonMachine and League CSV, not loaded entirely into memory
- Async Support: Non-blocking concurrent API requests using PHP Fibers via FmpPromise
- Strong Typing: All data structures use readonly classes with comprehensive type hints
- Immutable Payloads: All payload objects are immutable with readonly properties
- Validation: Optional strict mode for enhanced data validation
- Bulk Operations: Efficient handling of bulk data endpoints
- Error Handling: Comprehensive exception handling with request URL context
Requirements
- PHP 8.4 or higher
- Symfony HTTP Client
- JsonMachine for efficient JSON parsing
- League CSV for CSV processing
- Webmozart Assert for validation
Installation
Install via Composer:
composer require shredio/fmp-client
Quick Start
use Shredio\FmpClient\SymfonyFmpClient; use Symfony\Component\HttpClient\HttpClient; // Initialize the client $httpClient = HttpClient::create(); $fmpClient = new SymfonyFmpClient($httpClient, 'your-api-key-here'); // Get company profile foreach ($fmpClient->companyProfile('AAPL') as $profile) { echo "Company: {$profile->companyName}\n"; echo "Price: ${$profile->price}\n"; echo "Market Cap: {$profile->marketCap}\n"; } // Get stock list (streamed) foreach ($fmpClient->stockList() as $stock) { echo "{$stock->symbol}: {$stock->name}\n"; }
Configuration Options
Strict Mode
Enable strict mode for enhanced validation that throws exceptions on invalid data:
$strictClient = $fmpClient->withStrictMode(true); try { foreach ($strictClient->companyProfile('INVALID') as $profile) { // Process profile } } catch (UnexpectedResponseContentException $e) { echo "Validation error: {$e->getMessage()}\n"; echo "Request URL: {$e->getRequestUrl()}\n"; }
Unknown Keys
When the API returns keys that a payload does not know (e.g. a newly added field), strict mode throws
UnexpectedResponseContentException. In non-strict mode the payload is returned without the unknown keys
and the problem is passed to the error handler with noticesOnly set to true.
Custom Error Handling
Implement custom error handling for non-strict mode (useful for logging):
use Shredio\FmpClient\Exception\UnexpectedResponseContentExceptionHandler; $handler = new class implements UnexpectedResponseContentExceptionHandler { public function handle(UnexpectedResponseContentException $exception): void { if ($exception->noticesOnly) { // the payload was returned, e.g. the API added a new key error_log("FMP Client Notice: {$exception->getMessage()}"); return; } // the payload was discarded error_log("FMP Client Error: {$exception->getMessage()}"); } }; $fmpClient = new FmpClient($httpClient, 'api-key', $handler);
Usage Examples
Basic Stock Data
use Shredio\FmpClient\Enum\PeriodQuery; // Get available exchanges foreach ($fmpClient->availableExchanges() as $exchange) { echo "{$exchange->name} ({$exchange->code})\n"; } // Get company financials foreach ($fmpClient->balanceSheetStatement('AAPL') as $statement) { echo "Date: {$statement->date}\n"; echo "Total Assets: {$statement->totalAssets}\n"; } // Get financial statement growth metrics foreach ($fmpClient->incomeStatementGrowth('AAPL', limit: 5, period: PeriodQuery::Quarter) as $growth) { echo "Date: {$growth->date}\n"; echo "Revenue Growth: {$growth->growthRevenue}\n"; echo "Net Income Growth: {$growth->growthNetIncome}\n"; } // Get revenue breakdown by product line foreach ($fmpClient->revenueProductSegmentation('AAPL') as $segmentation) { echo "Fiscal Year: {$segmentation->fiscalYear}\n"; foreach ($segmentation->data as $product => $revenue) { echo " {$product}: {$revenue} {$segmentation->reportedCurrency}\n"; } } // Get dividend history foreach ($fmpClient->dividends('AAPL') as $dividend) { echo "Date: {$dividend->date}, Amount: {$dividend->dividend}\n"; } // Get a quote for a single symbol $quote = $fmpClient->quote('AAPL'); if ($quote !== null) { echo "Price: {$quote->price} ({$quote->changePercentage}%)\n"; echo "Market Cap: {$quote->marketCap}\n"; } // Get shares float information $sharesFloat = $fmpClient->getSharesFloat('AAPL'); if ($sharesFloat !== null) { echo "Free Float: {$sharesFloat->freeFloat}%\n"; echo "Float Shares: {$sharesFloat->floatShares}\n"; echo "Outstanding Shares: {$sharesFloat->outstandingShares}\n"; }
Bulk Operations
use DateTimeImmutable; // Bulk company profiles (memory efficient streaming) foreach ($fmpClient->companyProfileBulk() as $profile) { echo "{$profile->symbol}: {$profile->companyName}\n"; } // End of day bulk quotes $date = new DateTimeImmutable('2024-01-15'); foreach ($fmpClient->eodBulkQuotes($date) as $quote) { echo "{$quote->symbol}: Close ${$quote->close}\n"; } // Bulk financial statements foreach ($fmpClient->incomeStatementBulk('2023') as $statement) { echo "{$statement->symbol}: Revenue {$statement->revenue}\n"; } // Bulk analyst rating consensus foreach ($fmpClient->gradesConsensusBulk() as $grades) { echo "{$grades->symbol}: {$grades->consensus}\n"; } // Bulk price target summaries foreach ($fmpClient->priceTargetSummaryBulk() as $summary) { echo "{$summary->symbol}: {$summary->lastYearCount} targets, average {$summary->lastYearAvgPriceTarget}\n"; } // Bulk DCF valuations, FMP ratings and the earnings surprises of a year foreach ($fmpClient->discountedCashFlowBulk() as $valuation) { echo "{$valuation->symbol}: DCF {$valuation->dcf}, price {$valuation->stockPrice}\n"; } foreach ($fmpClient->ratingBulk() as $rating) { echo "{$rating->symbol}: {$rating->rating}\n"; } foreach ($fmpClient->earningsSurprisesBulk(2026) as $surprise) { echo "{$surprise->symbol} {$surprise->date}: actual {$surprise->epsActual}, estimated {$surprise->epsEstimated}\n"; }
Calendar Data
use DateTimeImmutable; use Psr\Log\NullLogger; $from = new DateTimeImmutable('2024-01-01'); $to = new DateTimeImmutable('2024-01-31'); $logger = new NullLogger(); // Earnings calendar (automatically paginated) foreach ($fmpClient->earningsCalendar($from, $to, $logger) as $earning) { echo "Date: {$earning->date}\n"; echo "Symbol: {$earning->symbol}\n"; echo "EPS Estimate: {$earning->epsEstimate}\n"; } // Detailed earnings calendar with report time (bmo/amc), period ending and confirmation flag (automatically paginated) foreach ($fmpClient->detailedEarningsCalendar($from, $to, $logger) as $earning) { echo "{$earning->symbol} - {$earning->date} [{$earning->time}]\n"; echo " EPS: {$earning->epsActual} (est. {$earning->epsEstimated}), confirmed: {$earning->confirmed}\n"; } // Dividends calendar foreach ($fmpClient->dividendsCalendar($from, $to, $logger) as $dividend) { echo "{$dividend->symbol}: {$dividend->dividend} on {$dividend->date}\n"; } // Historical stock splits for a single symbol foreach ($fmpClient->splits('AAPL') as $split) { echo "{$split->symbol}: {$split->numerator}:{$split->denominator} on {$split->date}\n"; } // Stock splits calendar foreach ($fmpClient->splitsCalendar($from, $to, $logger) as $split) { echo "{$split->symbol}: {$split->numerator}:{$split->denominator} on {$split->date}\n"; } // Economic calendar (macroeconomic events; automatically paginated for large date ranges) foreach ($fmpClient->economicCalendar($from, $to, $logger) as $event) { echo "{$event->date} [{$event->country}] {$event->event} (impact: {$event->impact})\n"; echo " Previous: {$event->previous}, Estimate: {$event->estimate}, Actual: {$event->actual}\n"; } // IPO calendar (expected and priced initial public offerings) foreach ($fmpClient->iposCalendar($from, $to, $logger) as $ipo) { echo "{$ipo->date} {$ipo->symbol} ({$ipo->exchange}): {$ipo->company} - {$ipo->actions}, {$ipo->priceRange}\n"; }
The calendar endpoints (earningsCalendar, detailedEarningsCalendar, dividendsCalendar, splitsCalendar, iposCalendar, economicCalendar) accept any window: the client walks it backwards from to page by page. FMP silently narrows every request to roughly the last 90 days before to, so an empty page is not the end of the window - the walk steps 90 days back and continues until it passes from. A window ending a year ahead therefore still returns everything announced in between, even when its tail holds nothing yet.
Historical Data
use DateTimeImmutable; use Shredio\FmpClient\Enum\TimeInterval; $from = new DateTimeImmutable('2024-01-01'); $to = new DateTimeImmutable('2024-01-31'); // Historical end-of-day prices (also works with forex pairs, e.g. 'EURUSD') // Ranges exceeding the API limit of 5000 records per request are fetched in multiple requests automatically foreach ($fmpClient->historicalPriceEod('AAPL', $from, $to) as $price) { echo "Date: {$price->date}, Close: ${$price->close}\n"; } // Historical end-of-day prices, lightweight (only date, price and volume) foreach ($fmpClient->historicalPriceEodLight('AAPL', $from, $to) as $price) { echo "Date: {$price->date}, Price: ${$price->price}\n"; } // Historical end-of-day prices without split adjustments foreach ($fmpClient->historicalPriceEodNonSplitAdjusted('AAPL', $from, $to) as $price) { echo "Date: {$price->date}, Close: ${$price->adjClose}\n"; } // Historical chart data with intervals foreach ($fmpClient->historicalChart('AAPL', TimeInterval::FiveMin, $from, $to) as $data) { echo "Time: {$data->date}, Price: ${$data->close}\n"; }
Financial Metrics and Ratios
use Shredio\FmpClient\Enum\PeriodQuery; // Key metrics foreach ($fmpClient->keyMetrics('AAPL', 10, PeriodQuery::Annual) as $metrics) { echo "Date: {$metrics->date}\n"; echo "P/E Ratio: {$metrics->peRatio}\n"; echo "ROE: {$metrics->roe}\n"; } // TTM (Trailing Twelve Months) metrics foreach ($fmpClient->keyMetricsTtm('AAPL') as $metrics) { echo "Market Cap: {$metrics->marketCapTtm}\n"; echo "Revenue TTM: {$metrics->revenueTtm}\n"; } // Financial ratios foreach ($fmpClient->ratios('AAPL', 5, PeriodQuery::Quarterly) as $ratios) { echo "Current Ratio: {$ratios->currentRatio}\n"; echo "Debt to Equity: {$ratios->debtEquityRatio}\n"; } // Market risk premium by country foreach ($fmpClient->marketRiskPremium() as $premium) { echo "Country: {$premium->country} ({$premium->continent})\n"; echo "Country Risk Premium: {$premium->countryRiskPremium}%\n"; echo "Total Equity Risk Premium: {$premium->totalEquityRiskPremium}%\n"; } // Trailing twelve months income statements foreach ($fmpClient->incomeStatementTtm('AAPL', limit: 4) as $statement) { echo "Date: {$statement->date} ({$statement->period->value})\n"; echo "TTM Revenue: {$statement->revenue}\n"; } // Valuation and analyst sentiment $priceTarget = $fmpClient->priceTargetConsensus('AAPL'); if ($priceTarget !== null) { echo "Consensus Target: {$priceTarget->targetConsensus}\n"; } $dcf = $fmpClient->discountedCashFlow('AAPL'); if ($dcf !== null) { echo "DCF: {$dcf->dcf}, Stock Price: {$dcf->stockPrice}\n"; } $grades = $fmpClient->gradesConsensus('AAPL'); if ($grades !== null) { echo "Consensus: {$grades->consensus} (buy: {$grades->buy}, hold: {$grades->hold}, sell: {$grades->sell})\n"; } // Rating changes foreach ($fmpClient->grades('AAPL', limit: 10) as $grade) { echo "{$grade->date} {$grade->gradingCompany}: {$grade->previousGrade} -> {$grade->newGrade} ({$grade->action})\n"; } // Rating distribution over time (monthly snapshots) foreach ($fmpClient->gradesHistorical('AAPL', limit: 12) as $snapshot) { echo "{$snapshot->date}: buy {$snapshot->analystRatingsBuy}, hold {$snapshot->analystRatingsHold}, sell {$snapshot->analystRatingsSell}\n"; } // Number and average of the published price targets $priceTargetSummary = $fmpClient->priceTargetSummary('AAPL'); if ($priceTargetSummary !== null) { echo "Last quarter: {$priceTargetSummary->lastQuarterCount} targets, average {$priceTargetSummary->lastQuarterAvgPriceTarget}\n"; } // US Treasury rates foreach ($fmpClient->treasuryRates() as $rate) { echo "Date: {$rate->date}\n"; echo "1 Month: {$rate->month1}%, 3 Month: {$rate->month3}%\n"; echo "1 Year: {$rate->year1}%, 10 Year: {$rate->year10}%\n"; echo "30 Year: {$rate->year30}%\n"; }
Ownership, Congress Trades and Transcripts
// Insider transactions foreach ($fmpClient->insiderTrades('AAPL', limit: 20) as $trade) { echo "{$trade->transactionDate} {$trade->reportingName} ({$trade->typeOfOwner})\n"; echo " {$trade->transactionType}: {$trade->securitiesTransacted} @ {$trade->price}\n"; } // Insider transactions aggregated per quarter foreach ($fmpClient->insiderTradeStatistics('AAPL') as $statistics) { echo "{$statistics->year} Q{$statistics->quarter}: {$statistics->totalPurchases} purchases, {$statistics->totalSales} sales\n"; } // Institutional ownership from the 13F filings of a single quarter $positions = $fmpClient->institutionalPositionsSummary('AAPL', 2026, 2); if ($positions !== null) { echo "{$positions->investorsHolding} institutions hold {$positions->ownershipPercent}%\n"; echo "New positions: {$positions->newPositions}, closed positions: {$positions->closedPositions}\n"; } // The largest institutional holders of the quarter foreach ($fmpClient->institutionalHolders('AAPL', 2026, 2, limit: 20) as $holder) { echo "{$holder->investorName}: {$holder->sharesNumber} shares ({$holder->ownership}%), change {$holder->changeInSharesNumber}\n"; } // Trades disclosed by U.S. senators foreach ($fmpClient->senateTrades('AAPL', limit: 20) as $trade) { echo "{$trade->transactionDate} {$trade->firstName} {$trade->lastName} ({$trade->district})\n"; echo " {$trade->type}: {$trade->amount}\n"; } // Trades disclosed by members of the U.S. House of Representatives foreach ($fmpClient->houseTrades('AAPL', limit: 20) as $trade) { echo "{$trade->transactionDate} {$trade->firstName} {$trade->lastName} ({$trade->district})\n"; echo " {$trade->type}: {$trade->amount}\n"; } // Upcoming and historical earnings reports for a single symbol foreach ($fmpClient->earnings('AAPL', limit: 8) as $report) { echo "{$report->date}: actual {$report->epsActual}, estimated {$report->epsEstimated}\n"; } // The latest earning call transcript foreach ($fmpClient->earningCallTranscriptDates('AAPL') as $date) { $transcript = $fmpClient->earningCallTranscript('AAPL', $date->fiscalYear, $date->quarter); if ($transcript !== null) { echo "{$transcript->date} {$transcript->period->value} {$transcript->year}\n"; echo substr($transcript->content, 0, 200) . "\n"; } break; }
Latest Feeds
Feeds of the newest records across all symbols, ordered from the newest to the oldest. The API serves at most 101 pages (0-100) of each feed.
use DateTimeImmutable; // Insider transactions filed since yesterday foreach ($fmpClient->insiderTradesLatest(limit: 1000, from: new DateTimeImmutable('yesterday')) as $trade) { echo "{$trade->filingDate} {$trade->symbol} {$trade->reportingName}: {$trade->transactionType}\n"; } // Analyst price targets and rating actions foreach ($fmpClient->priceTargetLatestNews(limit: 100) as $news) { echo "{$news->publishedDate} {$news->symbol}: {$news->priceTarget} by {$news->analystCompany}\n"; } foreach ($fmpClient->gradesLatestNews(limit: 100) as $news) { echo "{$news->publishedDate} {$news->symbol}: {$news->action} to {$news->newGrade} by {$news->gradingCompany}\n"; } // The same news for a single symbol foreach ($fmpClient->priceTargetNews('AAPL', limit: 20) as $news) { echo "{$news->publishedDate}: {$news->priceTarget} ({$news->newsTitle})\n"; } // 13F filings, congress disclosures and earning call transcripts foreach ($fmpClient->institutionalOwnershipLatest(limit: 100) as $filing) { echo "{$filing->acceptedDate} {$filing->name}: {$filing->formType} for {$filing->date}\n"; } foreach ($fmpClient->senateTradesLatest(limit: 100) as $trade) { echo "{$trade->disclosureDate} {$trade->firstName} {$trade->lastName}: {$trade->type} {$trade->assetDescription}\n"; } foreach ($fmpClient->houseTradesLatest(limit: 100) as $trade) { echo "{$trade->disclosureDate} {$trade->firstName} {$trade->lastName}: {$trade->type} {$trade->assetDescription}\n"; } foreach ($fmpClient->earningCallTranscriptLatest() as $transcript) { echo "{$transcript->date} {$transcript->symbol} {$transcript->period->value} {$transcript->fiscalYear}\n"; }
ETFs, Index Constituents and Batch Requests
use DateTimeImmutable; use Shredio\FmpClient\Enum\StockIndex; // Profile of an ETF with its sector breakdown $info = $fmpClient->etfInfo('VWCE.DE'); if ($info !== null) { echo "{$info->name} by {$info->etfCompany}, expense ratio {$info->expenseRatio}%\n"; foreach ($info->sectorsList as $sector) { echo " {$sector->industry}: {$sector->exposure}%\n"; } } // Holdings, ordered from the largest to the smallest position foreach ($fmpClient->etfHoldings('SPY') as $holding) { echo "{$holding->asset} {$holding->name}: {$holding->weightPercentage}%\n"; } // Holdings of every fund at once, streamed part by part (several hundred megabytes each) foreach ($fmpClient->etfHoldingsBulk() as $holding) { echo "{$holding->symbol}: {$holding->asset} {$holding->name} {$holding->weightPercentage}%\n"; } // Sector and country allocation foreach ($fmpClient->etfSectorWeightings('SPY') as $weighting) { echo "{$weighting->sector}: {$weighting->weightPercentage}%\n"; } foreach ($fmpClient->etfCountryWeightings('VWCE.DE') as $weighting) { echo "{$weighting->country}: {$weighting->weightPercentage}%\n"; } // Current members of an index and the changes of its composition foreach ($fmpClient->indexConstituents(StockIndex::Sp500) as $constituent) { echo "{$constituent->symbol} {$constituent->name} ({$constituent->sector})\n"; } foreach ($fmpClient->historicalIndexConstituents(StockIndex::Nasdaq) as $change) { echo "{$change->date} {$change->changeType}: +{$change->addedTicker} -{$change->removedTicker}\n"; } // Quotes and market capitalizations of many symbols in one call, lists of any length are split into requests automatically foreach ($fmpClient->batchQuote(['AAPL', 'SAP.DE', '^GSPC', 'BTCUSD', 'EURUSD']) as $quote) { echo "{$quote->symbol}: {$quote->price} ({$quote->changePercentage}%)\n"; } foreach ($fmpClient->marketCapitalizationBatch(['AAPL', 'MSFT', 'SAP.DE']) as $capitalization) { echo "{$capitalization->symbol}: {$capitalization->marketCap}\n"; } // Daily market capitalization, ranges over 5000 records are fetched in multiple requests automatically $history = $fmpClient->historicalMarketCapitalization('AAPL', new DateTimeImmutable('2000-01-01'), new DateTimeImmutable()); foreach ($history as $capitalization) { echo "{$capitalization->date}: {$capitalization->marketCap}\n"; } // Executives of a company foreach ($fmpClient->keyExecutives('AAPL') as $executive) { echo "{$executive->name}, {$executive->title}\n"; }
Asynchronous Operations
// Execute multiple requests concurrently $companyProfilePromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->companyProfile('AAPL')) ); $dividendsPromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->dividends('AAPL')) ); $keyMetricsPromise = $fmpClient->promise(fn() => iterator_to_array($fmpClient->keyMetrics('AAPL')) ); // Wait for all promises to complete $profiles = $companyProfilePromise->wait(); $dividends = $dividendsPromise->wait(); $metrics = $keyMetricsPromise->wait(); echo "Loaded data for: " . $profiles[0]->companyName . "\n"; echo "Dividend count: " . count($dividends) . "\n"; echo "Metrics count: " . count($metrics) . "\n";
Available Endpoints
Company & Stock Data
stockList()- List all available stockscompanyProfile(string $symbols)- Company profile informationcompanyProfileBulk()- Bulk company profiles (streaming)peersBulk()- Bulk stock peers (companies grouped by industry/sector similarity)sharesFloat(string $symbol)- Shares float information (free float, float shares, outstanding shares)keyExecutives(string $symbol)- Executives of a company with their title, compensation, gender and year of birthavailableExchanges()- Available stock exchangesallExchangeMarketHours()- Market hours for all exchangesholidaysByExchange(string $exchange)- Market holidays and early-close days for an exchange
Financial Statements
balanceSheetStatement(string $symbol)- Balance sheet databalanceSheetStatementBulk(string $year, Period $period)- Bulk balance sheetsbalanceSheetStatementTtm(string $symbol, int|null $limit)- Historical series of quarter-end balance sheets served by the TTM endpointbalanceSheetStatementGrowth(string $symbol, int|null $limit, PeriodQuery|null $period)- Balance sheet growth metricsbalanceSheetStatementGrowthBulk(int $year, Period $period)- Bulk balance sheet growth metricsincomeStatement(string $symbol)- Income statement dataincomeStatementBulk(string $year, Period $period)- Bulk income statementsincomeStatementTtm(string $symbol, int|null $limit)- Historical series of trailing twelve months income statementsincomeStatementGrowth(string $symbol, int|null $limit, PeriodQuery|null $period)- Income statement growth metricsincomeStatementGrowthBulk(int $year, Period $period)- Bulk income statement growth metricscashFlowStatement(string $symbol)- Cash flow datacashFlowStatementBulk(string $year, Period $period)- Bulk cash flow statementscashFlowStatementTtm(string $symbol, int|null $limit)- Historical series of trailing twelve months cash flow statementscashFlowStatementGrowth(string $symbol, int|null $limit, PeriodQuery|null $period)- Cash flow growth metricscashFlowStatementGrowthBulk(int $year, Period $period)- Bulk cash flow growth metricsfinancialGrowth(string $symbol, int|null $limit, PeriodQuery|null $period)- Growth of the key figures of all three statements, including the growth per share over 3, 5 and 10 yearsrevenueProductSegmentation(string $symbol, PeriodQuery $period)- Revenue breakdown by product linerevenueGeographicSegmentation(string $symbol, PeriodQuery $period)- Revenue breakdown by geographic regionlatestFinancialStatements(int $page, int $limit)- Latest financial statements
Market Data & Quotes
quote(string $symbol)- Full quote for a single symbol (stocks, ETFs, indexes, forex, crypto)batchQuote(array $symbols)- Full quotes for a list of symbols, split into requests of at most 1000 symbols automaticallymarketCapitalizationBatch(array $symbols)- Latest market capitalization for a list of symbolseodBulkQuotes(DateTimeImmutable $date)- End of day bulk quotesbatchExchangeQuote(string $exchange)- Exchange quotesbatchExchangeQuoteDetailed(string $exchange)- Detailed exchange quotesbatchForexQuotes()- Forex currency quotes
Historical Data
historicalPriceEod(string $symbol, DateTimeImmutable $from, DateTimeImmutable $to)- Historical prices (also works with forex pairs)historicalPriceEodLight(string $symbol, DateTimeImmutable $from, DateTimeImmutable $to)- Historical prices, lightweight (date, price, volume only)historicalPriceEodNonSplitAdjusted(string $symbol, DateTimeImmutable $from, DateTimeImmutable $to)- Historical prices without split adjustmentshistoricalChart(string $symbol, TimeInterval $interval, DateTimeImmutable $from, DateTimeImmutable $to)- Historical chart datahistoricalMarketCapitalization(string $symbol, DateTimeImmutable $from, DateTimeImmutable $to)- Daily market capitalization
Analytics & Metrics
keyMetrics(string $symbol, int $limit, PeriodQuery $period)- Key financial metricskeyMetricsTtm(string $symbol)- TTM key metricskeyMetricsTtmBulk()- Bulk TTM key metricsratios(string $symbol, int $limit, PeriodQuery $period)- Financial ratiosratiosTtm(string $symbol)- TTM ratiosratiosTtmBulk()- Bulk TTM ratiosfinancialScores(string $symbol)- Financial scoresscoresBulk()- Bulk financial scoresratingBulk()- Bulk ratings and scores computed by FMP from the fundamentals (not analyst ratings)analystEstimates(string $symbol, string $period, int $page, int $limit)- Analyst estimatespriceTargetConsensus(string $symbol)- Consensus analyst price target (high, low, consensus, median)discountedCashFlow(string $symbol)- DCF valuation together with the current stock pricediscountedCashFlowBulk()- Bulk DCF valuationspriceTargetSummary(string $symbol)- Number and average of the price targets published in the last month, quarter, year and overallpriceTargetSummaryBulk()- Bulk price target summariespriceTargetNews(string $symbol, int $page, int|null $limit)- Individual analyst price targets with the news they were published inpriceTargetLatestNews(int $page, int|null $limit)- Latest analyst price targets across all symbolsgradesConsensus(string $symbol)- Analyst rating distribution and the resulting consensus ratinggradesConsensusBulk()- Bulk analyst rating distributions and consensus ratingsgrades(string $symbol, int|null $limit)- Individual analyst rating actions (upgrade, downgrade, maintain)gradesHistorical(string $symbol, int|null $limit)- Monthly snapshots of the analyst rating distributiongradesNews(string $symbol, int $page, int|null $limit)- Rating actions with the news they were published ingradesLatestNews(int $page, int|null $limit)- Latest rating actions across all symbolsmarketRiskPremium()- Market risk premium by countrytreasuryRates()- US Treasury rates for various maturities
Calendar Events
earningsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Earnings calendardetailedEarningsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Earnings calendar with report time (bmo/amc), period ending, fiscal period/year and confirmation flagdividendsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Dividends calendarsplitsCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Stock splits calendariposCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Calendar of expected and priced initial public offeringseconomicCalendar(DateTimeImmutable $from, DateTimeImmutable $to, ?LoggerInterface $logger)- Economic data releases calendardividends(string $symbol)- Company dividend historyearnings(string $symbol, int|null $limit)- Upcoming and historical earnings reports for a single symbolearningsSurprisesBulk(int $year)- Bulk reported and estimated earnings per share of a yearsplits(string $symbol)- Company stock split history
Ownership & Insider Activity
insiderTrades(string $symbol, int $page, int|null $limit)- Insider transactions reported on SEC forms 3, 4 and 5insiderTradeStatistics(string $symbol)- Insider transactions aggregated per quarter (counts and volumes of acquisitions and dispositions)insiderTradesLatest(int $page, int|null $limit, DateTimeImmutable|null $from)- Latest insider transactions across all symbolsinstitutionalPositionsSummary(string $symbol, int $year, int $quarter)- Institutional ownership aggregated from the 13F filings of a quarterinstitutionalHolders(string $symbol, int $year, int $quarter, int $page, int|null $limit)- Institutional holders of a quarter with the change of their positioninstitutionalOwnershipLatest(int $page, int|null $limit)- Latest 13F filings of institutional investorssenateTrades(string $symbol, int|null $limit)- Trades disclosed by U.S. senatorssenateTradesLatest(int $page, int|null $limit)- Latest trades disclosed by U.S. senators across all assetshouseTrades(string $symbol, int $page, int|null $limit)- Trades disclosed by members of the U.S. House of RepresentativeshouseTradesLatest(int $page, int|null $limit)- Latest trades disclosed by members of the U.S. House of Representatives across all assets
Earning Call Transcripts
earningCallTranscriptDates(string $symbol)- Quarters with an available transcriptearningCallTranscript(string $symbol, int $year, int $quarter)- Full transcript of a single earning callearningCallTranscriptLatest(int $page, int|null $limit)- Latest earning calls with a transcript across all symbols
ETFs & Funds
etfList()- Symbols and names of the covered ETFsetfInfo(string $symbol)- Profile of an ETF or a mutual fund (issuer, expense ratio, assets under management, NAV, sector breakdown)etfHoldings(string $symbol)- Assets held by an ETF or a mutual fundetfHoldingsBulk()- Assets held by every ETF and mutual fund at once (streaming)etfSectorWeightings(string $symbol)- Share of every sector in a fundetfCountryWeightings(string $symbol)- Share of every country in a fund
Search
searchIsin(string $isin)- Search for stocks by ISIN code
Other Data
cryptocurrencyList()- Available cryptocurrenciesindexList()- Available market indicesindexConstituents(StockIndex $index)- Current constituents of the S&P 500, Nasdaq 100 or Dow Jones Industrial AveragehistoricalIndexConstituents(StockIndex $index)- Companies added to and removed from one of the three indexesfinancialStatementSymbolList()- Symbols with financial statements
Data Types
All API responses are mapped to strongly-typed readonly payload classes with comprehensive type annotations. Each payload class includes a toArray() method that returns all properties as an associative array.
Example payload structure:
// CompanyProfile payload readonly class CompanyProfile { public function __construct( public string $symbol, public ?float $price = null, public ?int $marketCap = null, public ?string $companyName = null, // ... more properties ) {} /** * @return array{symbol: string, price: float|null, marketCap: int|null, companyName: string|null, ...} */ public function toArray(): array { // Returns all properties as associative array } }
Testing
Run the test suite:
composer test
Run static analysis:
composer phpstan
The library includes comprehensive tests with real API response fixtures and uses MockHttpClient for reliable testing without API dependencies.
Architecture
The library follows these key design principles:
- Memory Efficiency: Uses streaming parsers (JsonMachine, League CSV) to handle large responses without loading entire datasets into memory
- Async Processing: Leverages PHP Fibers through FmpPromise for concurrent request handling
- Immutable Data: All payload objects are readonly and immutable
- Strong Typing: Comprehensive type hints throughout the codebase
- Error Resilience: Graceful handling of malformed API responses with optional strict validation
Core Components
- FmpClient - Main entry point with all API methods
- FmpPromise - Async operations using PHP Fibers
- LargeResponseParser - Memory-efficient streaming parser
- FmpPayloadMapper - Maps API responses to typed objects
- FmpValidator - Data validation layer
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
composer test - Run static analysis:
composer phpstan - Submit a pull request
License
This library is licensed under the MIT License. See the LICENSE file for details.
Financial Modeling Prep API
This library provides a PHP interface to the Financial Modeling Prep API. You'll need an API key from FMP to use this library. Visit their website to sign up and get your API key.