InoreaderCs 0.0.1-beta.5

This is a prerelease version of InoreaderCs.
There is a newer version of this package available.
See the version list below for details.
dotnet add package InoreaderCs --version 0.0.1-beta.5
                    
NuGet\Install-Package InoreaderCs -Version 0.0.1-beta.5
                    
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="InoreaderCs" Version="0.0.1-beta.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InoreaderCs" Version="0.0.1-beta.5" />
                    
Directory.Packages.props
<PackageReference Include="InoreaderCs" />
                    
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 InoreaderCs --version 0.0.1-beta.5
                    
#r "nuget: InoreaderCs, 0.0.1-beta.5"
                    
#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 InoreaderCs@0.0.1-beta.5
                    
#: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=InoreaderCs&version=0.0.1-beta.5&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=InoreaderCs&version=0.0.1-beta.5&prerelease
                    
Install as a Cake Tool

📰 InoreaderCs

NuGet package GitHub Workflow Status Testspace Coveralls

.NET client for the Inoreader HTTP API

Prerequisites

Installation

dotnet add package InoreaderCs

Features

Like IsaacSchemm/InoreaderFs, but not fucked up:

  • Correctly send the ot query parameter to stream/items/ids in microsecond format, not seconds, so it isn't ignored.
  • Has a built-in OAuth2 client with smart refresh logic as well as a password-based auth client, both of which make auth requests automatically and support pluggable persistence strategies.
  • Observe rate-limiting statistics.
  • Uses modern, interchangeable, customizable HttpClient instead of ancient, disgusting HttpWebRequest.
  • Allows you to set custom HTTP request headers, such as User-Agent.
  • Easily gets article's read and starred state, short ID, description, and original feed name and URL.
  • Instances are configurable because they are not static classes, so you don't need to supply authentication to literally every request, you can just set it up once, for example in an IoC context, and not have to pass it around your entire codebase.
  • Interfaces allow mocking and interchangeability, instead of everything being sealed static classes.
  • Hierarchical interface structure makes it easier to find the API method you want and understand what it applies to.
  • Facade pattern hides the complexity of the Inoreader API's very overloaded methods with lots of conditionally valid parameters.
  • Avoids the insane concept of stream IDs and all their complexity of parsing, translating, handling, and using them, because developers today shouldn't have to deal with weird Google decisions from 2001 that Inoreader bent over backwards to be compatible with for no real benefit because there is no Google Reader client that anyone pointed at Inoreader as a drop-in replacement backend.
  • Full documentation of methods and entities.
  • Exceptions have information about what went wrong.
  • Updated in the last 6 years by someone who uses Inoreader and this library heavily every day.
  • Automated tests.
  • Includes correct, strongly-typed arguments in API methods like subscription/edit, which are incorrect in the official documentation and unehlpful, weakly-typed strings in InoreaderFs.

Configuration

Authentication

Persisting auth tokens

Implement the IAuthTokenPersister interface so that auth tokens can be saved and loaded.

public class MyAuthTokenPersister: IAuthTokenPersister {

    public async Task<PersistedAuthTokens?> LoadAuthTokens() {
        // load auth tokens
    }

    public async Task SaveAuthTokens(PersistedAuthTokens authToken) {
        // save auth tokens
    }

}
Authentication client

If your app authenticates to Inoreader using OAuth2, subclass the OAuth2Client abstract class so that users can see and grant consent for OAuth2 app access to their account.

public class MyOauth2Client(Oauth2Parameters oauthParameters, IAuthTokenPersister authTokenPersister, IHttpClient? httpClient, ILoggerFactory? loggerFactory)
    : Oauth2Client(oauthParameters, authTokenPersister, httpClient, loggerFactory) {

    protected override Uri AuthorizationReceiverCallbackUrl => /* URL of your web server's OAuth2 callback resource */;

    protected override async Task<ConsentResult> ShowConsentPageToUser(Uri consentUri, Uri codeReceiverUri, Task authorizationSuccess) {
        // show consent page to user
    }

}

Otherwise, construct a PasswordAuthClient instance.

API Client

Create a new instance of InoreaderClient. It uses one instance of an IAuthClient, so if you have multiple auth strategies, construct additional InoreaderClient instances.

Oauth2Parameters oauthParameters = new(appId: 123, appKey: "abc");

using IInoreaderClient inoreader = new InoreaderClient(new InoreaderOptions {
    AuthClient = new MyOauth2Client(oauthParameters, new MyAuthTokenPersister())
});

Usage

List articles

DetailedArticles articleList = await inoreader.Newsfeed.ListArticlesDetailed();
foreach (Article article in articleList.Articles) {
    Console.WriteLine(article.Title);
}

