Skip to content

Repository files navigation

Modrinth.Net

GitHub Nuget Nuget (with prereleases) Modrinth API

C# Wrapper for the Modrinth API

Main attributes

  • Automatic rate limiting
    • Retry count is configurable
  • No dependencies
  • Fully documented
  • Support for .NET 8.0 and newer

AOT / source-generated JSON

For Native AOT or trimmed deployments, pass a JsonSerializerContext via ModrinthClientConfig.JsonSerializerContext. The context is merged into the serializer's type resolver chain, so you only need to declare types for the endpoints you actually use.

using System.Text.Json.Serialization;
using Modrinth;
using Modrinth.Models;

// Declare a source-generated context for the endpoints you use
[JsonSerializable(typeof(SearchResponse))]
[JsonSerializable(typeof(SearchResult[]))]
internal partial class MyModrinthContext : JsonSerializerContext;

var client = new ModrinthClient(new ModrinthClientConfig
{
    UserAgent = "MyAwesomeProject",
    JsonSerializerContext = MyModrinthContext.Default
});

var results = await client.Project.SearchAsync("sodium");
Console.WriteLine(results.Hits[0].Title);

Usage

using Modrinth;

var options = new ModrinthClientConfig 
{
    // Optional, if you want to access authenticated API endpoints
    ModrinthToken = "Your_Authentication_Token",
    // For Modrinth API, you must specify a user-agent
    // There is a default library user-agent, but it is recommended to specify your own
    UserAgent = "MyAwesomeProject"
};

var client = new ModrinthClient(options);

var project = await client.Project.GetAsync("sodium");

Console.WriteLine(project.Description);

But you don't have to provide options at all, you can just create a client with the default options:

var client = new ModrinthClient();

User-Agent

  • You can also use the UserAgent class to help you create a valid user-agent
  • User-Agent currently cannot be changed after the client has been created
  • More info about the User-Agent can be found here
using Modrinth;

// Note: All properties are optional, and will be ignored if they are null or empty
var userAgent = new UserAgent
{
    ProjectName = "ProjectName",
    ProjectVersion = "1.0.0",
    GitHubUsername = "Username",
    Contact = "contact@contact.com"
};

var options = new ModrinthClientOptions
{
    UserAgent = userAgent.ToString()
};

var client = new ModrinthClient(options);

Search

  • You can search for projects using the SearchAsync method, in the Project endpoint
using Modrinth;

var client = new ModrinthClient(userAgent: "My_Awesome_Project");

var search = await client.Project.SearchAsync("sodium");

foreach (var project in search.Hits)
{
    Console.WriteLine(project.Title);
}

Search with facets/filtering

  • You can filter the search results by using facets, which are a way to filter the results by certain criteria
  • You can read more about facets here
  • You can create a FacetCollection and add facets to it, and then pass it to the SearchAsync method

Example:

// For search with facets, you first need to create a FacetCollection
var facets = new FacetCollection();

// Then you can add facets to it
// You add a facet by calling the Add method on the FacetCollection
// In one call, you can add multiple facets, they will be combined in an OR statement
// If you call Add again, the new facets will be combined in an AND statement with the previous ones

// Example:
facets.Add(Facet.Category("adventure"), Facet.Category("magic"));
facets.Add(Facet.Version("1.19.4"));

// This will create a query that looks like this:
// (category:adventure OR category:magic) AND version:1.19.4
// Basically it will search for projects that have the category "adventure" or "magic" on Minecraft version 1.19.4

// Then you can pass the FacetCollection to the SearchAsync method
var search = await _client.Project.SearchAsync("", facets: facets);

As FacetCollection implements ICollection<T>, you can use collection initializers to add facets to it, like this:

var facets = new FacetCollection
{
    { Facet.Category("adventure"), Facet.Category("magic") },
    { Facet.Version("1.19.4") }
};

Which will create the same query as the previous example.

Unsuccesful API calls

  • If the API call was unsuccessful, the client will throw an ModrinthApiException exception
  • This will be thrown if the API call return non-200 status code
using Modrinth;
using Modrinth.Exceptions;
using System.Net;

var client = new ModrinthClient(userAgent: "My_Awesome_Project");

try 
{
    var project = await _client.Project.GetAsync("non-existent-project");
    
    Console.WriteLine(project.Title);
}
// You can catch the exception and only handle the 404 status code
catch (ModrinthApiException e) when (e.Response.StatusCode == HttpStatusCode.NotFound) 
{
    Console.WriteLine("Project not found");
}
// Or you can catch the exception and handle all non-200 status codes
catch (ModrinthApiException e)
{
    Console.WriteLine($"API call failed with status code {e.Response.StatusCode}");
}

