A modern and well documented API wrapper for the osu! API v2.
This wrapper currently only supports public scope endpoints.
Installation โข Getting Started โข Contribute โข API Coverage
โ๏ธ Extensive API documentation โ Detailed documentations, beyond the official API docs
โ๏ธ Seamless Integration โ Designed with .NET Generic Host in mind
โ๏ธ Easy Error Handling โ Result pattern for API responses with error-handling assistance
โ๏ธ Flexible Authentication Flow โ Easy-to-use authorization infrastructure
โ๏ธ Actively Maintained โ Contributions welcome!
osu.NET is available via NuGet:
# via the dotnet CLI
dotnet add package osu.NET
# via the Package Manager CLI
Install-Package osu.NET
This library is primary designed to be integrated with the .NET Generic Host, but can also be used stand-alone.
Every API model and every endpoint is well documented, including:
- Documentation of API properties and parameters, beyond what the osu! API documentation provides
- References to the osu! API documentation and osu-web source-code
- Information about the API errors to expect on each endpoint
For the authorization flow, there are multiple methods to choose from:
Authorization Provider | Authorization Flow | Usageโ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ โ |
---|---|---|
OsuClientAccessTokenProvider |
Authorization using client ID & secret | new(id, secret) .FromEnvironmentVariables(id, secret) |
OsuStaticAccessTokenProvider |
Authorization using a static access token | new(accessToken) |
OsuDelegateAccessTokenProvider |
Authorization using an access token provided via a delegate (eg. for fetching from a database) | new(cancellationToken => ...) |
Tip
You can also write your own access token provider by inheriting IOsuAccessTokenProvider
.
The API wrapper provides extension methods for registering the OsuApiClient
as a scoped service. The access tokens are provided via an IOsuAccessTokenProvider
instance provided on service registration, optionally the API client can be configured too.
Example:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddHostedService<TestService>();
services.AddOsuApiClient(
OsuClientAccessTokenProvider.FromEnvironmentVariables("OSU_ID", "OSU_SECRET"),
(options, services) =>
{
options.EnableLogging = true;
});
})
.Build();
The OsuApiClient
can then be consumed via dependency injection:
public class TestService(OsuApiClient client) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
ApiResult<UserExtended> result = await client.GetUserAsync("mrekk", cancellationToken);
}
}
To use the OsuApiClient
without the .NET Generic Host, there are some considerations to be made.
In order to get started, you create an instance of the IOsuAccessTokenProvider
providing the desired authorization flow, and using that you create an instance of the OsuApiClient
:
OsuClientAccessTokenProvider provider = OsuClientAccessTokenProvider
.FromEnvironmentVariables("OSU_ID", "OSU_SECRET");
OsuApiClientOptions options = new()
{
EnableLogging = false // false by default, do *not* set it to true for stand-alone usage
};
OsuApiClient client = new(provider, options, null! /* ILogger, set to null for stand-alone usage*/);
Important
Since the logging is based on the Microsoft.Extensions.Logging.ILogger<T>
, a part of the .NET Generic Host, logging needs to be disabled and the logger set to null.
The API endpoint methods return an ApiResult<T>
, wrapping the data returned from the osu! API (.Value
) and alternatively providing the API error if one was returned (.Error
).
The error message provided by the API is interpreted into an ApiErrorType
for common errors, allowing to handle different errors in individual ways. Furthermore, the ApiResult<T>
type provides a Match
method, allowing to match the result for the returned value if the request succeeded, or for the ApiError
if the requested failed.
Note
The xmldocs for the API endpoint methods always provide the ApiErrorType
the endpoints are expected to return, as well as when they do it, so you always know which errors to expect.
Here is an example on how to handle the response of a GetUserBeatmapScoreAsync
API request:
ApiResult<UserBeatmapScore> result = await client.GetUserBeatmapScoreAsync(4697929, 7562902);
// You can also return a value inside the result matching lambdas, eg.:
// double? pp = result.Match<double>(value => value?.Score.PP, error => null);
result.Match(
value => logger.LogInformation("PP: {PP}", value?.Score.PP,
error => error.Type switch
{
ApiErrorType.BeatmapNotFound => logger.LogError("Beatmap not found."),
ApiErrorType.UserOrScoreNotFound => logger.LogError("User not found or has no score."),
_ => logger.LogError("{Message}", error.Message)
})
);
Tip
osu.NET provides a roslyn code analyzer for assisting with result-matching. If you match a result with the exact syntax above, matching the error directly with a error.Type switch {...}
, the code analyzer will warn you if you have an unhandled ApiErrorType
possibly returned by the API endpoint called.
This feature is experimental and the warning can be disabled via #pragma warning disable OSU001
, or as suggested by your IDE.
This library is continuously maintained, and contributions are always welcome. Whether it's improving documentation, adding new features, or updating existing code, every contribution helps keep the project up-to-date and easy-to-use.
๐ Improve Documentation
Some parts of the documentation are still missing. If you encounter some, and you can provide information about it, any contributions filling the gaps are much appreciated!
๐ง Add or Update API Endpoints
Not all endpoints the API provides are implemented. If you require a missing endpoint, feel free to propose it using a GitHub issue or implement it via a pull request. Similarily, feel free to contribute if you notice an outdated endpoint, as the osu! API evolves over time.
๐ Update API Models
If any API models are outdated due to changes in the osu! API, feel free to report it via a GitHub issue or update them via a pull request.
๐ฃ๏ธ Report Issues
If something isn't working as expected, open an issue with a detailed description so the problem can be addressed promptly.
Below is a list of all planned and implemented osu! API endpoints. If you'd like to suggest a missing endpoint or add one yourself, feel free to create an issue or pull request.
โ = Implemented | โ = Not Implemented | ๐ = Undocumented in official docs
- โ
/beatmaps/packs
- โ
/beatmaps/packs/{tag}
- โ
/beatmaps?id[]
- โ
/beatmaps/lookup?checksum
- โ
/beatmaps/lookup?filename
- โ
/beatmaps/{beatmap}
- โ
/beatmaps/{beatmap}/attributes
- โ
/beatmaps/{beatmap}/scores
- โ
/beatmaps/{beatmap}/scores/users/{user}
- โ
/beatmaps/{beatmap}/scores/users/{user}/all
- โ
/beatmapsets/discussions/posts
- โ
/beatmapsets/discussions/votes
- โ
/beatmapsets/discussions
- โ
/beatmapsets/search
- โ
/beatmapsets/lookup
- โ
/beatmapsets/{beatmapset}
- โ
/beatmapsets/events
๐
- โ
/changelog
- โ
/changelog/{buildOrStream}
- โ
/changelog/{stream}/{build}
- โ
/comments
- โ
/comments/{comment}
- โ
/events
- โ
/forums/topics
- โ
/forums/topics/{topic}
- โ
/forums
- โ
/forums/{forum}
- โ
/search
- โ
/matches
- โ
/matches/{match}
- โ
/rooms/{room}/playlist/{playlist}/scores
- โ
/rooms/{room}
๐
- โ
/news
- โ
/news/{news}
- โ
/news/{news}?id
- โ
/rankings/kudosu
- โ
/rankings/{mode}/{type}
- โ
/spotlights
- โ
/scores
- โ
/scores/{ruleset}/{score}
๐ - โ
/scores/{score}
๐ - โ
/scores/{score}/download
๐
- โ
/users/{user}/kudosu
- โ
/users/{user}/scores/{type}
- โ
/users/{user}/beatmapsets/{type}
- โ
/users/{user}/recent_activity
- โ
/users/{user}/{mode?}
- โ
/users?id[]
- โ
/users/lookup
๐
- โ
/wiki/{locale}/{path}
- โ
/seasonal-backgrounds
๐ - โ
/tags
๐