OpenSourceInitiative.LicenseApi 3.0.0

dotnet add package OpenSourceInitiative.LicenseApi --version 3.0.0
                    
NuGet\Install-Package OpenSourceInitiative.LicenseApi -Version 3.0.0
                    
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="OpenSourceInitiative.LicenseApi" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OpenSourceInitiative.LicenseApi" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="OpenSourceInitiative.LicenseApi" />
                    
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 OpenSourceInitiative.LicenseApi --version 3.0.0
                    
#r "nuget: OpenSourceInitiative.LicenseApi, 3.0.0"
                    
#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 OpenSourceInitiative.LicenseApi@3.0.0
                    
#: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=OpenSourceInitiative.LicenseApi&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=OpenSourceInitiative.LicenseApi&version=3.0.0
                    
Install as a Cake Tool

OpenSourceInitiative.LicenseApi

CI License: MIT NuGet Version

A lightweight, multi-targeted (.NET 10 / netstandard2.0) client library for the Open Source Initiative License API. Fetches the OSI license catalog, supports filtering by SPDX ID, name, keyword, and steward, and extracts human-readable license text from the OSI HTML pages. No caching layer — every call goes to the network; callers that want caching add their own decorator.


Quick start

services.AddOsiLicensesClient();

// With options
services.AddOsiLicensesClient(options =>
{
    options.BaseAddress = new Uri("https://...");   // default: OSI API
});

Resolve IOsiClient from the container:

var client = sp.GetRequiredService<IOsiClient>();

// Stream all licenses
await foreach (var license in client.GetAllLicensesAsyncEnumerable())
    Console.WriteLine(license?.Name);

// Filter
var gplFamily = await client.GetBySpdxIdAsync("GPL*");
var popular   = await client.GetByKeywordAsync(OsiLicenseKeyword.PopularStrongCommunity);

Standalone (no DI)

await using var client = new OsiClient();
var mit = await client.GetByOsiIdAsync("mit");
Console.WriteLine(mit?.LicenseText);

Public API surface

IOsiClient

The primary interface for all license queries. Lives at OpenSourceInitiative.LicenseApi.Interfaces.

Method Description
GetAllLicensesAsyncEnumerable(token) Streams the full catalog as IAsyncEnumerable<OsiLicense?>.
GetByOsiIdAsync(id, token) Fetches a single license by its OSI ID (e.g. "mit").
GetBySpdxIdAsync(id, token) Filters by SPDX ID; supports * wildcards ("GPL*", "*-2.0").
GetByNameAsync(name, token) Filters by human-readable name.
GetByKeywordAsync(keyword, token) Filters by OsiLicenseKeyword enum value.
GetByStewardAsync(steward, token) Filters by steward organization slug.

Implements IDisposable and IAsyncDisposable.

Input handling: id/name/steward/keyword arguments are always treated as opaque values and escaped before being combined with the configured BaseAddress — a caller passing a full URL, a //host reference, or .. segments through one of these methods cannot redirect the request to a different host. Don't rely on this as input validation, though: garbage in still means "license not found" or a JsonException, not a meaningful error.


OsiClient

public sealed class — the concrete HTTP implementation of IOsiClient. Registered as a typed IHttpClientFactory client named "OsiClient" when using DI.

Constructor: OsiClient(ILogger<OsiClient>? logger, OsiClientOptions? options, HttpClient? httpClient) — all parameters optional. When httpClient is null, the client owns and disposes the inner HttpClient; when provided externally it is not disposed.

License text is fetched automatically per license via a two-step strategy:

  1. OSI HTML page — extracts the node with CSS class license-content.
  2. Steward HTML URL — last resort, only used if the steward URL doesn't already point at a .txt file.

If both steps fail (network error, unreachable page, markup without a license-content node), LicenseText is left as an empty string rather than throwing — a scraping failure on a single license does not fail the whole call.


OsiClientOptions

public sealed class — configures the DI registration. Lives at OpenSourceInitiative.LicenseApi.Options.