Useful options:

  • To only fetch articles from a specific folder, tag, or subscription/feed, replace Newsfeed (which refers to all articles in the entire account) with Folders, Tags, or Subscriptions, respectively.
  • To change the page size, pass the maxArticles parameter.
  • To only return articles crawled after a certain time, pass the minTime parameter.
  • To remove or require articles to have a specific state like read or starred, pass the subtract or intersect parameters, respectively.
  • To fetch subsequent pages from a multi-page response, pass the previous page or its PaginationToken as the pagination parameter.

    Even when the pagination parameter is sent properly, the Inoreader API servers sometimes ignore it and incorrectly return the first page again instead of the desired page. This makes it look like many of the articles are duplicates. After fetching multiple pages of articles, always filter by the unique Article.ShortId to remove the erroneous duplicates, for example, using IEnumerable<T>.Distinct.

Check if there are new articles

DateTimeOffset mostRecentArticleTime = default;
while (true) {
    BriefArticles mostRecentArticle = await inoreader.Newsfeed.ListArticlesBrief(maxArticles: 1, minTime: mostRecentArticleTime);

    if (mostRecentArticle.Articles[0].CrawlTime is var articleTime && articleTime != mostRecentArticleTime) {
        mostRecentArticleTime = articleTime;
        Console.WriteLine("New article received");
    }
    await Task.Delay(TimeSpan.FromMinutes(10));
}

Mark an article read or unread

await inoreader.Articles.MarkArticles(ArticleState.Read, [article]);
await inoreader.Articles.UnmarkArticles(ArticleState.Read, [article]);

Star or unstar an article

await inoreader.Articles.MarkArticles(ArticleState.Starred, [article]);
await inoreader.Articles.UnmarkArticles(ArticleState.Starred, [article]);

Tag or untag an article

await inoreader.Articles.TagArticles("my tag", [article]);
await inoreader.Articles.UntagArticles("my tag", [article]);

Subscribe to a feed

Uri feedUrl = new("https://arstechnica.com/science/feed/");
SubscriptionCreationResult subscription = await inoreader.Subscriptions.Subscribe(feedUrl, CancellationToken.None);

// alternative that immediately sets name or folder
await inoreader.Subscriptions.Subscribe(feed, title: "Science", folder: "Technology");

Show the number of unread articles

NewsfeedUnreadCounts unreadResponse = await inoreader.Newsfeed.GetUnreadCounts();
int unreadCount = unreadResponse.AllArticles.UnreadCount;
string unreadLabel = $"{unreadCount:N0}{(unreadCount == unreadResponse.MaxDisplayableCount ? "+" : "")}";

List subscriptions, folders, or tags

IEnumerable<Subscription> subscriptions = await inoreader.Subscriptions.List();
IEnumerable<FolderState> folders = await inoreader.Folders.List();
IEnumerable<TagState> tags = await inoreader.Tags.List();

Rename subscriptions, folders, or tags

Uri subscription = new("https://arstechnica.com/science/feed/");
await inoreader.Subscriptions.Rename(subscription, newName: "Science!");
await inoreader.Folders.Rename("Technology", newName: "New Technology");
await inoreader.Tags.Rename("My tag", newName: "My new tag");

Organize subscriptions into folders

Uri subscription = new("https://arstechnica.com/science/feed/");
await inoreader.Subscriptions.AddToFolder(subscription, "Technology");
await inoreader.Subscriptions.RemoveFromFolder(subscription, "Technology");

Delete subscriptions, folders, or tags

await inoreader.Subscriptions.Unsubscribe(new Uri("https://arstechnica.com/science/feed/"));
await inoreader.Folders.Delete("Technology");
await inoreader.Tags.Delete("My tag");

Mark all articles as read

Article latestArticle;
await inoreader.Newsfeed.MarkAllArticlesAsRead(latestArticle.CrawlTime);
await inoreader.Folders.MarkAllArticlesAsRead("Technology", latestArticle.CrawlTime);
await inoreader.Tags.MarkAllArticlesAsRead("My tag", latestArticle.CrawlTime);
await inoreader.Subscriptions.MarkAllArticlesAsRead(new Uri("https://arstechnica.com/science/feed/"), latestArticle.CrawlTime);

Get self user

User self = await inoreader.Users.GetSelf();
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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.0 38 3/5/2026
0.0.1-beta.7 45 3/5/2026
0.0.1-beta.6 137 11/23/2025
0.0.1-beta.5 223 11/10/2025
0.0.1-beta.4 131 11/2/2025
0.0.1-beta.3 137 10/31/2025
0.0.1-beta.2 163 10/28/2025
0.0.1-beta.1 164 10/28/2025