A reusable .NET library for connecting to and retrieving stock data from the Polygon.io REST API
$ dotnet add package TreyThomasCodes.Polygon.RestClientA reusable .NET 8+ library for connecting to and retrieving data from the Polygon.io API.
dotnet add package TreyThomasCodes.Polygon.RestClient
The library provides extension methods for IServiceCollection to register the Polygon client. There are three ways to configure it:
Add the Polygon configuration to your appsettings.json:
{
"Polygon": {
"ApiKey": "your-api-key-here",
"BaseUrl": "https://api.polygon.io",
"TimeoutSeconds": 30,
"MaxRetries": 3
}
}
Register the client in your Program.cs or Startup.cs:
using TreyThomasCodes.Polygon.RestClient;
var builder = WebApplication.CreateBuilder(args);
// Register Polygon client using configuration
builder.Services.AddPolygonClient(builder.Configuration);
using TreyThomasCodes.Polygon.RestClient;
var builder = WebApplication.CreateBuilder(args);
// Register Polygon client with API key
builder.Services.AddPolygonClient("your-api-key-here");
using TreyThomasCodes.Polygon.RestClient;
var builder = WebApplication.CreateBuilder(args);
// Register Polygon client with configuration action
builder.Services.AddPolygonClient(options =>
{
options.ApiKey = "your-api-key-here";
options.BaseUrl = "https://api.polygon.io";
options.TimeoutSeconds = 30;
options.MaxRetries = 3;
});
Once registered, inject IPolygonClient into your services or controllers:
using TreyThomasCodes.Polygon.RestClient.Services;
public class StockDataService
{
private readonly IPolygonClient _polygonClient;
public StockDataService(IPolygonClient polygonClient)
{
_polygonClient = polygonClient;
}
public async Task<decimal?> GetLastTradePrice(string ticker)
{
var request = new GetLastTradeRequest { Ticker = ticker };
var response = await _polygonClient.Stocks.GetLastTradeAsync(request);
return response?.Results?.Price;
}
public async Task<decimal?> GetLastQuoteBidPrice(string ticker)
{
var request = new GetLastQuoteRequest { Ticker = ticker };
var response = await _polygonClient.Stocks.GetLastQuoteAsync(request);
return response?.Results?.Bid?.Price;
}
public async Task<bool> IsMarketOpen()
{
var request = new GetMarketStatusRequest();
var response = await _polygonClient.ReferenceData.GetMarketStatusAsync(request);
return response?.Market == "open";
}
}
This library provides three different patterns for making API calls. Choose the one that best fits your coding style:
The most explicit pattern using strongly-typed request objects:
using TreyThomasCodes.Polygon.RestClient.Requests.Stocks;
var request = new GetBarsRequest
{
Ticker = "AAPL",
Multiplier = 1,
Timespan = AggregateInterval.Day,
From = "2025-01-01",
To = "2025-01-31",
Adjusted = true
};
var bars = await _polygonClient.Stocks.GetBarsAsync(request);
For simple, single-parameter operations:
// Get snapshot with just the ticker
var snapshot = await _polygonClient.Stocks.GetSnapshotAsync("AAPL");
// Get last trade with just the ticker
var lastTrade = await _polygonClient.Stocks.GetLastTradeAsync("MSFT");
// Get ticker details with just the ticker
var details = await _polygonClient.ReferenceData.GetTickerDetailsAsync("TSLA");
For expressive, chainable queries (requires using TreyThomasCodes.Polygon.RestClient.Fluent;):
using TreyThomasCodes.Polygon.RestClient.Fluent;
// Get stock bars with a fluent, progressive builder
var bars = await _polygonClient.Stocks
.Bars("AAPL")
.From("2025-01-01")
.To("2025-01-31")
.Daily()
.Adjusted()
.Limit(100)
.ExecuteAsync();
// Search tickers with fluent filters
var tickers = await _polygonClient.ReferenceData
.Tickers()
.Search("Apple")
.ActiveOnly()
.OfType("CS")
.Limit(10)
.ExecuteAsync();
// Get options chain with fluent filtering
var chain = await _polygonClient.Options
.ChainSnapshot("SPY")
.CallsOnly()
.ExpiringBetween("2025-12-01", "2025-12-31")
.AtStrike(650m)
.Limit(100)
.ExecuteAsync();
The fluent API provides:
Daily(), Hourly(4), Minutely(15)CallsOnly(), ExpiringBetween(), ActiveOnly()All patterns produce the same results and use the same validation. Choose based on your preference!
The IPolygonClient provides access to the following services:
IStocksService)Accessed via IPolygonClient.Stocks
GetBarsAsync - Get aggregate OHLC bars for a stock over a date rangeGetPreviousCloseAsync - Get the previous day's OHLC dataGetGroupedDailyAsync - Get daily OHLC data for all tickers on a specific dateGetDailyOpenCloseAsync - Get the open and close prices for a specific dayGetTradesAsync - Get tick-level trade data for a stockGetQuotesAsync - Get tick-level quote (bid/ask) data for a stockGetLastTradeAsync - Get the most recent trade for a stockGetLastQuoteAsync - Get the most recent NBBO quote for a stockGetMarketSnapshotAsync - Get snapshot data for all available tickersGetSnapshotAsync - Get snapshot data for a specific tickerIReferenceDataService)Accessed via IPolygonClient.ReferenceData
GetTickersAsync - Get a list of tickers with various filter optionsGetTickerDetailsAsync - Get detailed information for a specific tickerGetTickerTypesAsync - Get list of all supported ticker typesGetMarketStatusAsync - Get current market trading statusGetExchangesAsync - Get list of exchanges and market centersGetConditionCodesAsync - Get trade and quote condition codesIOptionsService)Accessed via IPolygonClient.Options
GetContractDetailsAsync - Get detailed information about a specific options contract by its ticker symbolGetSnapshotAsync - Get a snapshot of current market data for a specific options contract, including Greeks, implied volatility, and underlying asset informationGetChainSnapshotAsync - Get snapshots for all options contracts for a given underlying asset with filtering by strike price, contract type, and expiration dateGetLastTradeAsync - Get the most recent trade for a specific options contractGetQuotesAsync - Get historical bid/ask quote data for a specific options contract with time-based filtering and paginationGetTradesAsync - Get historical trade data for a specific options contract with time-based filtering and paginationGetBarsAsync - Get aggregate OHLC (bar/candle) data for an options contract over a specified time range with configurable intervalsGetPreviousDayBarAsync - Get the previous trading day's OHLC bar data for a specific options contractGetDailyOpenCloseAsync - Get daily open, high, low, close summary for a specific options contract including pre-market and after-hours pricesWorking with options tickers can be complex due to the OCC format requirements. The library provides helper classes to simplify ticker construction:
OptionsTicker - Static factory methods for creating and parsing OCC format options tickers:
using TreyThomasCodes.Polygon.Models.Options;
// Create an options ticker from components
string ticker = OptionsTicker.Create(
underlying: "UBER",
expirationDate: new DateTime(2022, 1, 21),
type: OptionType.Call,
strike: 50m
);
// Returns: "O:UBER220121C00050000"
// Parse an existing ticker into components
var parsed = OptionsTicker.Parse("O:UBER220121C00050000");
Console.WriteLine($"Underlying: {parsed.Underlying}"); // UBER
Console.WriteLine($"Expiration: {parsed.ExpirationDate}"); // 2022-01-21
Console.WriteLine($"Type: {parsed.Type}"); // Call
Console.WriteLine($"Strike: {parsed.Strike}"); // 50
OptionsTickerBuilder - Fluent API for building options tickers:
using TreyThomasCodes.Polygon.Models.Options;
var ticker = new OptionsTickerBuilder()
.WithUnderlying("SPY")
.WithExpiration(2025, 12, 19)
.AsCall()
.WithStrike(650m)
.Build();
// Returns: "O:SPY251219C00650000"
Convenience Methods - Simplified methods for common operations:
using TreyThomasCodes.Polygon.Models.Options;
using TreyThomasCodes.Polygon.Models.Common;
// Method 1: Use components directly (simplest approach)
var contract = await _polygonClient.Options.GetContractByComponentsAsync(
underlying: "UBER",
expirationDate: new DateTime(2022, 1, 21),
type: OptionType.Call,
strike: 50m
);
var snapshot = await _polygonClient.Options.GetSnapshotByComponentsAsync(
underlying: "SPY",
expirationDate: new DateTime(2025, 12, 19),
type: OptionType.Call,
strike: 650m
);
var lastTrade = await _polygonClient.Options.GetLastTradeByComponentsAsync(
underlying: "TSLA",
expirationDate: new DateTime(2026, 3, 20),
type: OptionType.Call,
strike: 700m
);
var bars = await _polygonClient.Options.GetBarsByComponentsAsync(
underlying: "SPY",
expirationDate: new DateTime(2025, 12, 19),
type: OptionType.Call,
strike: 650m,
multiplier: 1,
timespan: AggregateInterval.Day,
from: "2025-11-01",
to: "2025-11-30"
);
var chainSnapshot = await _polygonClient.Options.GetChainSnapshotByComponentsAsync(
underlyingAsset: "SPY",
type: OptionType.Call,
expirationDateGte: new DateTime(2025, 12, 1),
expirationDateLte: new DateTime(2025, 12, 31),
limit: 100
);
// Method 2: Use OptionsTicker objects for reusability
var ticker = OptionsTicker.Parse("O:SPY251219C00650000");
var contractDetails = await _polygonClient.Options.GetContractDetailsAsync(ticker);
var marketSnapshot = await _polygonClient.Options.GetSnapshotAsync(ticker);
var trade = await _polygonClient.Options.GetLastTradeAsync(ticker);
var quotes = await _polygonClient.Options.GetQuotesAsync(ticker, timestamp: "2024-12-01", limit: 100);
var trades = await _polygonClient.Options.GetTradesAsync(ticker, timestamp: "2021-09-03", limit: 100);
var dailyBars = await _polygonClient.Options.GetBarsAsync(ticker, 1, AggregateInterval.Day, "2025-11-01", "2025-11-30");
var dailyOHLC = await _polygonClient.Options.GetDailyOpenCloseAsync(ticker, "2023-01-09");
var previousDay = await _polygonClient.Options.GetPreviousDayBarAsync(ticker);
// Helper methods: Discover available strikes and expiration dates
var strikes = await _polygonClient.Options.GetAvailableStrikesAsync(
underlying: "SPY",
type: OptionType.Call,
expirationDateGte: "2025-12-01",
expirationDateLte: "2025-12-31"
);
var expirations = await _polygonClient.Options.GetExpirationDatesAsync(
underlying: "UBER",
type: OptionType.Put,
strikePrice: 50m // Optional: filter by strike
);
These helpers eliminate the need to manually construct OCC format ticker strings and provide type-safe, validated ticker generation.
| Option | Description | Default |
|---|---|---|
ApiKey | Your Polygon.io API key (required) | - |
BaseUrl | Base URL for Polygon API | https://api.polygon.io |
TimeoutSeconds | HTTP request timeout in seconds | 30 |
MaxRetries | Maximum number of retry attempts | 3 |
For comprehensive examples and detailed usage instructions for every API call, see USAGE.md.
using TreyThomasCodes.Polygon.Models.Common;
using TreyThomasCodes.Polygon.RestClient.Requests.Stocks;
using TreyThomasCodes.Polygon.RestClient.Requests.Options;
using TreyThomasCodes.Polygon.RestClient.Requests.Reference;
// Get historical price data
var barsRequest = new GetBarsRequest
{
Ticker = "AAPL",
Multiplier = 1,
Timespan = AggregateInterval.Day,
From = "2025-09-01",
To = "2025-09-30",
Adjusted = true
};
var bars = await _polygonClient.Stocks.GetBarsAsync(barsRequest);
// Get the latest trade
var lastTradeRequest = new GetLastTradeRequest { Ticker = "AAPL" };
var lastTrade = await _polygonClient.Stocks.GetLastTradeAsync(lastTradeRequest);
Console.WriteLine($"Last trade price: ${lastTrade.Results.Price}");
// Search for tickers
var tickersRequest = new GetTickersRequest
{
Search = "Apple",
Active = true,
Limit = 10
};
var tickers = await _polygonClient.ReferenceData.GetTickersAsync(tickersRequest);
// Check market status
var statusRequest = new GetMarketStatusRequest();
var status = await _polygonClient.ReferenceData.GetMarketStatusAsync(statusRequest);
Console.WriteLine($"Market is {status.Market}");
// Get option contract details
var contractRequest = new GetContractDetailsRequest
{
OptionsTicker = "O:SPY251219C00650000"
};
var optionContract = await _polygonClient.Options.GetContractDetailsAsync(contractRequest);
Console.WriteLine($"Strike: ${optionContract.Results.StrikePrice}, Expiration: {optionContract.Results.ExpirationDate}");
// Get option bars (historical OHLC data)
var optionBarsRequest = new Options.GetBarsRequest
{
OptionsTicker = "O:SPY251219C00650000",
Multiplier = 1,
Timespan = AggregateInterval.Day,
From = "2023-01-09",
To = "2023-02-10"
};
var optionBars = await _polygonClient.Options.GetBarsAsync(optionBarsRequest);
Console.WriteLine($"Found {optionBars.Results?.Count} option bars");
See USAGE.md for detailed examples of all available API calls.
MPL 2.0 License - see LICENSE file for details.