Property Type Default Description
BaseAddress Uri https://opensource.org/api/ OSI API base URL.
PrimaryHandlerFactory Func<HttpMessageHandler>? null Injects a custom primary handler (useful for testing).
UserAgent IList<ProductInfoHeaderValue> Assembly name + version Added to every request.
HttpClientHandler HttpClientHandler AllowAutoRedirect = true Used when no external HttpClient is supplied.

OsiLicense

public sealed record — represents one OSI license entry. Lives at OpenSourceInitiative.LicenseApi.Models.

Property Type Notes
Id string OSI-internal identifier (e.g. "mit").
Name string Human-readable name.
SpdxId string? SPDX identifier (e.g. "MIT").
Version string? Optional version string.
SubmissionDate DateTime? Parsed from yyyyMMdd via CustomFormatDateTimeConverter.
ApprovalDate DateTime? Parsed from yyyyMMdd.
Approved bool OSI approval status.
Keywords IReadOnlyCollection<OsiLicenseKeyword> Deserialized via OsiLicenseKeywordsConverter; unknown tokens are ignored.
Stewards IReadOnlyCollection<string> Steward organization slugs.
Links OsiLicenseLinks HAL-style _links object.
LicenseText string? Extracted plain text — not part of the API payload, populated by the client after fetching. Empty string if scraping failed. Mutable, so you can set it yourself when constructing an OsiLicense by hand (e.g. in tests).

OsiLicenseExtensions adds license.GetLicenseText(httpClient, token) and license.GetAndSetLicenseText(httpClient, token) for re-fetching or backfilling the text on an existing instance.


OsiLicenseKeyword

public enum — OSI classification keywords. Lives at OpenSourceInitiative.LicenseApi.Enums.

Values: PopularStrongCommunity, International, SpecialPurpose, NonReusable, Superseded, VoluntarilyRetired, RedundantWithMorePopular, OtherMiscellaneous, Uncategorized.

Serializes to/from the OSI API string tokens (e.g. popular-strong-community) via OsiLicenseKeywordsConverter.


ServiceCollectionExtensions

public static class — the single registration entry point. Lives at OpenSourceInitiative.LicenseApi.Extensions.

AddOsiLicensesClient(this IServiceCollection, Action<OsiClientOptions>?) — registers a named IHttpClientFactory client ("OsiClient") and IOsiClientOsiClient as transient.


OsiException / OsiInitializationException

public abstract/sealed class — base and derived exception types. Live at OpenSourceInitiative.LicenseApi.Exceptions.

OsiInitializationException is thrown by the obsolete OsiLicensesClient.InitializeAsync when the catalog fetch fails.


CustomFormatDateTimeConverter

public class JsonConverter<DateTime?> — handles the yyyyMMdd date format used by the OSI API for submission and approval dates. Registered via [JsonConverter] attributes on OsiLicense. Null and empty strings deserialize to null; an unrecognized format throws JsonException.


IOsiLicensesClient / OsiLicensesClient (deprecated)

[Obsolete] — wraps IOsiClient with an eager-loading, snapshot-based API kept for backward compatibility. Use IOsiClient directly for new code. Unlike IOsiClient, its SearchAsync/Search assume every entry returned by the API has a non-null Id/Name; a malformed catalog entry missing either field will throw a NullReferenceException here rather than being filtered out.


Target frameworks

TFM Notes
net10.0 Full feature set. Uses ValueTask.CompletedTask, MediaTypeNames, ReadAsStreamAsync(token), C# 14 extension blocks.
netstandard2.0 Compatible subset. #if !NETSTANDARD2_0 guards cover API surface differences. System.Text.Json pulled as a NuGet dependency.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  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 is compatible.  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 (1)

Showing the top 1 NuGet packages that depend on OpenSourceInitiative.LicenseApi:

Package Downloads
OpenSourceInitiative.LicenseApi.DependencyInjection

Dependency Injection extensions for OpenSourceInitiative.LicenseApi. Provides IServiceCollection extensions to register a typed IOsiLicensesClient with IHttpClientFactory and optional request logging via ILogger. Multi-targets net10.0 and netstandard2.0.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 113 7/1/2026
2.2.0 115 6/23/2026
2.1.0 126 4/2/2026
2.0.0 118 3/4/2026
1.1.1 305 12/17/2025
1.1.0 300 12/17/2025
1.0.0 341 12/16/2025