Search by

aternos / modrinth-api

aternos

PHP Client for the Modrinth API. This client is based on the openapi spec.

Package info

github.com/aternosorg/php-modrinth-api

pkg:composer/aternos/modrinth-api

Statistics

Installs: 6 359

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 1

v4.0.0 2026-10-02 12:44 UTC

README

An API client for the Modrinth API written in PHP.

This client is a combination of code generated by OpenAPI Generator from the Modrinth OpenAPI specification and some wrappers around it to improve the usability.

The generated code can be found in src/Api and src/Model. It is recommended to use the wrappers in src/Client instead.

Requirements

  • PHP 8.4.1 or newer
  • PHP extensions: curl, json, mbstring

Installation

Install the package via composer:

composer require aternos/modrinth-api

Usage

The main entry point for the API is the ModrinthAPIClient class.

<?php
use Aternos\ModrinthApi\Client\ModrinthAPIClient;

$modrinthClient = new ModrinthAPIClient();

// set a user agent identifying your application (recommended)
$modrinthClient->setUserAgent("my-app/1.0.0 (contact@example.com)");

Authentication

Most endpoints are public. Some endpoints (e.g. notifications, reports, threads or the payout history) require a personal access token. If a token is set, it is used for all requests.

$modrinthClient = new ModrinthAPIClient("your_token");
// or
$modrinthClient->setApiToken("your_token");

Error Handling

All methods that send a request throw an Aternos\ModrinthApi\ApiException if the request fails. The exception code is the HTTP status code of the response.

use Aternos\ModrinthApi\ApiException;

try {
    $project = $modrinthClient->getProject("does-not-exist");
} catch (ApiException $e) {
    echo $e->getCode() . PHP_EOL; // e.g. 404
    var_dump($e->getResponseBody());
}

Custom HTTP Client or Configuration

You can pass your own Guzzle client, e.g. to set timeouts or add middlewares, and your own Aternos\ModrinthApi\Configuration, e.g. to use the staging API:

use Aternos\ModrinthApi\Configuration;
use GuzzleHttp\Client;

$configuration = (new Configuration())->setHost("https://staging-api.modrinth.com/v2");
$modrinthClient = new ModrinthAPIClient(null, $configuration, new Client(["timeout" => 10]));

Projects

Searching for Projects

searchProjects() returns a PaginatedProjectSearchList. It contains the results of the current page and methods to navigate between pages. It implements Iterator, ArrayAccess and Countable, so it can be used like an array. getResults() returns the underlying array.

$projects = $modrinthClient->searchProjects();

foreach ($projects as $project) {
    echo $project->getTitle() . PHP_EOL;
}

if ($projects->hasNextPage()) {
    $projects = $projects->getNextPage();
}

// fetch all results from this and all following pages (one request per page)
$allProjects = $projects->getResultsFromFollowingPages();

Search results are SearchProject objects. They only contain the data returned by the search, but you can fetch the full project or the author:

$project = $projects[0]->getFullProject();
$author = $projects[0]->fetchAuthor();

Search Options

You can search for a query, apply filters, change the sort order and set the page size. All options are optional and can be combined.

use Aternos\ModrinthApi\Client\Options\ProjectSearchOptions;
use Aternos\ModrinthApi\Client\Options\SearchIndex;

$options = new ProjectSearchOptions();
$options->setQuery("mclogs")
    ->setIndex(SearchIndex::UPDATED)
    ->setLimit(20);
$projects = $modrinthClient->searchProjects($options);

// or using named arguments
$projects = $modrinthClient->searchProjects(new ProjectSearchOptions(
    query: "mclogs",
    index: SearchIndex::UPDATED,
    limit: 20,
));

Facets

Facets filter the search results, e.g. by project type, loader, category, game version or license. Facets in a FacetORGroup are combined with OR, the OR groups in a FacetANDGroup are combined with AND.

use Aternos\ModrinthApi\Client\Options\Facets\Facet;
use Aternos\ModrinthApi\Client\Options\Facets\FacetANDGroup;
use Aternos\ModrinthApi\Client\Options\Facets\FacetORGroup;
use Aternos\ModrinthApi\Client\Options\Facets\FacetType;

// projects for Minecraft 1.20.1 OR 1.20
$versions = new FacetORGroup([
    new Facet(FacetType::VERSIONS, "1.20.1"),
    new Facet(FacetType::VERSIONS, "1.20"),
]);

// the same using addMultiple(), which is shorter if all facets have the same type
$versions = (new FacetORGroup())->addMultiple(FacetType::VERSIONS, "1.20.1", "1.20");

// a single OR group can be used directly
$options = new ProjectSearchOptions(facets: $versions);

// (1.20.1 OR 1.20) AND fabric AND mod
$facets = new FacetANDGroup([
    $versions,
    new FacetORGroup([new Facet(FacetType::CATEGORIES, "fabric")]),
    new FacetORGroup([new Facet(FacetType::PROJECT_TYPE, "mod")]),
]);
$options->setFacets($facets);

$projects = $modrinthClient->searchProjects($options);

Loaders are categories in the search, so use FacetType::CATEGORIES to filter by loader.

By default, facets check for equality. Other operations are available as well:

use Aternos\ModrinthApi\Client\Options\Facets\FacetOperation;

$facet = new Facet(FacetType::DOWNLOADS, "10000", FacetOperation::GREATER_THAN);

Fetching Projects

// get a project by its id or slug
$project = $modrinthClient->getProject("mclogs");
echo $project->getTitle() . ": " . $project->getDownloads() . " downloads" . PHP_EOL;

// get multiple projects by their ids
$projects = $modrinthClient->getProjects(["6DdCzpTL", "VPo0otUH"]);