List of endpoints and their support in this library

Icon Meaning Comment
✅ Implemented
❌ Not implemented
⚠️ Untested The endpoint has been implemented, but no tests have been written for it yet

Project endpoints

Name Method Implemented
Search projects GET ✅
Get a project GET ✅
Modify a project PATCH ❌
Delete a project DELETE ⚠️
Get multiple projects GET ✅
Bulk-edit multiple projects PATCH ❌
Get a list of random projects GET ✅
Create a project POST ❌
Change project's icon PATCH ✅
Delete project's icon DELETE ✅
Check project slug/ID validity GET ✅
Add a gallery image POST ✅
Modify a gallery image PATCH ✅
Delete a gallery image DELETE ✅
Get all of a project's dependencies GET ✅
Follow a project POST ✅
Unfollow a project DELETE ✅
Schedule a project POST ❌

Version endpoints

Name Method Implemented
List project's versions GET ✅
Get a version GET ✅
Modify a version PATCH ❌
Delete a version DELETE ⚠️
Get a version given a version number or ID GET ❌
Create a version POST ❌
Schedule a version POST ⚠️
Get multiple versions GET ✅
Add files to version POST ❌

Version file endpoints

Name Method Implemented
Get version from hash GET ✅️
Delete a file from its hash DELETE ⚠️
Latest version of a project from a hash, loader(s), and game version(s) POST ✅️
Get versions from hashes POST ✅️
Latest versions of multiple projects from hashes, loader(s), and game version(s) POST ✅️

User endpoints

Name Method Implemented
Get a user GET ✅
Modify a user PATCH ❌
Get user from authorization header GET ✅
Get multiple users GET ✅
Change user's avatar PATCH ✅
Get user's projects GET ✅
Get user's followed projects GET ✅
Get user's payout history GET ⚠
Withdraw payout balance to PayPal or Venmo POST ❌

Threads endpoints

🔐 All of the endpoints in this section require authentication.

Name Method Implemented
Report a project, user, or version POST ❌
Get your open reports GET ❌
Get report from ID GET ❌
Modify a report PATCH ❌
Get multiple reports GET ❌
Get a thread GET ❌
Send a text message to a thread POST ❌
Get multiple threads GET ❌
Delete a thread DELETE ❌

Notifications endpoints

🔐 All of the endpoints in this section require authentication.

Name Method Implemented
Get user's notifications GET ⚠
Get notification from ID GET ❌
Mark notification as read PATCH ❌
Delete a notification DELETE ❌
Get multiple notifications GET ❌
Mark multiple notifications as read PATCH ❌
Delete multiple notifications DELETE ❌

Team endpoints

Name Method Implemented
Get a project's team members GET ✅
Get a team's members GET ✅
Add a user to a team POST ⚠️
Get the members of multiple teams GET ✅
Join a team POST ⚠️
Modify a team member's information PATCH ⚠️
Remove a member from a team DELETE ⚠️
Transfer team's ownership to another user PATCH ⚠️

Tag endpoints

Name Method Implemented Comment
Get a list of categories GET ✅
Get a list of loaders GET ✅
Get a list of game versions GET ✅
Get the text and title of a license GET ✅
Get a list of donation platforms GET ✅
Get a list of report types GET ✅
Get a list of project types GET ✅
Get a list of side types GET ✅

Miscellaneous endpoints

Name Method Implemented
Forge Updates JSON file GET ❌
Various statistics about this Modrinth instance GET ✅

Development

Testing

Library uses NUnit for testing.

To run tests, you can use the dotnet test command. To run authenticated tests, you need to set the ModrinthApiKey secret for the test project.

You can do this by running the following command in the terminal, in the root of the project:

dotnet user-secrets init --project .\test\Modrinth.Net.Test
dotnet user-secrets set ModrinthApiKey "Your_Authentication_Token" --project .\test\Modrinth.Net.Test

If you wish to remove the secret you can run:

dotnet user-secrets remove ModrinthApiKey --project .\test\Modrinth.Net.Test

Optionally, you can also set the MODRINTH_API_KEY environment variable, but secrets are preferred.

Disclaimer

This is not an official Modrinth project. This is a third-party project that is not affiliated with Modrinth in any way.

Releases

Used by

Contributors

Languages