Finlight.Client 1.0.1

dotnet add package Finlight.Client --version 1.0.1
                    
NuGet\Install-Package Finlight.Client -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Finlight.Client" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Finlight.Client" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Finlight.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Finlight.Client --version 1.0.1
                    
#r "nuget: Finlight.Client, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Finlight.Client@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Finlight.Client&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Finlight.Client&version=1.0.1
                    
Install as a Cake Tool

finlight .NET Client

Official .NET client for the finlight.me financial news API. Full API documentation: docs.finlight.me

Features

  • πŸ”Ž Article search β€” full-text and field queries over enriched financial news
  • ⚑ Real-time streaming β€” enhanced and raw WebSocket feeds as IAsyncEnumerable
  • πŸ” Resilient by default β€” retries with backoff, automatic reconnects, proactive connection rotation
  • πŸ” Webhook verification β€” HMAC-SHA256 signature checks with replay protection
  • πŸͺΆ Lightweight β€” one dependency (Microsoft.Extensions.Logging.Abstractions), nullable-annotated, fully documented API

Installation

dotnet add package Finlight.Client

Requires .NET 8 or later.

Quick Start

using Finlight;

using var client = new FinlightClient("your-api-key");

var response = await client.Articles.FetchArticlesAsync(new GetArticlesParams
{
    Query = "(ticker:AAPL OR ticker:NVDA) AND NOT source:www.reuters.com",
    PageSize = 20,
});

foreach (var article in response.Articles)
{
    Console.WriteLine($"{article.PublishDate:u} [{article.Sentiment}] {article.Title}");
}

REST API

Search articles

var response = await client.Articles.FetchArticlesAsync(new GetArticlesParams
{
    Query = "artificial intelligence",
    From = "2024-01-01",
    To = "2024-02-01",
    Language = "en",
    OrderBy = ArticleOrderBy.PublishDate,
    Order = SortOrder.Desc,
    PageSize = 100,
    Page = 1,
    IncludeContent = true,
    IncludeEntities = true,
    Categories = [Category.Markets, Category.Technology],
});

The API reports no total count; advance Page until a short or empty page comes back.

Fetch a single article by URL

var article = await client.Articles.FetchArticleByLinkAsync(new GetArticleByLinkParams
{
    Link = "https://www.example.com/some-article",
    IncludeContent = true,
});

List sources

var sources = await client.Sources.GetSourcesAsync();

WebSocket Streaming

Enhanced stream

Enriched articles (sentiment, entities, content). Duplicates within the last 10 deliveries are suppressed.

await foreach (var article in client.WebSocket.StreamAsync(new GetArticlesWebSocketParams
{
    Query = "ticker:NVDA",
    IncludeContent = true,
}, cancellationToken))
{
    Console.WriteLine($"{article.Source}: {article.Title}");
}

Raw stream

Unenriched articles with lower latency. The query language is limited to source:, title:, and summary: fields.

await foreach (var article in client.RawWebSocket.StreamAsync(new GetRawArticlesWebSocketParams
{
    Query = "title:earnings",
}, cancellationToken))
{
    Console.WriteLine($"{article.Source}: {article.Title}");
}

Streaming semantics

  • Reconnects (exponential backoff from 500ms to 10s, rate-limit waits, proactive rotation before the server's 2-hour connection cap) are handled internally.
  • The stream ends normally when the server preempts this client because another connection took over the slot (see Takeover).
  • FinlightBlockedException is thrown when the server permanently rejects the connection β€” reconnecting will not help.
  • Cancel the token or break out of the loop to stop; breaking closes the connection cleanly.
  • One active stream per client instance; a concurrent second stream throws InvalidOperationException.

Custom WebSocket options

using Finlight.WebSockets;

var ws = new ArticleWebSocketClient(
    new FinlightClientOptions { ApiKey = "your-api-key" },
    new FinlightWebSocketOptions
    {
        Takeover = true, // take over the connection slot from another client
        OnClose = (code, reason) => Console.WriteLine($"closed: {code} {reason}"),
    });
Option Default Description
PingInterval 25s Application-level ping cadence
PongTimeout 60s Force reconnect when no pong arrives
BaseReconnectDelay 500ms First reconnect backoff
MaxReconnectDelay 10s Backoff cap
ConnectionLifetime 115min Proactive rotation, under the 2h server cap
Takeover false Take over an existing connection for the same key
OnClose – Callback invoked with (closeCode, reason)

Webhooks

Verify inbound webhooks with the raw, unmodified request body:

app.MapPost("/webhooks/finlight", async (HttpRequest request) =>
{
    using var reader = new StreamReader(request.Body);
    var rawBody = await reader.ReadToEndAsync();

    try
    {
        var article = FinlightWebhooks.ConstructEvent(
            rawBody,
            request.Headers["X-Webhook-Signature"]!,
            endpointSecret: "your-webhook-secret",
            request.Headers["X-Webhook-Timestamp"]);
        // handle article ...
        return Results.Ok();
    }
    catch (FinlightWebhookVerificationException)
    {
        return Results.Unauthorized();
    }
});

The signature is an HMAC-SHA256 over "{timestamp}.{body}" (or the body alone when no timestamp header is present), compared in constant time, with a 5-minute replay tolerance.

Configuration

Option Default Description
ApiKey – (required) Your finlight API key
BaseUrl https://api.finlight.me REST base URL
WssUrl wss://wss.finlight.me WebSocket base URL
Timeout 5s Per-attempt timeout (REST and WebSocket handshake)
RetryCount 3 Total REST attempts
TimeProvider system Clock override for tests

Dependency injection

The client works with IHttpClientFactory and never disposes a caller-owned HttpClient:

services.AddHttpClient("finlight", http => http.Timeout = Timeout.InfiniteTimeSpan);
services.AddSingleton(sp => new FinlightClient(
    new FinlightClientOptions { ApiKey = configuration["Finlight:ApiKey"]! },
    sp.GetRequiredService<IHttpClientFactory>().CreateClient("finlight"),
    sp.GetService<ILoggerFactory>()));

Logging

Pass an ILoggerFactory to get structured logs (connection lifecycle, retries, protocol events). Without one, the client is silent.

Error Handling

Exception Meaning
FinlightApiException Non-2xx REST response after retries; carries StatusCode, ReasonPhrase, Body
FinlightBlockedException WebSocket permanently rejected (close code 1008)
FinlightWebhookVerificationException Webhook signature/timestamp/payload validation failed
TimeoutException A single REST attempt exceeded Timeout

Retries: statuses 429, 500, 502, 503, and 504 are retried up to RetryCount total attempts with exponential backoff (500ms Β· 2^(attemptβˆ’1)).

Testing

dotnet test                            # unit tests (offline)
FINLIGHT_API_KEY=... dotnet test       # + integration tests against the live API

License

MIT

Support

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 119 8/10/2026
1.0.0 109 8/10/2026