// get random projects (the API may return fewer projects than requested)
$projects = $modrinthClient->getRandomProjects(10);

Check if a slug or id exists:

$projectId = $modrinthClient->checkProjectValidity("mclogs");

if ($projectId !== null) {
    echo "project exists, id: " . $projectId . PHP_EOL;
} else {
    echo "project does not exist" . PHP_EOL;
}

Additional Project Data

The Project and SearchProject wrappers provide methods to fetch related data:

$project = $modrinthClient->getProject("mclogs");

// all versions of the project, optionally filtered by loaders, game versions and featured status
$versions = $project->fetchProjectVersions();
$versions = $project->fetchProjectVersions(["paper"], ["1.21"]);

// the members of the project team
$members = $project->getMembers();

// the dependencies of the project
// projects can depend on other projects or directly on specific versions
$dependencies = $project->getDependencies();
$dependencyProjects = $dependencies->getProjects();
$dependencyVersions = $dependencies->getVersions();

// the moderation thread of the project (requires authentication, not available for search results)
$thread = $project->getThread();

Note that $project->getVersions() is the getter of the generated model and only returns the version ids. Use fetchProjectVersions() to get the full versions.

Versions

// get all versions of a project, optionally filtered by loaders, game versions and featured status
$versions = $modrinthClient->getProjectVersions("mclogs");
$versions = $modrinthClient->getProjectVersions("mclogs", ["paper"], ["1.21"], true);

// get a version of a project by its id or version number
$version = $modrinthClient->getProjectVersionFromIdOrNumber("mclogs", "2.6.2");

// get a version by its id
$version = $modrinthClient->getVersion("xzRGr4AC");

// get multiple versions by their ids
$versions = $modrinthClient->getVersions(["xzRGr4AC", "EwNN8uNA"]);

The Version wrapper provides methods to fetch related data:

$project = $version->getProject();
$author = $version->getAuthor();

foreach ($version->getDependencies() as $dependency) {
    // a dependency can point to a project, a specific version or both
    $dependencyProject = $dependency->getProject();
    $dependencyVersion = $dependency->getVersion();
}

// get the download url of the primary file
foreach ($version->getFiles() as $file) {
    if ($file->getPrimary()) {
        echo $file->getFilename() . ": " . $file->getUrl() . PHP_EOL;
    }
}

Finding Versions by File Hash

You can find the version a file belongs to by its SHA1 or SHA512 hash. For example, this can be used to find the source of a plugin or mod that is installed on a server.

use Aternos\ModrinthApi\Client\HashAlgorithm;

$hash = sha1_file("/path/to/plugin.jar");

// get the version of a file
$version = $modrinthClient->getVersionFromHash($hash, HashAlgorithm::SHA1);

// get the versions of multiple files at once
$versions = $modrinthClient->getVersionsFromHashes([$hash], HashAlgorithm::SHA1);

// get the latest version of the same project for the given loaders and game versions, e.g. to check for updates
$latest = $modrinthClient->getLatestVersionFromHash($hash, ["paper"], ["1.21"], HashAlgorithm::SHA1);

// only consider release versions
$latest = $modrinthClient->getLatestVersionFromHash($hash, ["paper"], ["1.21"], HashAlgorithm::SHA1, ["release"]);

// the same for multiple files at once
$latest = $modrinthClient->getLatestVersionsFromHashes([$hash], ["paper"], ["1.21"], HashAlgorithm::SHA1);

Users

// get a user by id or username
$user = $modrinthClient->getUser("matthias");
echo $user->getUsername() . PHP_EOL;

// get multiple users by their ids
$users = $modrinthClient->getUsers(["MpxzqsyW", "Dc7EYhxG"]);

// get the user the api token belongs to (requires authentication)
$user = $modrinthClient->getCurrentUser();

// get the projects of a user
$projects = $user->getProjects();

// get the projects a user follows (requires authentication)
$projects = $user->getFollowedProjects();

// get the notifications of a user (requires authentication)
$notifications = $user->getNotifications();

// get the payout history of a user (requires authentication)
$history = $user->getPayoutHistory();

Teams

// get the members of a project
$members = $modrinthClient->getProjectMembers("mclogs");

// get the members of a team
$members = $modrinthClient->getTeamMembers("ThaUQrOs");

foreach ($members as $member) {
    echo $member->getUser()->getUsername() . ": " . $member->getRole() . PHP_EOL;
}

// get the members of multiple teams at once, returns one array of members per team
$teams = $modrinthClient->getTeams(["ThaUQrOs"]);

Tags

You can fetch all available categories, loaders, game versions and project types. These tags can be used to search for projects directly:

$categories = $modrinthClient->getCategories();
$projects = $categories[0]->searchProjects();

$loaders = $modrinthClient->getLoaders();
$projects = $loaders[0]->searchProjects();

$gameVersions = $modrinthClient->getGameVersions();
$projects = $gameVersions[0]->searchProjects();

$projectTypes = $modrinthClient->getProjectTypes();
$projects = $projectTypes[0]->searchProjects();

// search options can be passed as well, the tag is added to the existing facets
$projects = $categories[0]->searchProjects(new ProjectSearchOptions(query: "chat"));

// or use the tag as a facet in your own search
$facet = $gameVersions[0]->toFacet();

Other tags:

$sideTypes = $modrinthClient->getSideTypes();
$donationPlatforms = $modrinthClient->getDonationPlatforms();
$reportTypes = $modrinthClient->getReportTypes();

// get the full text of a license by its SPDX id
$licenseText = $modrinthClient->getLicenseText("MIT");

Updating the generated code

The generated code can be updated by installing the openapi generator running the following command:

openapi-generator-cli generate -c config.yaml