Lotus.Namsor.NET 0.1.1

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

Namsor.NET

A .NET 10 client for the NamSor v2 API: gender, origin, ethnicity, country of residence, US race ethnicity, and full name splitting.

Install

dotnet add package Lotus.Namsor.NET

Register once, inject once

services.AddNamsor(o =>
{
    o.ApiKey = apiKey;
    o.MaxCreditsPerCall = 500;
});

INamsorClient is the only thing registered and the only thing you inject. It is registered transient so IHttpClientFactory can rotate handlers; injecting it into a singleton captures one HttpClient for the life of the app and defeats that.

Every service hangs off the client:

public sealed class NameEnrichmentService(INamsorClient namsor, ILogger<NameEnrichmentService> logger)
{
    public async Task EnrichAsync(string fullName, CancellationToken ct)
    {
        var split = await namsor.NameParser.ParseAsync(fullName, ct);
        var first = split!.FirstLastName!.FirstName!;
        var last = split.FirstLastName.LastName!;

        var ethnicity = await namsor.Diaspora.ClassifyAsync(first, last, "US", ct);
        var gender = await namsor.Gender.ClassifyAsync(first, last, ct);

        var usage = await namsor.Admin.GetUsageAsync(ct);
        logger.LogInformation("{Remaining} credits left", usage?.RemainingCredits);
    }
}
Property Service Credits per name
namsor.Gender male / female inference 1
namsor.Origin where the name comes from 10
namsor.Diaspora ethnicity 20
namsor.Country where the bearer probably lives now 10
namsor.UsRace US race ethnicity 10
namsor.NameParser split a full name 1
namsor.Admin quota, status, service prices free

Batches are correlated by id, not by position

Nothing in the NamSor docs promises the response array comes back in request order, and every response echoes an id. Matching by array index would attach one person's ethnicity to another and never throw, so the client stamps an id on anything you leave blank and rebuilds results by dictionary lookup.

var results = await namsor.Diaspora.ClassifyBatchAsync(names, ct);

foreach (var r in results)
{
    if (!r.Matched)
    {
        // NamSor returned nothing for this name; r.Value is null rather than a neighbour's answer
        continue;
    }

    Save(r.Input.LastName, r.Value!.Ethnicity);
}

Batches over BatchSize (default 100) are chunked automatically, and results still come back in your order.

Geo variants are named, not overloaded (ClassifyGeoBatchAsync, ParseGeoBatchAsync). A collection expression has no type of its own, so overloading on element type would make ClassifyBatchAsync([]) ambiguous and impossible to compile.

Credits

The free plan is 2,500 credits a month, which is 2,500 genderized names but only 125 ethnicities. Two guards:

Splitting a full name and then classifying its ethnicity costs 21 per name, not 20, so the free plan covers 119 such names rather than 125.

var estimate = namsor.Estimate(names.Count, NamsorService.Diaspora);
if (estimate.Credits > budgetLeft) return;

and MaxCreditsPerCall, which throws NamsorBudgetExceededException before the request is sent, so a refused call costs nothing.

Errors

All derive from NamsorException.

Situation Exception
401 NamsorAuthenticationException
403, quota or disabled key NamsorQuotaExceededException
404, 5xx, unparseable body NamsorApiException
refused locally on budget NamsorBudgetExceededException

NamSor returns 403 for both an exhausted quota and a disabled key. Admin routes are free, so Admin.GetUsageAsync() tells you which.

Exceptions carry the endpoint and the response body, never the request headers, so the API key cannot reach a log through an error path.

Live smoke test

$env:NAMSOR_API_KEY = "..."
dotnet run --project samples/Namsor.Smoke             # free admin routes only
dotnet run --project samples/Namsor.Smoke -- --billed  # also spends 1 credit

It prints your quota, every service's real price, and any drift against the built-in cost table.

Scope

Covered: gender (4 variants), origin, diaspora, country of residence, US race ethnicity (including ZIP), name splitting, and all 5 admin routes.

Other api functionalities are not needed, but I'm open to implementing them.

Not covered: Indian names (caste, religion, subclassification), name type recognition, phone number format, and names corridor. X-OPTION-EXPLANABILITY is also left out: it costs 50 credits per name on top of the classification, which is the entire monthly free quota on 50 names, and NamSor has to enable it per-account.

docs/api/ holds the captured API documentation, since NamSor publishes no fetchable OpenAPI spec.

AI

I used AI to build this API Wrapper.

Product Compatible and additional computed target framework versions.
.NET 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. 
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
0.1.1 122 8/16/2026