MENU navbar-image

Introduction

The ModDex API gives read-only access to ModDex's Minecraft mod and modpack catalog: community reviews and ratings, project details, files, dependencies, and lookup from CurseForge and Modrinth IDs, slugs and links.

Access and rate limits

Every v2 endpoint is public. A token is optional: it raises your limits and changes nothing else (see Authenticating requests). Limits are per minute, counted per client IP (IPv6 per /64) without a token and per account with one:

Without a token With a token
All requests 60 300
Searches and filtered /v2/projects requests 30 120

A search is any /v2/projects request with q or a filter. Paging, sorting and type count only against the first row. A batch lookup counts as one request.

Every response counted against your limit carries:

If you go over, you get 429 with code: rate_limited and a Retry-After header (seconds). Wait that long before retrying. A response served from a cache carries the headers of the request that filled it, so treat them as approximate.

The API also has a shared ceiling for expensive requests (searches, heavy include blocks, dependents and modpack contents). When the whole API is busy those return 503 with code: service_unavailable and a Retry-After, whatever your own limit.

If that isn't enough, create a token and then ask for a higher limit by email at [email protected] or on the ModDex Discord. Tell us your ModDex username, what you're building and roughly how many requests a minute you expect.

Identify your client

Send X-Client: <name>/<version> with every request, for example X-Client: modrinth-reviews-extension/2.1.0. Browser extensions can't set User-Agent, so use X-Client; server-side clients may send either. It doesn't change the response. We use it to tell your traffic apart from everyone else's, and to get in touch before we block anything.

Caching

Responses are Cache-Control: public, max-age=300 (5 minutes) with an ETag. Catalog vocabulary (/v2/catalog/filters, /v2/minecraft-versions, /v2/loaders, /v2/tags) is cached for an hour. A lookup that finds nothing is cached for 60 seconds, so a page that isn't on ModDex doesn't cost a request on every view. No other error is cached.

Revalidate with If-None-Match: <etag>: an unchanged response is 304 with no body. Requests with a token are private, so shared caches skip them.

CORS

Every endpoint sends Access-Control-Allow-Origin: *, so a browser page or extension on any origin can call it. Requests don't use credentials, so don't send cookies. Authorization and X-Client are allowed request headers, and ETag, Retry-After and the X-RateLimit-* headers are readable from JavaScript.

Conventions

Errors. Every error has the same shape. Branch on code, which is stable, rather than on message:

{
    "message": "The per page field must not be greater than 50.",
    "code": "validation_failed",
    "errors": {"per_page": ["The per page field must not be greater than 50."]},
    "docs_url": "https://moddex.gg/api/docs"
}
code Status Meaning
not_found 404 No such project, review or route.
validation_failed 422 A parameter is invalid; errors maps each parameter to its messages.
ambiguous 422 A slug matches a mod and a modpack; candidates lists both. Pass type.
conflict 409 A combined lookup's identifiers match different projects; matches shows which.
page_depth_exceeded 422 page × per_page is over 10,000. Narrow the query with filters.
invalid_cursor 422 A sync cursor was edited or belongs to the other feed. Start over without it.
unauthenticated, token_expired 401 The bearer token is invalid, or has expired.
forbidden 403 Your client is blocked, or the token can't be used (no read ability, or an unverified account).
rate_limited 429 See Access and rate limits.
service_unavailable 503 Busy, timed out, or switched off for maintenance. Retry after Retry-After.
method_not_allowed, bad_request, server_error, api_version_retired 405, 400, 500, 410 As named.

Some errors add a hint saying what to change.

Lists are comma-separated: genres=tech,magic. Values are trimmed, and empty and repeated entries are ignored. Array syntax (genres[]=) and repeated keys are a 422. A list takes at most 50 values unless its parameter says fewer, and a batch lookup takes 100 in total.

Booleans are 1, 0, true or false. Anything else is a 422. A filter described only by what it keeps, such as featured ("Only staff picks"), does nothing when 0.

include adds heavy blocks a response leaves out by default, such as include=description,ratings on a project. Each endpoint lists what it accepts; an unknown value is a 422.

Pagination. Lists are paged with page and per_page and return meta: {current_page, last_page, per_page, total} and links: {first, last, prev, next}. You can read up to 10,000 rows into a list (page × per_page). The two sync feeds use cursors instead: follow meta.next_cursor.

Endpoint Paging per_page (default / max)
/v2/projects page 20 / 50
/v2/projects/{id}/reviews, /v2/reviews, lookup reviews page 20 / 50
/v2/projects/{id}/files page 20 / 50 (10 / 10 with include=changelog)
/v2/projects/{id}/dependencies, /contents page 20 / 100
/v2/projects/{id}/dependents page 20 / 50
/v2/projects/{id}/similar page 12 / 50
/v2/sync/projects cursor 100 / 100
/v2/sync/reviews cursor 50 / 50

Timestamps are ISO 8601 in UTC, such as 2026-09-30T12:00:00Z.

Ratings. A reviewer rates from 0.5 to 5 stars in steps of 0.5. Every project carries a rating block:

"rating": {"average": 4.8, "bayesian": 4.6, "count": 52, "written_count": 31}

average is the mean and bayesian the adjusted score the catalog ranks by; both are null (not 0) when nobody has rated the project. count is every rating, quick (stars only) and written; written_count is written reviews only.

Taxonomy. Genres, features, themes, loaders and environments are {slug, name} objects. The slug is what the matching /v2/projects filter takes, so a value from any response can go straight back into a filter. Minecraft versions are plain strings such as 1.21.1.

Downloads. downloads_count is exact. The min_downloads and max_downloads filters compare against the count rounded to 2 significant figures, as the website's slider does, and max_downloads is exclusive.

Output safety

Fields named *_html (descriptions, changelogs, review text) are sanitized HTML that's safe to insert into a page:

Everything else is plain text, so escape it before you render it. That includes:

On a page you don't control (a browser extension on Modrinth or CurseForge), put ModDex HTML inside a Shadow DOM or a sandboxed iframe, so the host page's styles and scripts can't reach it, and ours can't reach theirs.

Spoilers in content_html are wrapped in <span data-spoiler>. Hide them with CSS such as [data-spoiler]{filter:blur(4px)}.

Profanity masking

Review text is masked by default: each profane word becomes asterisks of the same length. Add unmasked=1 for the original text. Masking depends only on that parameter, not on who's asking, so responses stay cacheable.

Looking up projects

ModDex lists projects from CurseForge and Modrinth, often both under one page. Lookup finds that page from any of six keys:

Key Example
moddex_id 1234
moddex_slug sodium (old slugs still resolve: via_alias)
curseforge_id 394468
curseforge_slug sodium
modrinth_id AANobbMI (8 characters, case-sensitive)
modrinth_slug sodium

Path form. /v2/lookup/{platform}/{value} works out whether the value is an ID or a slug. Add /reviews to get the project's reviews with the project summary in meta.project, in one request.

Links. /v2/lookup?url=<link> takes a pasted ModDex, CurseForge or Modrinth project link, with or without the scheme, www., a trailing slash, query string or fragment. The link's own type (/mod/ or /modpack/) is used. ModDex doesn't fetch the link.

Combined. /v2/lookup?curseforge_id=394468&modrinth_id=AANobbMI resolves each key separately. If they all match the same project, or only some match (ModDex may not have linked the two listings), you get 200 with matched saying what each key hit. Keys that match different projects are a 409 conflict.

Mod or modpack? A CurseForge slug, or a ModDex slug, can belong to a mod and a modpack at once. Without type=mod or type=modpack that's 422 ambiguous with both candidates. Links carry their type, so url= is never ambiguous.

Stale listings. When a platform slug is held by more than one project of the same type (a listing that stopped syncing keeps its old URL), the live, most recently synced one wins and the others are listed in matched.alternatives.

Merged listings. Some mods publish separate Fabric and Forge listings that ModDex merges into one page. Looking up the merged listing returns the main project with matched.via_facet: true. A /v2/projects/{id}/… URL with a merged listing's ID redirects (301) to the main project.

Batch and files. /v2/lookup/batch looks up to 100 values in one request. /v2/lookup/files finds a project from a Modrinth file's SHA1 or a CurseForge file ID, and /v2/lookup/files/batch takes up to 100.

Lookup resolves every project that has a ModDex page, including delisted ones (available: false). Listings (/v2/projects, similar projects) show only what the catalog shows.

Storing ModDex data

The API is built for showing ModDex data next to your own, not for copying the catalog. If you do store reviews or projects for longer than the HTTP cache keeps them, ModDex's terms require you to remove content within 7 days of its removal from ModDex. To do that:

The daily check is needed because a review can disappear without leaving a tombstone (it was unapproved or deleted, or its author deleted their account).

Authenticating requests

You don't need a token for v2. A token only raises your rate limits (see Access and rate limits), and the responses are the same either way. The deprecated v1 endpoints still require one.

Token lifecycle

  1. Create: sign in to ModDex, open Settings → API Tokens, name the token and click Create (you may be asked for your password). Copy the token right away, because it's only shown in full once.
  2. Use: send it in the Authorization header. Responses to a request with a token carry X-ModDex-Token-Expires, the expiry time in ISO 8601.
  3. Renew: tokens expire after 90 days. We email you 7 days and 1 day before. Create a new one and swap it in.
  4. Revoke: delete a token from the same page at any time.
Authorization: Bearer {YOUR_AUTH_KEY}

Tokens are read-only. Keep them on a server: if you put a token in a browser extension or a web page, anyone who installs or opens it can read the token.

Check a token with:

curl https://moddex.gg/api/user \
  --header 'Authorization: Bearer {YOUR_AUTH_KEY}' \
  --header 'Accept: application/json'

A 200 means it works; X-ModDex-Token-Expires says until when.

Authentication errors

If the token doesn't work, you get an error. We don't quietly downgrade the request to guest access.

v2 code v1 error Meaning
unauthenticated token_invalid The token is unknown, malformed or revoked.
token_expired token_expired The token is past its expiry date.
(none) token_missing v1 only: no token was sent.

v2 errors use the standard error shape:

{
    "message": "API token has expired.",
    "code": "token_expired",
    "hint": "Create a new token from https://moddex.gg/settings?tab=tokens and update the Authorization header.",
    "docs_url": "https://moddex.gg/api/docs"
}

v2

The current API. It's public, so you don't need an account or a token. Every endpoint is a GET under https://moddex.gg/api/v2.

Lookup

Find a ModDex project from a ModDex, CurseForge or Modrinth ID or slug, from a pasted link, or from a file. Lookup resolves any project with a page on ModDex, including delisted ones (available: false). A merged loader-specific listing resolves to its project (via_facet), and an old ModDex slug to the project that holds it now (via_alias).

Look up by explicit keys or a link.

Pass any combination of the six keys and url. Each is resolved on its own, then:

url accepts modrinth.com/{mod|modpack}/{id or slug}, curseforge.com/minecraft/{mc-mods|modpacks}/{slug}, curseforge.com/projects/{id} and ModDex /{mod|modpack}/{slug} links, with or without the scheme, www., a trailing slash, query string or fragment. A CurseForge or Modrinth sub-page (/files, /files/{id}, /versions, /version/{v}, /gallery) resolves to its project, so the current tab's URL can be passed as it is. The link's type wins over type. ModDex doesn't fetch the link.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup?moddex_id=1234&curseforge_id=394468&modrinth_id=AANobbMI" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup"
);

const params = {
    "moddex_id": "1234",
    "curseforge_id": "394468",
    "modrinth_id": "AANobbMI",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'moddex_id' => '1234',
            'curseforge_id' => '394468',
            'modrinth_id' => 'AANobbMI',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup'
params = {
  'moddex_id': '1234',
  'curseforge_id': '394468',
  'modrinth_id': 'AANobbMI',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Found):


{
    "data": {
        "id": 1234,
        "name": "Sodium",
        "slug": "sodium",
        "type": "mod",
        "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
        "available": true,
        "rating": {
            "average": 4.8,
            "bayesian": 4.6,
            "count": 52,
            "written_count": 31
        },
        "links": {
            "web": "https://moddex.gg/mod/sodium",
            "reviews": "https://moddex.gg/mod/sodium#reviews",
            "write_review": "https://moddex.gg/mod/sodium#review-form",
            "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
        },
        "summary": "A modern rendering engine for Minecraft.",
        "downloads_count": 98000000,
        "last_updated_at": "2026-09-30T12:00:00Z",
        "published_at": "2020-01-07T00:00:00Z",
        "curseforge": {
            "id": 394468,
            "slug": "sodium",
            "url": "https://www.curseforge.com/minecraft/mc-mods/sodium",
            "downloads_count": 40000000,
            "created_at": "2020-06-01T00:00:00Z",
            "updated_at": "2026-09-30T12:00:00Z",
            "delisted_at": null,
            "screenshots": []
        },
        "modrinth": {
            "id": "AANobbMI",
            "slug": "sodium",
            "url": "https://modrinth.com/mod/sodium",
            "downloads_count": 58000000,
            "created_at": "2020-01-07T00:00:00Z",
            "updated_at": "2026-09-29T08:00:00Z",
            "delisted_at": null,
            "screenshots": [],
            "organization": {
                "id": "aBcD1234",
                "slug": "caffeinemc",
                "name": "CaffeineMC",
                "url": "https://modrinth.com/organization/caffeinemc",
                "icon_url": null
            }
        },
        "minecraft_versions": [
            "1.21.1",
            "1.20.1"
        ],
        "loaders": [
            {
                "slug": "fabric",
                "name": "Fabric"
            },
            {
                "slug": "neoforge",
                "name": "NeoForge"
            }
        ],
        "genres": [
            {
                "slug": "no-genre",
                "name": "No Genre"
            }
        ],
        "features": [
            {
                "slug": "performance-optimization",
                "name": "Performance & Optimization"
            }
        ],
        "themes": [],
        "environment": [
            {
                "slug": "client-only",
                "name": "Client Only"
            }
        ],
        "client_side": "required",
        "server_side": "unsupported",
        "counts": {
            "dependencies": 0,
            "dependents": 4200,
            "modpack_dependents": 3900
        },
        "featured": null,
        "license": {
            "name": "Polyform Shield License 1.0.0",
            "open_source": false,
            "categories": [
                "restrictive"
            ]
        },
        "latest_version": {
            "curseforge": null,
            "modrinth": {
                "version_number": "mc1.21.1-0.6.0",
                "released_at": "2026-09-29T08:00:00Z",
                "minecraft_versions": [
                    "1.21.1"
                ],
                "loaders": [
                    "fabric",
                    "neoforge"
                ],
                "release_type": "release",
                "url": "https://modrinth.com/mod/sodium/version/abc12345"
            }
        },
        "authors": [
            {
                "name": "CaffeineMC",
                "role": null,
                "is_owner": false,
                "is_organization": true,
                "curseforge_url": null,
                "modrinth_url": "https://modrinth.com/organization/caffeinemc",
                "curseforge_handle": null,
                "modrinth_handle": null
            },
            {
                "name": "jellysquid3",
                "role": "Owner",
                "is_owner": true,
                "is_organization": false,
                "curseforge_url": "https://www.curseforge.com/members/jellysquid3",
                "modrinth_url": "https://modrinth.com/user/jellysquid3",
                "curseforge_handle": "jellysquid3",
                "modrinth_handle": "jellysquid3"
            }
        ],
        "platform_urls": {
            "source": "https://github.com/CaffeineMC/sodium",
            "issues": "https://github.com/CaffeineMC/sodium/issues",
            "wiki": null,
            "discord": null
        },
        "sources": [
            {
                "project_id": 1234,
                "platform": "modrinth",
                "platform_id": "AANobbMI",
                "label": "Modrinth",
                "loaders": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    }
                ],
                "url": "https://modrinth.com/mod/sodium",
                "latest_file_url": "https://modrinth.com/mod/sodium/version/abc12345",
                "downloads_count": 58000000,
                "available": true,
                "is_canonical": true,
                "last_updated_at": "2026-09-29T08:00:00Z"
            }
        ],
        "community_tags_count": 3
    },
    "matched": {
        "curseforge_id": {
            "hit": true,
            "key": "curseforge_id",
            "value": "394468",
            "via_facet": false,
            "via_alias": false,
            "alternatives": []
        },
        "modrinth_id": {
            "hit": true,
            "key": "modrinth_id",
            "value": "AANobbMI",
            "via_facet": false,
            "via_alias": false,
            "alternatives": []
        }
    }
}
 

Example response (404, No match):


{
    "message": "No ModDex project matches.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Example response (409, Different projects):


{
    "message": "The identifiers match different projects.",
    "code": "conflict",
    "matches": {
        "curseforge_id": 1234,
        "modrinth_id": 5678
    },
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/lookup

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

moddex_id   integer  optional    

ModDex project ID. Example: 1234

moddex_slug   string  optional    

ModDex slug; old slugs resolve too.

curseforge_id   integer  optional    

CurseForge project ID. Example: 394468

curseforge_slug   string  optional    

CurseForge slug.

modrinth_id   string  optional    

Modrinth project ID (8 characters, case-sensitive). Example: AANobbMI

modrinth_slug   string  optional    

Modrinth slug.

url   string  optional    

A ModDex, CurseForge or Modrinth project link, URL-encoded.

type   string  optional    

Restrict to mod or modpack.

include   string  optional    

Comma-separated blocks to add, as on "Show a project".

Response

Response Fields

data   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When CurseForge stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

description_html   string     

With include=description. Sanitized HTML.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When Modrinth stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

organization   object|null     

The Modrinth organization that owns it, if any.

id   string     
slug   string|null     
name   string     
url   string|null     
icon_url   string|null     
description   string|null     

With include=description. Markdown source that allows inline HTML: never render it with a permissive renderer; use description_html.

description_html   string|null     

With include=description. Sanitized HTML.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

followers   integer     

With include=counts.

stacks   integer     

With include=counts.

library_entries   integer     

With include=counts.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

license   object     
name   string|null     

As listed; comma-separated when several.

open_source   boolean     

True only when every listed license is open source.

categories   string[]     

One of permissive, copyleft, public_domain, attribution, restrictive, other, none.

latest_version   object     

Newest release per platform; null when there is none.

curseforge   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

modrinth   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

authors   object[]     

Credits, as the project page shows them.

name   string     
role   string|null     
is_owner   boolean     
is_organization   boolean     
curseforge_url   string|null     
modrinth_url   string|null     
curseforge_handle   string|null     

CurseForge username; what curseforge_authors matches.

modrinth_handle   string|null     

Modrinth username; what modrinth_authors matches.

platform_urls   object     

Each an https URL or null.

source   string|null     
issues   string|null     
wiki   string|null     
discord   string|null     
sources   object[]     

Every listing the project is downloaded from, including merged loader-specific ones.

project_id   integer     

The listing's ModDex ID: what /dependencies?source= takes.

platform   string     

One of curseforge, modrinth.

platform_id   string     
label   string     
loaders   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

url   string|null     

Null while the listing is delisted.

latest_file_url   string|null     
downloads_count   integer     
available   boolean     
is_canonical   boolean     

This is the project's own row, not a merged loader-specific listing.

last_updated_at   string|null     
community_tags_count   integer     

Tags in /community-tags active: voted community tags plus the project's own genres, themes and features.

ratings   object     

With include=ratings.

histogram   object[]     

Ten steps, 0.5 to 5.

rating   number     

0.5 to 5.

count   integer     
categories   object     
gameplay   object[]     
rating   number     

0.5 to 5.

count   integer     
performance   object[]     
rating   number     

0.5 to 5.

count   integer     
aesthetics   object[]     
rating   number     

0.5 to 5.

count   integer     
ranks   object|null     

Null when unrated.

global   integer     
by_type   integer     

Among projects of the same type.

avg_completion_hours   number|null     

With include=completion. Modpacks only; null for mods and when nobody has reported it.

matched   object     

One entry per lookup parameter sent, keyed by parameter name.

*   object     
hit   boolean     

Whether this parameter matched the project.

key   string|null     

The identifier tried (for url, the one the link mapped to). Null for a link ModDex doesn't cover. One of moddex_id, moddex_slug, curseforge_id, curseforge_slug, modrinth_id, modrinth_slug.

value   string     

The value looked up (for url, the ID or slug taken from the link).

via_facet   boolean     
via_alias   boolean     
alternatives   integer[]     

Batch lookup.

Up to 100 values in total, comma-separated, in one request (it counts as one request against the rate limit). modrinth, curseforge and moddex values are auto-detected as on the path lookup. urls takes links: URL-encode each one before joining them with commas. A urls value that decodes to several links (the commas between them were encoded too) is a 422. type applies to every value except a link that carries its own type.

Each value maps to one of:

A bad value doesn't fail the rest of the batch. Output is keyed by each value as sent (trimmed); sort your values so identical batches share a cache entry.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup/batch?modrinth=AANobbMI%2Clithium&curseforge=394468" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup/batch"
);

const params = {
    "modrinth": "AANobbMI,lithium",
    "curseforge": "394468",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup/batch';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'modrinth' => 'AANobbMI,lithium',
            'curseforge' => '394468',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup/batch'
params = {
  'modrinth': 'AANobbMI,lithium',
  'curseforge': '394468',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Mixed):


{
    "data": {
        "modrinth": {
            "AANobbMI": {
                "id": 1234,
                "name": "Sodium",
                "slug": "sodium",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
                "available": true,
                "rating": {
                    "average": 4.8,
                    "bayesian": 4.6,
                    "count": 52,
                    "written_count": 31
                },
                "links": {
                    "web": "https://moddex.gg/mod/sodium",
                    "reviews": "https://moddex.gg/mod/sodium#reviews",
                    "write_review": "https://moddex.gg/mod/sodium#review-form",
                    "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
                }
            },
            "lithium": null
        },
        "curseforge": {},
        "moddex": {},
        "urls": {}
    }
}
 

Request      

GET api/v2/lookup/batch

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

modrinth   string  optional    

Modrinth IDs or slugs. Example: AANobbMI,lithium

curseforge   string  optional    

CurseForge IDs or slugs. Example: 394468

moddex   string  optional    

ModDex IDs or slugs.

urls   string  optional    

ModDex, CurseForge or Modrinth links, each URL-encoded.

type   string  optional    

mod or modpack.

Response

Response Fields

data   object     
modrinth   object     

Keyed by each modrinth value as sent: a project summary, {ambiguous, candidates}, or null (not on ModDex, or not a valid value).

*   object     
ambiguous   boolean     
candidates   object[]     

Every project the value could mean. The project summary: id, name, slug, type, logo_url, available, rating and links.

curseforge   object     

Keyed by each curseforge value as sent: a project summary, {ambiguous, candidates}, or null (not on ModDex, or not a valid value).

*   object     
ambiguous   boolean     
candidates   object[]     

Every project the value could mean. The project summary: id, name, slug, type, logo_url, available, rating and links.

moddex   object     

Keyed by each moddex value as sent: a project summary, {ambiguous, candidates}, or null (not on ModDex, or not a valid value).

*   object     
ambiguous   boolean     
candidates   object[]     

Every project the value could mean. The project summary: id, name, slug, type, logo_url, available, rating and links.

urls   object     

Keyed by each urls value as sent: a project summary, {ambiguous, candidates}, or null (not on ModDex, or not a valid value).

*   object     
ambiguous   boolean     
candidates   object[]     

Every project the value could mean. The project summary: id, name, slug, type, logo_url, available, rating and links.

Look up a file.

Map a file (from a mods folder or a crash log) to its ModDex project. Modrinth files are found by SHA1, CurseForge files by file ID. CurseForge fingerprints aren't stored, so a CurseForge jar can't be found by its content.

Pass exactly one of sha1 or curseforge_file_id. A Modrinth file returns its version's row: the version's primary file at the top level and the rest in secondary_files. secondary is true when the SHA1 you sent is one of those secondary files.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup/files?curseforge_file_id=5432101" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup/files"
);

const params = {
    "curseforge_file_id": "5432101",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup/files';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'curseforge_file_id' => '5432101',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup/files'
params = {
  'curseforge_file_id': '5432101',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Found):


{
    "data": {
        "file": {
            "id": 9,
            "platform": "curseforge",
            "curseforge_file_id": "5432101",
            "modrinth_version_id": null,
            "sha1": null,
            "display_name": "sodium-1.21.1-0.6.0.jar",
            "version_number": "0.6.0",
            "release_type": "release",
            "minecraft_versions": [
                "1.21.1"
            ],
            "loaders": [
                "fabric"
            ],
            "file_name": "sodium-1.21.1-0.6.0.jar",
            "file_size": 1048576,
            "downloads_count": 1200,
            "released_at": "2026-09-01T12:00:00Z",
            "is_featured": false,
            "download_url": "https://www.curseforge.com/minecraft/mc-mods/sodium/download/5432101",
            "platform_url": "https://www.curseforge.com/minecraft/mc-mods/sodium/files/5432101",
            "server_pack": null,
            "secondary_files": []
        },
        "project": {
            "id": 1234,
            "name": "Sodium",
            "slug": "sodium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
            "available": true,
            "rating": {
                "average": 4.8,
                "bayesian": 4.6,
                "count": 52,
                "written_count": 31
            },
            "links": {
                "web": "https://moddex.gg/mod/sodium",
                "reviews": "https://moddex.gg/mod/sodium#reviews",
                "write_review": "https://moddex.gg/mod/sodium#review-form",
                "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
            }
        },
        "secondary": false
    }
}
 

Example response (404, No match):


{
    "message": "No ModDex project has this file.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/lookup/files

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

sha1   string  optional    

A Modrinth file's SHA1 (40 hex characters, any case).

curseforge_file_id   integer  optional    

A CurseForge file ID. Example: 5432101

Response

Response Fields

data   object     
file   object     

The release row.

id   integer     

ModDex file ID.

platform   string     

One of curseforge, modrinth.

curseforge_file_id   string|null     

CurseForge rows only.

modrinth_version_id   string|null     

Modrinth rows only.

sha1   string|null     

Modrinth rows only: the primary file's SHA1.

display_name   string     
version_number   string|null     
release_type   string     

One of release, beta, alpha.

minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

file_name   string|null     
file_size   integer|null     

Bytes.

downloads_count   integer     

The file's downloads (the version's, for Modrinth rows).

released_at   string|null     
is_featured   boolean     

Modrinth's featured flag.

download_url   string|null     

The platform's download page. Null while the publishing listing is delisted.

platform_url   string|null     

The release's page on its platform. Null while the listing is delisted.

server_pack   object|null     

CurseForge modpacks: the server pack.

curseforge_file_id   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
secondary_files   object[]     

Modrinth: the version's other files.

sha1   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
changelog_html   string|null     

With include=changelog. Sanitized HTML.

changelog_truncated   boolean     

With include=changelog. True when the changelog was cut at 100 KB.

project   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

secondary   boolean     

The looked-up SHA1 is one of this version's secondary files.

Batch file lookup.

Up to 100 values in total across sha1 and curseforge_file_id, comma-separated. Each maps to {file, project, secondary} or null (unknown, hidden or malformed). Output is keyed by each value as sent.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup/files/batch?curseforge_file_id=5432101%2C5432102" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup/files/batch"
);

const params = {
    "curseforge_file_id": "5432101,5432102",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup/files/batch';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'curseforge_file_id' => '5432101,5432102',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup/files/batch'
params = {
  'curseforge_file_id': '5432101,5432102',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Mixed):


{
    "data": {
        "sha1": {},
        "curseforge_file_id": {
            "5432101": null
        }
    }
}
 

Request      

GET api/v2/lookup/files/batch

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

sha1   string  optional    

Modrinth SHA1s.

curseforge_file_id   string  optional    

CurseForge file IDs. Example: 5432101,5432102

Response

Response Fields

data   object     
sha1   object     

Keyed by SHA1 as sent; null when unknown.

*   object     
file   object     

The release row.

id   integer     

ModDex file ID.

platform   string     

One of curseforge, modrinth.

curseforge_file_id   string|null     

CurseForge rows only.

modrinth_version_id   string|null     

Modrinth rows only.

sha1   string|null     

Modrinth rows only: the primary file's SHA1.

display_name   string     
version_number   string|null     
release_type   string     

One of release, beta, alpha.

minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

file_name   string|null     
file_size   integer|null     

Bytes.

downloads_count   integer     

The file's downloads (the version's, for Modrinth rows).

released_at   string|null     
is_featured   boolean     

Modrinth's featured flag.

download_url   string|null     

The platform's download page. Null while the publishing listing is delisted.

platform_url   string|null     

The release's page on its platform. Null while the listing is delisted.

server_pack   object|null     

CurseForge modpacks: the server pack.

curseforge_file_id   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
secondary_files   object[]     

Modrinth: the version's other files.

sha1   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
changelog_html   string|null     

With include=changelog. Sanitized HTML.

changelog_truncated   boolean     

With include=changelog. True when the changelog was cut at 100 KB.

project   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

secondary   boolean     

The looked-up SHA1 is one of this version's secondary files.

curseforge_file_id   object     

Keyed by file ID as sent; null when unknown.

*   object     
file   object     

The release row.

id   integer     

ModDex file ID.

platform   string     

One of curseforge, modrinth.

curseforge_file_id   string|null     

CurseForge rows only.

modrinth_version_id   string|null     

Modrinth rows only.

sha1   string|null     

Modrinth rows only: the primary file's SHA1.

display_name   string     
version_number   string|null     
release_type   string     

One of release, beta, alpha.

minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

file_name   string|null     
file_size   integer|null     

Bytes.

downloads_count   integer     

The file's downloads (the version's, for Modrinth rows).

released_at   string|null     
is_featured   boolean     

Modrinth's featured flag.

download_url   string|null     

The platform's download page. Null while the publishing listing is delisted.

platform_url   string|null     

The release's page on its platform. Null while the listing is delisted.

server_pack   object|null     

CurseForge modpacks: the server pack.

curseforge_file_id   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
secondary_files   object[]     

Modrinth: the version's other files.

sha1   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
changelog_html   string|null     

With include=changelog. Sanitized HTML.

changelog_truncated   boolean     

With include=changelog. True when the changelog was cut at 100 KB.

project   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

secondary   boolean     

The looked-up SHA1 is one of this version's secondary files.

Look up by platform and value, with the project's reviews.

The project's review list (same parameters and response as /v2/projects/{id}/reviews), with the project in meta.project (summary shape) and the match in meta.matched (as on the path lookup). One request gives a browser extension the rating, the links and the reviews.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Found):


{
    "data": [],
    "links": {
        "first": "https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews?page=1",
        "last": "https://moddex.gg/api/v2/lookup/modrinth/sodium/reviews?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 0,
        "project": {
            "id": 1234,
            "name": "Sodium",
            "slug": "sodium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
            "available": true,
            "rating": {
                "average": null,
                "bayesian": null,
                "count": 0,
                "written_count": 0
            },
            "links": {
                "web": "https://moddex.gg/mod/sodium",
                "reviews": "https://moddex.gg/mod/sodium#reviews",
                "write_review": "https://moddex.gg/mod/sodium#review-form",
                "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
            }
        },
        "matched": {
            "key": "modrinth_slug",
            "value": "sodium",
            "via_facet": false,
            "via_alias": false,
            "alternatives": []
        }
    }
}
 

Example response (404, No match):


{
    "message": "No ModDex project matches.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/lookup/{platform}/{value}/reviews

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

platform   string     

One of moddex, curseforge, modrinth. Example: modrinth

value   string     

A project ID or slug on that platform. Example: sodium

Query Parameters

type   string  optional    

Restrict to mod or modpack.

sort   string  optional    

newest (default), oldest, rating or helpful.

unmasked   boolean  optional    

Return text without profanity masking.

per_page   integer  optional    

1 to 50. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
id   integer     
is_quick_rating   boolean     

Stars only: no title or text.

title   string|null     

Plain text.

content   string|null     

The Markdown the author wrote. Plain text: escape it.

content_html   string|null     

Sanitized HTML. Spoilers are wrapped in <span data-spoiler>.

rating   number     

0.5 to 5 in steps of 0.5.

categories   object     

Each 0.5 to 5, or null when not rated.

gameplay   number|null     
performance   number|null     
aesthetics   number|null     
minecraft_version   string|null     

As the reviewer entered it; may list several, comma-separated.

playtime_hours   integer|null     
completion_hours   integer|null     
play_status   string|null     

One of playing, played, completed, plan_to_play, on_hold, dropped.

pack_version   string|null     

The modpack version reviewed.

helpful_votes   integer     
unhelpful_votes   integer     
is_verified_developer   boolean     

Written by one of the project's verified developers.

public_moderator_note   string|null     

Plain text.

images   object[]     
url   string     
caption   string|null     

Plain text.

developer_response   object|null     

The developer's reply, if any.

content   string     

Plain text.

responded_at   string|null     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
project   object     

The project summary: id, name, slug, type, logo_url, available, rating and links.

url   string|null     

The review's page on ModDex.

created_at   string|null     
edited_at   string|null     
updated_at   string|null     
links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
project   object     

The project.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

matched   object     

How the value matched.

key   string     

Which identifier matched. One of moddex_id, moddex_slug, curseforge_id, curseforge_slug, modrinth_id, modrinth_slug.

value   string     

The value as sent.

via_facet   boolean     

The identifier belongs to a loader-specific listing merged into this project.

via_alias   boolean     

The ModDex slug is one this project used to have.

alternatives   integer[]     

Other project IDs that share the slug and type (stale listings).

Look up by platform and value.

The value is auto-detected: on moddex and curseforge an all-digit value is tried as an ID first, then as a slug; on modrinth an 8-character value is tried as a project ID (exact, case-sensitive) first, then as a slug. An ID hit beats a slug hit. CurseForge and Modrinth slugs are matched case-insensitively; a ModDex slug is matched exactly first (some carry a case-sensitive suffix), then lowercased.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/lookup/modrinth/sodium?type=mod" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/lookup/modrinth/sodium"
);

const params = {
    "type": "mod",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/lookup/modrinth/sodium';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'mod',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/lookup/modrinth/sodium'
params = {
  'type': 'mod',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Found):


{
    "data": {
        "id": 1234,
        "name": "Sodium",
        "slug": "sodium",
        "type": "mod",
        "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
        "available": true,
        "rating": {
            "average": 4.8,
            "bayesian": 4.6,
            "count": 52,
            "written_count": 31
        },
        "links": {
            "web": "https://moddex.gg/mod/sodium",
            "reviews": "https://moddex.gg/mod/sodium#reviews",
            "write_review": "https://moddex.gg/mod/sodium#review-form",
            "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
        },
        "summary": "A modern rendering engine for Minecraft.",
        "downloads_count": 98000000,
        "last_updated_at": "2026-09-30T12:00:00Z",
        "published_at": "2020-01-07T00:00:00Z",
        "curseforge": {
            "id": 394468,
            "slug": "sodium",
            "url": "https://www.curseforge.com/minecraft/mc-mods/sodium",
            "downloads_count": 40000000,
            "created_at": "2020-06-01T00:00:00Z",
            "updated_at": "2026-09-30T12:00:00Z",
            "delisted_at": null,
            "screenshots": []
        },
        "modrinth": {
            "id": "AANobbMI",
            "slug": "sodium",
            "url": "https://modrinth.com/mod/sodium",
            "downloads_count": 58000000,
            "created_at": "2020-01-07T00:00:00Z",
            "updated_at": "2026-09-29T08:00:00Z",
            "delisted_at": null,
            "screenshots": [],
            "organization": {
                "id": "aBcD1234",
                "slug": "caffeinemc",
                "name": "CaffeineMC",
                "url": "https://modrinth.com/organization/caffeinemc",
                "icon_url": null
            }
        },
        "minecraft_versions": [
            "1.21.1",
            "1.20.1"
        ],
        "loaders": [
            {
                "slug": "fabric",
                "name": "Fabric"
            },
            {
                "slug": "neoforge",
                "name": "NeoForge"
            }
        ],
        "genres": [
            {
                "slug": "no-genre",
                "name": "No Genre"
            }
        ],
        "features": [
            {
                "slug": "performance-optimization",
                "name": "Performance & Optimization"
            }
        ],
        "themes": [],
        "environment": [
            {
                "slug": "client-only",
                "name": "Client Only"
            }
        ],
        "client_side": "required",
        "server_side": "unsupported",
        "counts": {
            "dependencies": 0,
            "dependents": 4200,
            "modpack_dependents": 3900
        },
        "featured": null,
        "license": {
            "name": "Polyform Shield License 1.0.0",
            "open_source": false,
            "categories": [
                "restrictive"
            ]
        },
        "latest_version": {
            "curseforge": null,
            "modrinth": {
                "version_number": "mc1.21.1-0.6.0",
                "released_at": "2026-09-29T08:00:00Z",
                "minecraft_versions": [
                    "1.21.1"
                ],
                "loaders": [
                    "fabric",
                    "neoforge"
                ],
                "release_type": "release",
                "url": "https://modrinth.com/mod/sodium/version/abc12345"
            }
        },
        "authors": [
            {
                "name": "CaffeineMC",
                "role": null,
                "is_owner": false,
                "is_organization": true,
                "curseforge_url": null,
                "modrinth_url": "https://modrinth.com/organization/caffeinemc",
                "curseforge_handle": null,
                "modrinth_handle": null
            },
            {
                "name": "jellysquid3",
                "role": "Owner",
                "is_owner": true,
                "is_organization": false,
                "curseforge_url": "https://www.curseforge.com/members/jellysquid3",
                "modrinth_url": "https://modrinth.com/user/jellysquid3",
                "curseforge_handle": "jellysquid3",
                "modrinth_handle": "jellysquid3"
            }
        ],
        "platform_urls": {
            "source": "https://github.com/CaffeineMC/sodium",
            "issues": "https://github.com/CaffeineMC/sodium/issues",
            "wiki": null,
            "discord": null
        },
        "sources": [
            {
                "project_id": 1234,
                "platform": "modrinth",
                "platform_id": "AANobbMI",
                "label": "Modrinth",
                "loaders": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    }
                ],
                "url": "https://modrinth.com/mod/sodium",
                "latest_file_url": "https://modrinth.com/mod/sodium/version/abc12345",
                "downloads_count": 58000000,
                "available": true,
                "is_canonical": true,
                "last_updated_at": "2026-09-29T08:00:00Z"
            }
        ],
        "community_tags_count": 3
    },
    "matched": {
        "key": "modrinth_slug",
        "value": "sodium",
        "via_facet": false,
        "via_alias": false,
        "alternatives": []
    }
}
 

Example response (404, No match):


{
    "message": "No ModDex project matches.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Example response (422, Shared by a mod and a modpack):


{
    "message": "More than one project matches.",
    "code": "ambiguous",
    "hint": "Pass type=mod or type=modpack, or look up by a URL that carries the type.",
    "candidates": [],
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/lookup/{platform}/{value}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

platform   string     

One of moddex, curseforge, modrinth. Example: modrinth

value   string     

A project ID or slug on that platform, at most 255 characters. Example: sodium

Query Parameters

type   string  optional    

Restrict to mod or modpack. Needed when a slug is shared by a mod and a modpack. Example: mod

include   string  optional    

Comma-separated blocks to add, as on "Show a project".

Response

Response Fields

data   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When CurseForge stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

description_html   string     

With include=description. Sanitized HTML.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When Modrinth stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

organization   object|null     

The Modrinth organization that owns it, if any.

id   string     
slug   string|null     
name   string     
url   string|null     
icon_url   string|null     
description   string|null     

With include=description. Markdown source that allows inline HTML: never render it with a permissive renderer; use description_html.

description_html   string|null     

With include=description. Sanitized HTML.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

followers   integer     

With include=counts.

stacks   integer     

With include=counts.

library_entries   integer     

With include=counts.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

license   object     
name   string|null     

As listed; comma-separated when several.

open_source   boolean     

True only when every listed license is open source.

categories   string[]     

One of permissive, copyleft, public_domain, attribution, restrictive, other, none.

latest_version   object     

Newest release per platform; null when there is none.

curseforge   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

modrinth   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

authors   object[]     

Credits, as the project page shows them.

name   string     
role   string|null     
is_owner   boolean     
is_organization   boolean     
curseforge_url   string|null     
modrinth_url   string|null     
curseforge_handle   string|null     

CurseForge username; what curseforge_authors matches.

modrinth_handle   string|null     

Modrinth username; what modrinth_authors matches.

platform_urls   object     

Each an https URL or null.

source   string|null     
issues   string|null     
wiki   string|null     
discord   string|null     
sources   object[]     

Every listing the project is downloaded from, including merged loader-specific ones.

project_id   integer     

The listing's ModDex ID: what /dependencies?source= takes.

platform   string     

One of curseforge, modrinth.

platform_id   string     
label   string     
loaders   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

url   string|null     

Null while the listing is delisted.

latest_file_url   string|null     
downloads_count   integer     
available   boolean     
is_canonical   boolean     

This is the project's own row, not a merged loader-specific listing.

last_updated_at   string|null     
community_tags_count   integer     

Tags in /community-tags active: voted community tags plus the project's own genres, themes and features.

ratings   object     

With include=ratings.

histogram   object[]     

Ten steps, 0.5 to 5.

rating   number     

0.5 to 5.

count   integer     
categories   object     
gameplay   object[]     
rating   number     

0.5 to 5.

count   integer     
performance   object[]     
rating   number     

0.5 to 5.

count   integer     
aesthetics   object[]     
rating   number     

0.5 to 5.

count   integer     
ranks   object|null     

Null when unrated.

global   integer     
by_type   integer     

Among projects of the same type.

avg_completion_hours   number|null     

With include=completion. Modpacks only; null for mods and when nobody has reported it.

matched   object     

How the value matched.

key   string     

Which identifier matched. One of moddex_id, moddex_slug, curseforge_id, curseforge_slug, modrinth_id, modrinth_slug.

value   string     

The value as sent.

via_facet   boolean     

The identifier belongs to a loader-specific listing merged into this project.

via_alias   boolean     

The ModDex slug is one this project used to have.

alternatives   integer[]     

Other project IDs that share the slug and type (stale listings).

Projects

A project by its ModDex ID. Any project with a page on ModDex resolves, including delisted ones (available: false). A loader-specific listing that was merged into another project redirects (301) to that project.

List and search projects.

The catalog, as a guest sees it on the website: listed projects only (no delisted projects and no merged loader-specific listings), with every filter and sort the catalog page has. /v2/catalog/filters lists every parameter and its valid values; an unknown parameter or value is a 422.

Most list filters have an _exclude twin (genres_exclude=); genres, features, themes, minecraft_versions (mc_mode) and uses_mods take an any/all mode. Searches (q) and filtered requests count against a separate, lower rate limit; paging, sorting and type don't.

A search returns at most 1,000 matches and needs the search engine: while it is down, q gets a 503 and listing without q still works. Pages deeper than page × per_page = 10,000 are a 422.

A page can hold fewer than per_page projects while the search index catches up with a project that was just removed; meta.total still counts it until then.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects?type=mod&loaders=fabric&minecraft_versions=1.21.1&sort=downloads_count" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects"
);

const params = {
    "type": "mod",
    "loaders": "fabric",
    "minecraft_versions": "1.21.1",
    "sort": "downloads_count",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'mod',
            'loaders' => 'fabric',
            'minecraft_versions' => '1.21.1',
            'sort' => 'downloads_count',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects'
params = {
  'type': 'mod',
  'loaders': 'fabric',
  'minecraft_versions': '1.21.1',
  'sort': 'downloads_count',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "id": 1234,
            "name": "Sodium",
            "slug": "sodium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
            "available": true,
            "rating": {
                "average": 4.8,
                "bayesian": 4.6,
                "count": 52,
                "written_count": 31
            },
            "links": {
                "web": "https://moddex.gg/mod/sodium",
                "reviews": "https://moddex.gg/mod/sodium#reviews",
                "write_review": "https://moddex.gg/mod/sodium#review-form",
                "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
            },
            "summary": "A modern rendering engine for Minecraft.",
            "downloads_count": 98000000,
            "last_updated_at": "2026-09-30T12:00:00Z",
            "published_at": "2020-01-07T00:00:00Z",
            "curseforge": {
                "id": 394468,
                "slug": "sodium",
                "url": "https://www.curseforge.com/minecraft/mc-mods/sodium"
            },
            "modrinth": {
                "id": "AANobbMI",
                "slug": "sodium",
                "url": "https://modrinth.com/mod/sodium"
            },
            "minecraft_versions": [
                "1.21.1",
                "1.20.1"
            ],
            "loaders": [
                {
                    "slug": "fabric",
                    "name": "Fabric"
                }
            ],
            "genres": [
                {
                    "slug": "no-genre",
                    "name": "No Genre"
                }
            ],
            "features": [
                {
                    "slug": "performance-optimization",
                    "name": "Performance & Optimization"
                }
            ],
            "themes": [],
            "environment": [
                {
                    "slug": "client-only",
                    "name": "Client Only"
                }
            ],
            "client_side": "required",
            "server_side": "unsupported",
            "counts": {
                "dependencies": 0,
                "dependents": 4200,
                "modpack_dependents": 3900
            },
            "featured": null
        }
    ],
    "links": {
        "first": "https://moddex.gg/api/v2/projects?page=1",
        "last": "https://moddex.gg/api/v2/projects?page=200",
        "prev": null,
        "next": "https://moddex.gg/api/v2/projects?page=2"
    },
    "meta": {
        "current_page": 1,
        "last_page": 200,
        "per_page": 20,
        "total": 4000
    }
}
 

Example response (422, Unknown value):


{
    "message": "Unknown value(s): techh. Valid values: adventureexploration, base-defense, expert, kitchen-sink, magic, no-genre, roguelike, rpg, rts, run-and-gun, shooter, skyblock, stoneblock, survival, tech, vanilla, village-farm-life.",
    "code": "validation_failed",
    "errors": {
        "genres": [
            "Unknown value(s): techh. Valid values: adventureexploration, base-defense, expert, kitchen-sink, magic, no-genre, roguelike, rpg, rts, run-and-gun, shooter, skyblock, stoneblock, survival, tech, vanilla, village-farm-life."
        ]
    },
    "docs_url": "https://moddex.gg/api/docs"
}
 

Example response (503, Search unavailable):


{
    "message": "Service temporarily unavailable. Retry after the Retry-After interval.",
    "code": "service_unavailable",
    "hint": "Search is temporarily unavailable. Listing and filtering without q still work.",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/projects

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

q   string  optional    

Full-text search, 3 to 200 characters. Sorts by relevance unless sort is given.

type   string  optional    

mod or modpack. Example: mod

featured   boolean  optional    

Only staff picks.

loaders   string  optional    

Loader slugs (see /v2/loaders). With minecraft_versions, one file must carry both. Example: fabric

loaders_exclude   string  optional    
genres   string  optional    

Genre slugs (see /v2/tags?type=genre).

genres_exclude   string  optional    
genres_mode   string  optional    

any (default) or all.

features   string  optional    

Feature slugs.

features_exclude   string  optional    
features_mode   string  optional    

any (default) or all.

themes   string  optional    

Theme slugs.

themes_exclude   string  optional    
themes_mode   string  optional    

any (default) or all.

minecraft_versions   string  optional    

Exact versions (see /v2/minecraft-versions), or version groups such as 1.20 with mc_exact=0. Example: 1.21.1

minecraft_versions_exclude   string  optional    
mc_mode   string  optional    

any (default) or all.

mc_exact   boolean  optional    

Default true. False matches minecraft_versions as version groups.

environment   string  optional    

Where it installs: client-only, server-only, client-and-server, either-side, …

environment_exclude   string  optional    
platforms   string  optional    

curseforge, modrinth.

platforms_exclude   string  optional    
min_rating   number  optional    

0 to 5.

max_rating   number  optional    

0 to 5.

min_reviews   integer  optional    

Minimum ratings (quick and written).

max_reviews   integer  optional    
min_downloads   integer  optional    

Compared against the download count rounded to 2 significant figures.

max_downloads   integer  optional    

Exclusive, against the rounded count.

pack_size   string  optional    

small, medium, large, xlarge (modpacks by mod count).

min_modpack_usage   integer  optional    

Minimum number of modpacks that include the project.

authors   string  optional    

Up to 10 author names or handles on either platform, case-insensitive.

authors_exclude   string  optional    
curseforge_authors   string  optional    

Up to 10 CurseForge usernames (authors[].curseforge_handle), case-insensitive.

curseforge_authors_exclude   string  optional    
modrinth_authors   string  optional    

Up to 10 Modrinth usernames (authors[].modrinth_handle) or display names, case-insensitive.

modrinth_authors_exclude   string  optional    
uses_mods   string  optional    

Up to 10 ModDex mod IDs the project depends on.

uses_mods_exclude   string  optional    
uses_mods_mode   string  optional    

any (default) or all.

licenses   string  optional    

SPDX IDs such as MIT, case-insensitive.

licenses_exclude   string  optional    
open_source   boolean  optional    

True: every license is open source. False: anything else, including no license.

license_categories   string  optional    

permissive, copyleft, public_domain, attribution, restrictive, other, none.

license_categories_exclude   string  optional    
has_source   boolean  optional    

Only projects with a source code link.

has_wiki   boolean  optional    

Only projects with a wiki link.

updated_since   string  optional    

Last updated at or after: an ISO 8601 date (midnight UTC) or a date-time with a time zone.

updated_before   string  optional    

Last updated before (exclusive).

sort   string  optional    

bayesian_rating (default), relevance (default with q; needs q), average_rating, total_ratings, downloads_count, published_at, last_updated_at, dependencies_count, dependents_count, modpack_dependents_count, name. Example: downloads_count

direction   string  optional    

asc or desc. Defaults to asc for name, desc otherwise; relevance ignores it.

per_page   integer  optional    

1 to 50. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     

Projects in the list shape.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     

Show a project.

The full project. Heavy blocks are left out unless you ask for them with include:

Only fields named *_html are HTML; escape everything else (see Output safety).

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Found):


{
    "data": {
        "id": 1234,
        "name": "Sodium",
        "slug": "sodium",
        "type": "mod",
        "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
        "available": true,
        "rating": {
            "average": 4.8,
            "bayesian": 4.6,
            "count": 52,
            "written_count": 31
        },
        "links": {
            "web": "https://moddex.gg/mod/sodium",
            "reviews": "https://moddex.gg/mod/sodium#reviews",
            "write_review": "https://moddex.gg/mod/sodium#review-form",
            "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
        },
        "summary": "A modern rendering engine for Minecraft.",
        "downloads_count": 98000000,
        "last_updated_at": "2026-09-30T12:00:00Z",
        "published_at": "2020-01-07T00:00:00Z",
        "curseforge": {
            "id": 394468,
            "slug": "sodium",
            "url": "https://www.curseforge.com/minecraft/mc-mods/sodium",
            "downloads_count": 40000000,
            "created_at": "2020-06-01T00:00:00Z",
            "updated_at": "2026-09-30T12:00:00Z",
            "delisted_at": null,
            "screenshots": []
        },
        "modrinth": {
            "id": "AANobbMI",
            "slug": "sodium",
            "url": "https://modrinth.com/mod/sodium",
            "downloads_count": 58000000,
            "created_at": "2020-01-07T00:00:00Z",
            "updated_at": "2026-09-29T08:00:00Z",
            "delisted_at": null,
            "screenshots": [],
            "organization": {
                "id": "aBcD1234",
                "slug": "caffeinemc",
                "name": "CaffeineMC",
                "url": "https://modrinth.com/organization/caffeinemc",
                "icon_url": null
            }
        },
        "minecraft_versions": [
            "1.21.1",
            "1.20.1"
        ],
        "loaders": [
            {
                "slug": "fabric",
                "name": "Fabric"
            },
            {
                "slug": "neoforge",
                "name": "NeoForge"
            }
        ],
        "genres": [
            {
                "slug": "no-genre",
                "name": "No Genre"
            }
        ],
        "features": [
            {
                "slug": "performance-optimization",
                "name": "Performance & Optimization"
            }
        ],
        "themes": [],
        "environment": [
            {
                "slug": "client-only",
                "name": "Client Only"
            }
        ],
        "client_side": "required",
        "server_side": "unsupported",
        "counts": {
            "dependencies": 0,
            "dependents": 4200,
            "modpack_dependents": 3900
        },
        "featured": null,
        "license": {
            "name": "Polyform Shield License 1.0.0",
            "open_source": false,
            "categories": [
                "restrictive"
            ]
        },
        "latest_version": {
            "curseforge": null,
            "modrinth": {
                "version_number": "mc1.21.1-0.6.0",
                "released_at": "2026-09-29T08:00:00Z",
                "minecraft_versions": [
                    "1.21.1"
                ],
                "loaders": [
                    "fabric",
                    "neoforge"
                ],
                "release_type": "release",
                "url": "https://modrinth.com/mod/sodium/version/abc12345"
            }
        },
        "authors": [
            {
                "name": "CaffeineMC",
                "role": null,
                "is_owner": false,
                "is_organization": true,
                "curseforge_url": null,
                "modrinth_url": "https://modrinth.com/organization/caffeinemc",
                "curseforge_handle": null,
                "modrinth_handle": null
            },
            {
                "name": "jellysquid3",
                "role": "Owner",
                "is_owner": true,
                "is_organization": false,
                "curseforge_url": "https://www.curseforge.com/members/jellysquid3",
                "modrinth_url": "https://modrinth.com/user/jellysquid3",
                "curseforge_handle": "jellysquid3",
                "modrinth_handle": "jellysquid3"
            }
        ],
        "platform_urls": {
            "source": "https://github.com/CaffeineMC/sodium",
            "issues": "https://github.com/CaffeineMC/sodium/issues",
            "wiki": null,
            "discord": null
        },
        "sources": [
            {
                "project_id": 1234,
                "platform": "modrinth",
                "platform_id": "AANobbMI",
                "label": "Modrinth",
                "loaders": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    }
                ],
                "url": "https://modrinth.com/mod/sodium",
                "latest_file_url": "https://modrinth.com/mod/sodium/version/abc12345",
                "downloads_count": 58000000,
                "available": true,
                "is_canonical": true,
                "last_updated_at": "2026-09-29T08:00:00Z"
            }
        ],
        "community_tags_count": 3
    }
}
 

Example response (301, Merged listing):


{}
 

Example response (404, No such project):


{
    "message": "Not found.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Example response (422, Unknown include):


{
    "message": "Unknown value(s): screenshots. Valid values: description, ratings, counts, completion.",
    "code": "validation_failed",
    "errors": {
        "include": [
            "Unknown value(s): screenshots. Valid values: description, ratings, counts, completion."
        ]
    },
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/projects/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The ModDex project ID. Example: 1234

Query Parameters

include   string  optional    

Comma-separated blocks to add: description, ratings, counts, completion.

Response

Response Fields

data   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When CurseForge stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

description_html   string     

With include=description. Sanitized HTML.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

downloads_count   integer|null     
created_at   string|null     
updated_at   string|null     
delisted_at   string|null     

When Modrinth stopped listing it.

screenshots   object[]     
url   string     
title   string|null     

Plain text.

description   string|null     

Plain text.

organization   object|null     

The Modrinth organization that owns it, if any.

id   string     
slug   string|null     
name   string     
url   string|null     
icon_url   string|null     
description   string|null     

With include=description. Markdown source that allows inline HTML: never render it with a permissive renderer; use description_html.

description_html   string|null     

With include=description. Sanitized HTML.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

followers   integer     

With include=counts.

stacks   integer     

With include=counts.

library_entries   integer     

With include=counts.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

license   object     
name   string|null     

As listed; comma-separated when several.

open_source   boolean     

True only when every listed license is open source.

categories   string[]     

One of permissive, copyleft, public_domain, attribution, restrictive, other, none.

latest_version   object     

Newest release per platform; null when there is none.

curseforge   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

modrinth   object|null     
version_number   string|null     
released_at   string|null     
minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

release_type   string     

One of release, beta, alpha.

url   string|null     

The release on its platform.

authors   object[]     

Credits, as the project page shows them.

name   string     
role   string|null     
is_owner   boolean     
is_organization   boolean     
curseforge_url   string|null     
modrinth_url   string|null     
curseforge_handle   string|null     

CurseForge username; what curseforge_authors matches.

modrinth_handle   string|null     

Modrinth username; what modrinth_authors matches.

platform_urls   object     

Each an https URL or null.

source   string|null     
issues   string|null     
wiki   string|null     
discord   string|null     
sources   object[]     

Every listing the project is downloaded from, including merged loader-specific ones.

project_id   integer     

The listing's ModDex ID: what /dependencies?source= takes.

platform   string     

One of curseforge, modrinth.

platform_id   string     
label   string     
loaders   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

url   string|null     

Null while the listing is delisted.

latest_file_url   string|null     
downloads_count   integer     
available   boolean     
is_canonical   boolean     

This is the project's own row, not a merged loader-specific listing.

last_updated_at   string|null     
community_tags_count   integer     

Tags in /community-tags active: voted community tags plus the project's own genres, themes and features.

ratings   object     

With include=ratings.

histogram   object[]     

Ten steps, 0.5 to 5.

rating   number     

0.5 to 5.

count   integer     
categories   object     
gameplay   object[]     
rating   number     

0.5 to 5.

count   integer     
performance   object[]     
rating   number     

0.5 to 5.

count   integer     
aesthetics   object[]     
rating   number     

0.5 to 5.

count   integer     
ranks   object|null     

Null when unrated.

global   integer     
by_type   integer     

Among projects of the same type.

avg_completion_hours   number|null     

With include=completion. Modpacks only; null for mods and when nobody has reported it.

List a project's reviews.

Approved written reviews, as the project's Reviews tab shows them. Quick ratings (stars only) count toward rating but aren't listed.

Text is profanity-masked unless unmasked=1.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/reviews?sort=newest" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/reviews"
);

const params = {
    "sort": "newest",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'sort' => 'newest',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/reviews'
params = {
  'sort': 'newest',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Reviews):


{
    "data": [
        {
            "id": 77,
            "is_quick_rating": false,
            "title": "Essential",
            "content": "Doubles my FPS. ||The config screen is hidden in Video Settings.||",
            "content_html": "<p>Doubles my FPS. <span data-spoiler>The config screen is hidden in Video Settings.</span></p>",
            "rating": 5,
            "categories": {
                "gameplay": null,
                "performance": 5,
                "aesthetics": null
            },
            "minecraft_version": "1.21.1",
            "playtime_hours": 300,
            "completion_hours": null,
            "play_status": "playing",
            "pack_version": null,
            "helpful_votes": 12,
            "unhelpful_votes": 0,
            "is_verified_developer": false,
            "public_moderator_note": null,
            "images": [],
            "developer_response": null,
            "author": {
                "id": 9,
                "name": "Steve",
                "username": "steve",
                "avatar_url": null,
                "profile_url": "https://moddex.gg/user/steve",
                "roles": [],
                "reputation": {
                    "points": 420,
                    "tier": "contributor",
                    "tier_label": "Contributor"
                }
            },
            "project": {
                "id": 1234,
                "name": "Sodium",
                "slug": "sodium",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
                "available": true,
                "rating": {
                    "average": 4.8,
                    "bayesian": 4.6,
                    "count": 52,
                    "written_count": 31
                },
                "links": {
                    "web": "https://moddex.gg/mod/sodium",
                    "reviews": "https://moddex.gg/mod/sodium#reviews",
                    "write_review": "https://moddex.gg/mod/sodium#review-form",
                    "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
                }
            },
            "url": "https://moddex.gg/mod/sodium/reviews/77",
            "created_at": "2026-09-01T10:00:00Z",
            "edited_at": null,
            "updated_at": "2026-09-01T10:00:00Z"
        }
    ],
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/reviews?page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/reviews?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 1
    }
}
 

Request      

GET api/v2/projects/{project_id}/reviews

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Query Parameters

sort   string  optional    

newest (default), oldest, rating or helpful. Example: newest

min_rating   number  optional    

From 0.5 to 5.

max_rating   number  optional    

From 0.5 to 5.

minecraft_versions   string  optional    

Comma-separated versions the reviewer played; 1.20 matches every 1.20.x.

play_statuses   string  optional    

Comma-separated: playing, played, completed, on_hold, dropped.

playtime_min   integer  optional    

Minimum hours played.

media   string  optional    

all (default), with_images or text_only.

verified_only   boolean  optional    

Only reviews by the project's verified developers.

has_developer_response   boolean  optional    

Only reviews the developer answered.

pack_version   string  optional    

Comma-separated pack versions, matched exactly.

unmasked   boolean  optional    

Return text without profanity masking.

per_page   integer  optional    

1 to 50. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
id   integer     
is_quick_rating   boolean     

Stars only: no title or text.

title   string|null     

Plain text.

content   string|null     

The Markdown the author wrote. Plain text: escape it.

content_html   string|null     

Sanitized HTML. Spoilers are wrapped in <span data-spoiler>.

rating   number     

0.5 to 5 in steps of 0.5.

categories   object     

Each 0.5 to 5, or null when not rated.

gameplay   number|null     
performance   number|null     
aesthetics   number|null     
minecraft_version   string|null     

As the reviewer entered it; may list several, comma-separated.

playtime_hours   integer|null     
completion_hours   integer|null     
play_status   string|null     

One of playing, played, completed, plan_to_play, on_hold, dropped.

pack_version   string|null     

The modpack version reviewed.

helpful_votes   integer     
unhelpful_votes   integer     
is_verified_developer   boolean     

Written by one of the project's verified developers.

public_moderator_note   string|null     

Plain text.

images   object[]     
url   string     
caption   string|null     

Plain text.

developer_response   object|null     

The developer's reply, if any.

content   string     

Plain text.

responded_at   string|null     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
project   object     

The project summary: id, name, slug, type, logo_url, available, rating and links.

url   string|null     

The review's page on ModDex.

created_at   string|null     
edited_at   string|null     
updated_at   string|null     
links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     

List a project's files.

The project's Files tab, one platform at a time: the files of the project and of every loader-specific listing merged into it. Without platform you get the platform the website opens on; meta.platforms lists every platform with files.

One row per release. A CurseForge row is a file, with its server pack attached. A Modrinth row is a version: its primary file's fields at the top level, its other files in secondary_files.

download_url and platform_url are null while the listing that published the file is delisted. Download links go to the platform's own download or version page, not a CDN.

include=changelog adds each release's changelog as sanitized HTML and caps per_page at 10. A changelog over 100 KB is cut short (changelog_truncated: true); the full text is on platform_url.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/files?platform=modrinth&minecraft_version=1.21.1&loader=fabric" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/files"
);

const params = {
    "platform": "modrinth",
    "minecraft_version": "1.21.1",
    "loader": "fabric",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/files';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'platform' => 'modrinth',
            'minecraft_version' => '1.21.1',
            'loader' => 'fabric',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/files'
params = {
  'platform': 'modrinth',
  'minecraft_version': '1.21.1',
  'loader': 'fabric',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Modrinth versions):


{
    "data": [
        {
            "id": 9001,
            "platform": "modrinth",
            "curseforge_file_id": null,
            "modrinth_version_id": "abc12345",
            "sha1": "0123456789abcdef0123456789abcdef01234567",
            "display_name": "Sodium 0.6.0",
            "version_number": "mc1.21.1-0.6.0",
            "release_type": "release",
            "minecraft_versions": [
                "1.21.1"
            ],
            "loaders": [
                "fabric",
                "neoforge"
            ],
            "file_name": "sodium-fabric-0.6.0+mc1.21.1.jar",
            "file_size": 1048576,
            "downloads_count": 250000,
            "released_at": "2026-09-29T08:00:00Z",
            "is_featured": true,
            "download_url": "https://modrinth.com/mod/sodium/version/abc12345",
            "platform_url": "https://modrinth.com/mod/sodium/version/abc12345",
            "server_pack": null,
            "secondary_files": [
                {
                    "sha1": "89abcdef0123456789abcdef0123456789abcdef",
                    "file_name": "sodium-fabric-0.6.0+mc1.21.1-sources.jar",
                    "file_size": 524288,
                    "download_url": "https://modrinth.com/mod/sodium/version/abc12345"
                }
            ]
        }
    ],
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/files?page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/files?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 1,
        "platform": "modrinth",
        "platforms": [
            "curseforge",
            "modrinth"
        ]
    }
}
 

Example response (422, Too many changelogs):


{
    "message": "With include=changelog, per_page may be at most 10.",
    "code": "validation_failed",
    "errors": {
        "per_page": [
            "With include=changelog, per_page may be at most 10."
        ]
    },
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/projects/{project_id}/files

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Query Parameters

platform   string  optional    

curseforge or modrinth. Defaults to the website's tab. Example: modrinth

minecraft_version   string  optional    

An exact version as the file lists it. Example: 1.21.1

loader   string  optional    

A loader as the file lists it (fabric, forge, neoforge, quilt, …). Example: fabric

release_type   string  optional    

release, beta or alpha.

sort   string  optional    

released_at (default), downloads_count or version_number.

direction   string  optional    

asc or desc (default).

include   string  optional    

changelog.

per_page   integer  optional    

1 to 50 (10 with include=changelog). Default 20 (10 with include=changelog).

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     

One row per release.

id   integer     

ModDex file ID.

platform   string     

One of curseforge, modrinth.

curseforge_file_id   string|null     

CurseForge rows only.

modrinth_version_id   string|null     

Modrinth rows only.

sha1   string|null     

Modrinth rows only: the primary file's SHA1.

display_name   string     
version_number   string|null     
release_type   string     

One of release, beta, alpha.

minecraft_versions   string[]     

As the platform lists them.

loaders   string[]     

As the platform lists them.

file_name   string|null     
file_size   integer|null     

Bytes.

downloads_count   integer     

The file's downloads (the version's, for Modrinth rows).

released_at   string|null     
is_featured   boolean     

Modrinth's featured flag.

download_url   string|null     

The platform's download page. Null while the publishing listing is delisted.

platform_url   string|null     

The release's page on its platform. Null while the listing is delisted.

server_pack   object|null     

CurseForge modpacks: the server pack.

curseforge_file_id   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
secondary_files   object[]     

Modrinth: the version's other files.

sha1   string     
file_name   string|null     
file_size   integer|null     
download_url   string|null     
changelog_html   string|null     

With include=changelog. Sanitized HTML.

changelog_truncated   boolean     

With include=changelog. True when the changelog was cut at 100 KB.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
platform   string     

The platform listed. One of curseforge, modrinth.

platforms   string[]     

Platforms with at least one file. One of curseforge, modrinth.

List a project's dependencies.

What the project's Dependencies tab lists: the projects it requires, optionally uses, embeds or ships with, as its own listing declares them. A dependency ModDex has is project, in the list shape, always the project's main page even when the listing named a loader-specific one. A dependency ModDex doesn't have has project: null and only its platform ID and name.

On a project listed on both CurseForge and Modrinth, the two listings usually name the same libraries, so the list is read one platform at a time, as on the website: platform picks which (default: the website's), and a library on both appears once. meta.platform is null when the choice makes no difference.

Incompatible projects are listed in full under incompatible, not in data.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/dependencies?platform=modrinth" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/dependencies"
);

const params = {
    "platform": "modrinth",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/dependencies';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'platform' => 'modrinth',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/dependencies'
params = {
  'platform': 'modrinth',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Dependencies):


{
    "data": [
        {
            "relation_type": "required",
            "name": "Fabric API",
            "curseforge_id": null,
            "modrinth_id": "P7dR8mSH",
            "project": {
                "id": 77,
                "name": "Fabric API",
                "slug": "fabric-api",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/P7dR8mSH/icon.png",
                "available": true,
                "rating": {
                    "average": 4.9,
                    "bayesian": 4.7,
                    "count": 80,
                    "written_count": 40
                },
                "links": {
                    "web": "https://moddex.gg/mod/fabric-api",
                    "reviews": "https://moddex.gg/mod/fabric-api#reviews",
                    "write_review": "https://moddex.gg/mod/fabric-api#review-form",
                    "badge": "https://moddex.gg/badges/projects/fabric-api/rating.svg?type=mod"
                },
                "summary": "Core API library for the Fabric toolchain.",
                "downloads_count": 200000000,
                "last_updated_at": "2026-09-30T12:00:00Z",
                "published_at": "2018-12-14T00:00:00Z",
                "curseforge": {
                    "id": 306612,
                    "slug": "fabric-api",
                    "url": "https://www.curseforge.com/minecraft/mc-mods/fabric-api"
                },
                "modrinth": {
                    "id": "P7dR8mSH",
                    "slug": "fabric-api",
                    "url": "https://modrinth.com/mod/fabric-api"
                },
                "minecraft_versions": [
                    "1.21.1"
                ],
                "loaders": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    }
                ],
                "genres": [],
                "features": [
                    {
                        "slug": "apilibrary",
                        "name": "API/Library"
                    }
                ],
                "themes": [],
                "environment": [],
                "client_side": "optional",
                "server_side": "optional",
                "counts": {
                    "dependencies": 0,
                    "dependents": 97000,
                    "modpack_dependents": 60000
                },
                "featured": null
            }
        },
        {
            "relation_type": "optional",
            "name": "Some Addon",
            "curseforge_id": null,
            "modrinth_id": "AbCdEf12",
            "project": null
        }
    ],
    "incompatible": [],
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/dependencies?page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/dependencies?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 2,
        "platform": "modrinth",
        "source": 1234
    }
}
 

Request      

GET api/v2/projects/{project_id}/dependencies

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Query Parameters

platform   string  optional    

curseforge or modrinth. Example: modrinth

source   integer  optional    

A sources[].project_id from "Show a project": read that merged loader-specific listing's own list.

relation_type   string  optional    

required, optional, embedded, tool or include.

sort   string  optional    

downloads_count (default), name, bayesian_rating, average_rating, total_ratings, last_updated_at, published_at. Dependencies ModDex doesn't have sort last.

direction   string  optional    

asc or desc. Defaults to asc for name, desc otherwise.

per_page   integer  optional    

1 to 100. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
relation_type   string     

unknown when the listing gave none; incompatible in the incompatible list only. One of required, optional, embedded, tool, include, unknown, incompatible.

name   string     

The name the listing declared.

curseforge_id   integer|null     

The CurseForge project ID the listing declared.

modrinth_id   string|null     

The Modrinth project ID the listing declared.

project   object|null     

The dependency on ModDex; null when ModDex doesn't have it.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
platform   string|null     

The platform read; null when the project's list doesn't differ by platform. One of curseforge, modrinth.

source   integer     

The ModDex ID of the listing whose list was read.

incompatible   object[]     

Incompatible projects, not paginated.

relation_type   string     

unknown when the listing gave none; incompatible in the incompatible list only. One of required, optional, embedded, tool, include, unknown, incompatible.

name   string     

The name the listing declared.

curseforge_id   integer|null     

The CurseForge project ID the listing declared.

modrinth_id   string|null     

The Modrinth project ID the listing declared.

project   object|null     

The dependency on ModDex; null when ModDex doesn't have it.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

List a project's dependents.

What the project's Dependents tab lists: every project whose own listing declares this one as a dependency (incompatible declarations don't count), including delisted projects (available: false), as the website does. Each row's relation_type is how it depends on this one.

On a project listed on both platforms the list is read one platform at a time, by where the dependent is listed: platform picks which (default: the website's). meta.platform is null when the choice makes no difference.

Pages deeper than page × per_page = 10,000 are a 422.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/dependents?type=modpack" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/dependents"
);

const params = {
    "type": "modpack",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/dependents';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'modpack',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/dependents'
params = {
  'type': 'modpack',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Dependents):


{
    "data": [
        {
            "relation_type": "embedded",
            "project": {
                "id": 5678,
                "name": "Example Pack",
                "slug": "example-pack",
                "type": "modpack",
                "logo_url": "https://media.forgecdn.net/avatars/thumbnails/1/2/64/64/example.png",
                "available": true,
                "rating": {
                    "average": 4,
                    "bayesian": 3.9,
                    "count": 6,
                    "written_count": 2
                },
                "links": {
                    "web": "https://moddex.gg/modpack/example-pack",
                    "reviews": "https://moddex.gg/modpack/example-pack#reviews",
                    "write_review": "https://moddex.gg/modpack/example-pack#review-form",
                    "badge": "https://moddex.gg/badges/projects/example-pack/rating.svg?type=modpack"
                },
                "summary": "A light tech and exploration pack.",
                "downloads_count": 1250000,
                "last_updated_at": "2026-09-12T08:00:00Z",
                "published_at": "2025-03-01T00:00:00Z",
                "curseforge": {
                    "id": 998877,
                    "slug": "example-pack",
                    "url": "https://www.curseforge.com/minecraft/modpacks/example-pack"
                },
                "modrinth": null,
                "minecraft_versions": [
                    "1.21.1"
                ],
                "loaders": [
                    {
                        "slug": "neoforge",
                        "name": "NeoForge"
                    }
                ],
                "genres": [
                    {
                        "slug": "tech",
                        "name": "Tech"
                    }
                ],
                "features": [],
                "themes": [],
                "environment": [],
                "client_side": null,
                "server_side": null,
                "counts": {
                    "dependencies": 142,
                    "dependents": 0,
                    "modpack_dependents": 0
                },
                "featured": null
            }
        }
    ],
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/dependents?type=modpack&page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/dependents?type=modpack&page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 1,
        "platform": "modrinth"
    }
}
 

Request      

GET api/v2/projects/{project_id}/dependents

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Query Parameters

platform   string  optional    

curseforge or modrinth.

type   string  optional    

mod or modpack. Example: modpack

sort   string  optional    

downloads_count (default), name, bayesian_rating, average_rating, total_ratings, last_updated_at, published_at.

direction   string  optional    

asc or desc. Defaults to asc for name, desc otherwise.

per_page   integer  optional    

1 to 50. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
relation_type   string     

How the dependent depends on this project. One of required, optional, embedded, tool, include, unknown.

project   object     
id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
platform   string|null     

The platform read; null when the list doesn't differ by platform. One of curseforge, modrinth.

List a modpack's contents.

The mods a modpack ships, which are its dependencies: the same list, parameters and shape as "List a project's dependencies". A mod is a 404. For the modpacks that contain a mod, use "List a project's dependents" with type=modpack.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/5678/contents" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/5678/contents"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/5678/contents';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/5678/contents'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Contents):


{
    "data": [
        {
            "relation_type": "embedded",
            "name": "Sodium",
            "curseforge_id": null,
            "modrinth_id": "AANobbMI",
            "project": {
                "id": 1234,
                "name": "Sodium",
                "slug": "sodium",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
                "available": true,
                "rating": {
                    "average": 4.8,
                    "bayesian": 4.6,
                    "count": 52,
                    "written_count": 31
                },
                "links": {
                    "web": "https://moddex.gg/mod/sodium",
                    "reviews": "https://moddex.gg/mod/sodium#reviews",
                    "write_review": "https://moddex.gg/mod/sodium#review-form",
                    "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
                },
                "summary": "A modern rendering engine for Minecraft.",
                "downloads_count": 98000000,
                "last_updated_at": "2026-09-30T12:00:00Z",
                "published_at": "2020-01-07T00:00:00Z",
                "curseforge": {
                    "id": 394468,
                    "slug": "sodium",
                    "url": "https://www.curseforge.com/minecraft/mc-mods/sodium"
                },
                "modrinth": {
                    "id": "AANobbMI",
                    "slug": "sodium",
                    "url": "https://modrinth.com/mod/sodium"
                },
                "minecraft_versions": [
                    "1.21.1",
                    "1.20.1"
                ],
                "loaders": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    },
                    {
                        "slug": "neoforge",
                        "name": "NeoForge"
                    }
                ],
                "genres": [
                    {
                        "slug": "no-genre",
                        "name": "No Genre"
                    }
                ],
                "features": [
                    {
                        "slug": "performance-optimization",
                        "name": "Performance & Optimization"
                    }
                ],
                "themes": [],
                "environment": [
                    {
                        "slug": "client-only",
                        "name": "Client Only"
                    }
                ],
                "client_side": "required",
                "server_side": "unsupported",
                "counts": {
                    "dependencies": 0,
                    "dependents": 4200,
                    "modpack_dependents": 3900
                },
                "featured": null
            }
        }
    ],
    "incompatible": [],
    "links": {
        "first": "https://moddex.gg/api/v2/projects/5678/contents?page=1",
        "last": "https://moddex.gg/api/v2/projects/5678/contents?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 20,
        "total": 1,
        "platform": "modrinth",
        "source": 5678
    }
}
 

Example response (404, A mod):


{
    "message": "Not found.",
    "code": "not_found",
    "hint": "Only modpacks have contents. For the modpacks that include this mod, use /api/v2/projects/1234/dependents?type=modpack.",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/projects/{project_id}/contents

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID of a modpack. Example: 5678

Query Parameters

platform   string  optional    

curseforge or modrinth.

source   integer  optional    

A sources[].project_id.

relation_type   string  optional    

required, optional, embedded, tool or include.

sort   string  optional    

As for dependencies.

direction   string  optional    

asc or desc.

per_page   integer  optional    

1 to 100. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
relation_type   string     

unknown when the listing gave none; incompatible in the incompatible list only. One of required, optional, embedded, tool, include, unknown, incompatible.

name   string     

The name the listing declared.

curseforge_id   integer|null     

The CurseForge project ID the listing declared.

modrinth_id   string|null     

The Modrinth project ID the listing declared.

project   object|null     

The dependency on ModDex; null when ModDex doesn't have it.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
platform   string|null     

The platform read; null when the project's list doesn't differ by platform. One of curseforge, modrinth.

source   integer     

The ModDex ID of the listing whose list was read.

incompatible   object[]     

Incompatible projects, not paginated.

relation_type   string     

unknown when the listing gave none; incompatible in the incompatible list only. One of required, optional, embedded, tool, include, unknown, incompatible.

name   string     

The name the listing declared.

curseforge_id   integer|null     

The CurseForge project ID the listing declared.

modrinth_id   string|null     

The Modrinth project ID the listing declared.

project   object|null     

The dependency on ModDex; null when ModDex doesn't have it.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

List similar projects.

The project's Similar tab: up to 100 listed projects of the same type, most similar first, from a list ModDex computes ahead of time.

A newly added project has no list yet: the response is computed: false with an empty data and a Retry-After (seconds). ModDex computes new projects every 15 minutes. Delisted projects aren't computed. They return computed: true, computed_at: null and no Retry-After, since there's nothing to wait for.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/similar" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/similar"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/similar';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/similar'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Computed):


{
    "data": [
        {
            "id": 4321,
            "name": "Embeddium",
            "slug": "embeddium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/sk9rgfiA/icon.png",
            "available": true,
            "rating": {
                "average": 4.5,
                "bayesian": 4.2,
                "count": 12,
                "written_count": 5
            },
            "links": {
                "web": "https://moddex.gg/mod/embeddium",
                "reviews": "https://moddex.gg/mod/embeddium#reviews",
                "write_review": "https://moddex.gg/mod/embeddium#review-form",
                "badge": "https://moddex.gg/badges/projects/embeddium/rating.svg?type=mod"
            },
            "summary": "Rendering optimizations for NeoForge, based on Sodium.",
            "downloads_count": 9800000,
            "last_updated_at": "2026-08-30T10:00:00Z",
            "published_at": "2023-08-01T00:00:00Z",
            "curseforge": {
                "id": 908741,
                "slug": "embeddium",
                "url": "https://www.curseforge.com/minecraft/mc-mods/embeddium"
            },
            "modrinth": {
                "id": "sk9rgfiA",
                "slug": "embeddium",
                "url": "https://modrinth.com/mod/embeddium"
            },
            "minecraft_versions": [
                "1.21.1",
                "1.20.1"
            ],
            "loaders": [
                {
                    "slug": "neoforge",
                    "name": "NeoForge"
                }
            ],
            "genres": [
                {
                    "slug": "no-genre",
                    "name": "No Genre"
                }
            ],
            "features": [
                {
                    "slug": "performance-optimization",
                    "name": "Performance & Optimization"
                }
            ],
            "themes": [],
            "environment": [
                {
                    "slug": "client-only",
                    "name": "Client Only"
                }
            ],
            "client_side": "required",
            "server_side": "unsupported",
            "counts": {
                "dependencies": 0,
                "dependents": 310,
                "modpack_dependents": 300
            },
            "featured": null
        }
    ],
    "computed": true,
    "computed_at": "2026-10-06T03:12:00Z",
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/similar?page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/similar?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 12,
        "total": 1
    }
}
 

Example response (200, Not computed yet):


{
    "data": [],
    "computed": false,
    "computed_at": null,
    "links": {
        "first": "https://moddex.gg/api/v2/projects/1234/similar?page=1",
        "last": "https://moddex.gg/api/v2/projects/1234/similar?page=1",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 12,
        "total": 0
    }
}
 

Request      

GET api/v2/projects/{project_id}/similar

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Query Parameters

per_page   integer  optional    

1 to 50. Default 12.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     

Similar projects, most similar first.

id   integer     

ModDex project ID.

name   string     

Plain text; escape it.

slug   string     

ModDex slug.

type   string     

One of mod, modpack.

logo_url   string     

Absolute https URL; a ModDex placeholder when the project has no logo.

available   boolean     

False when the project is delisted on every platform it was on. Its ModDex page still exists.

rating   object     
average   number|null     

Mean rating, 0.5 to 5 (each rating is a step of 0.5). Null when unrated.

bayesian   number|null     

Bayesian-adjusted rating, which the catalog ranks by. Null when unrated.

count   integer     

Quick ratings plus written reviews.

written_count   integer     

Written reviews only.

links   object     
web   string     

The project page on ModDex.

reviews   string     

The page's Reviews tab.

write_review   string     

Opens the review form.

badge   string     

Rating badge (SVG), for a README.

summary   string|null     

Plain text.

downloads_count   integer     

Downloads across both platforms.

last_updated_at   string|null     

Newest platform update.

published_at   string|null     

Earliest platform creation date.

curseforge   object|null     

Null when the project isn't on CurseForge.

id   integer     
slug   string|null     

Null when the listing URL carries no slug.

url   string|null     

Null while the listing is delisted.

modrinth   object|null     

Null when the project isn't on Modrinth.

id   string     

Modrinth project ID (8 characters, case-sensitive).

slug   string|null     
url   string|null     

Null while the listing is delisted.

minecraft_versions   string[]     

Version strings, newest first.

loaders   object[]     

Mod loaders.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

genres   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

features   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

themes   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

environment   object[]     

Where it installs: client-only, server-only, client-and-server, either-side, …

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

client_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

server_side   string|null     

Deprecated by Modrinth. One of required, optional, unsupported, unknown.

counts   object     
dependencies   integer     

Entries in the dependency lists of both platforms together; a dependency declared on each platform can count twice. /dependencies reads one platform at a time, so its meta.total is usually lower.

dependents   integer     

Projects that depend on this one on either platform, each counted once. /dependents reads one platform at a time (meta.platform), so its meta.total can be lower.

modpack_dependents   integer     

Modpacks that include the project.

featured   object|null     

Staff pick. Null unless featured.

priority   integer|null     

Its slot on the ModDex homepage, lowest first (1 is the large card).

blurb   string|null     

Plain text.

links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     
computed   boolean     

False while a new project waits for its first computation; retry after Retry-After seconds.

computed_at   string|null     

When the list was computed.

List a project's community tags.

The genre, theme and feature tags on the project, as its community tag panel shows them. active is every tag currently applied, pinned tags first, then by name. proposed lists tags the community has suggested but not yet applied, highest score first. A tag that only comes from the platform listing has no community record yet, so its weighted_score and unique_voter_count are null.

The list isn't paginated, since a project has a few dozen tags at most.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/projects/1234/community-tags" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/projects/1234/community-tags"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/projects/1234/community-tags';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/projects/1234/community-tags'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Tags):


{
    "data": {
        "active": [
            {
                "tag": {
                    "id": 12,
                    "slug": "performance-optimization",
                    "name": "Performance & Optimization",
                    "type": "feature"
                },
                "weighted_score": 14,
                "unique_voter_count": 9,
                "pinned": true
            },
            {
                "tag": {
                    "id": 3,
                    "slug": "tech",
                    "name": "Tech",
                    "type": "genre"
                },
                "weighted_score": null,
                "unique_voter_count": null,
                "pinned": false
            }
        ],
        "proposed": [
            {
                "tag": {
                    "id": 40,
                    "slug": "qol-tweaks",
                    "name": "QoL & Tweaks",
                    "type": "feature"
                },
                "weighted_score": 3,
                "unique_voter_count": 2,
                "pinned": false
            }
        ]
    }
}
 

Request      

GET api/v2/projects/{project_id}/community-tags

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_id   integer     

The ModDex project ID. Example: 1234

Response

Response Fields

data   object     
active   object[]     

Applied tags, pinned first, then by name.

tag   object     
id   integer     
slug   string     
name   string     
type   string     

One of genre, theme, feature.

weighted_score   integer|null     

A starting score plus reputation-weighted votes; null when the tag has no community record yet.

unique_voter_count   integer|null     

Distinct voters; null when weighted_score is.

pinned   boolean     

Pinned by the developer or staff.

proposed   object[]     

Suggested, not yet applied; highest score first.

tag   object     
id   integer     
slug   string     
name   string     
type   string     

One of genre, theme, feature.

weighted_score   integer|null     

A starting score plus reputation-weighted votes; null when the tag has no community record yet.

unique_voter_count   integer|null     

Distinct voters; null when weighted_score is.

pinned   boolean     

Pinned by the developer or staff.

Reviews

List reviews.

Every public review on ModDex, newest first: approved written reviews of projects that have a page. Add quick ratings (stars only) with written_only=0. Takes the same filters as a project's review list, plus project_ids, type and since, for "latest reviews" widgets and authors watching their own projects. To post every new review as it appears, follow the reviews sync feed instead.

Text is profanity-masked unless unmasked=1. Pages deeper than page × per_page = 10,000 are a 422.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/reviews" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/reviews"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/reviews'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Reviews):


{
    "data": [
        {
            "id": 77,
            "is_quick_rating": false,
            "title": "Essential",
            "content": "Doubles my FPS.",
            "content_html": "<p>Doubles my FPS.</p>",
            "rating": 5,
            "categories": {
                "gameplay": null,
                "performance": 5,
                "aesthetics": null
            },
            "minecraft_version": "1.21.1",
            "playtime_hours": 300,
            "completion_hours": null,
            "play_status": "playing",
            "pack_version": null,
            "helpful_votes": 12,
            "unhelpful_votes": 0,
            "is_verified_developer": false,
            "public_moderator_note": null,
            "images": [
                {
                    "url": "https://cdn.moddex.gg/review-images/77/1.webp",
                    "caption": null
                }
            ],
            "developer_response": {
                "content": "Thanks!",
                "responded_at": "2026-09-02T09:00:00Z",
                "author": {
                    "id": 3,
                    "name": "jellysquid3",
                    "username": "jellysquid3",
                    "avatar_url": null,
                    "profile_url": "https://moddex.gg/user/jellysquid3",
                    "roles": [],
                    "reputation": {
                        "points": 10,
                        "tier": "explorer",
                        "tier_label": "Explorer"
                    }
                }
            },
            "author": {
                "id": 9,
                "name": "Steve",
                "username": "steve",
                "avatar_url": "https://cdn.moddex.gg/avatars/9-96.webp",
                "profile_url": "https://moddex.gg/user/steve",
                "roles": [
                    "moderator"
                ],
                "reputation": {
                    "points": 420,
                    "tier": "contributor",
                    "tier_label": "Contributor"
                }
            },
            "project": {
                "id": 1234,
                "name": "Sodium",
                "slug": "sodium",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
                "available": true,
                "rating": {
                    "average": 4.8,
                    "bayesian": 4.6,
                    "count": 52,
                    "written_count": 31
                },
                "links": {
                    "web": "https://moddex.gg/mod/sodium",
                    "reviews": "https://moddex.gg/mod/sodium#reviews",
                    "write_review": "https://moddex.gg/mod/sodium#review-form",
                    "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
                }
            },
            "url": "https://moddex.gg/mod/sodium/reviews/77",
            "created_at": "2026-09-01T10:00:00Z",
            "edited_at": null,
            "updated_at": "2026-09-02T09:00:00Z"
        }
    ],
    "links": {
        "first": "https://moddex.gg/api/v2/reviews?page=1",
        "last": "https://moddex.gg/api/v2/reviews?page=94",
        "prev": null,
        "next": "https://moddex.gg/api/v2/reviews?page=2"
    },
    "meta": {
        "current_page": 1,
        "last_page": 94,
        "per_page": 20,
        "total": 1869
    }
}
 

Request      

GET api/v2/reviews

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

project_ids   string  optional    

Up to 50 comma-separated ModDex project IDs. A merged listing's ID means its project's reviews.

type   string  optional    

mod or modpack.

since   string  optional    

Written at or after: an ISO 8601 date (midnight UTC) or a date-time with a time zone. A review held for moderation keeps its writing date when it is approved, so to catch every newly public review, follow the reviews sync feed instead.

written_only   boolean  optional    

Default true. False adds quick ratings.

sort   string  optional    

newest (default), oldest, rating or helpful.

min_rating   number  optional    

From 0.5 to 5.

max_rating   number  optional    

From 0.5 to 5.

minecraft_versions   string  optional    

Comma-separated versions the reviewer played; 1.20 matches every 1.20.x.

play_statuses   string  optional    

Comma-separated: playing, played, completed, on_hold, dropped.

playtime_min   integer  optional    

Minimum hours played.

media   string  optional    

all (default), with_images or text_only.

verified_only   boolean  optional    

Only reviews by the project's verified developers.

has_developer_response   boolean  optional    

Only reviews the developer answered.

pack_version   string  optional    

Comma-separated pack versions, matched exactly.

unmasked   boolean  optional    

Return text without profanity masking.

per_page   integer  optional    

1 to 50. Default 20.

page   integer  optional    

Default 1.

Response

Response Fields

data   object[]     
id   integer     
is_quick_rating   boolean     

Stars only: no title or text.

title   string|null     

Plain text.

content   string|null     

The Markdown the author wrote. Plain text: escape it.

content_html   string|null     

Sanitized HTML. Spoilers are wrapped in <span data-spoiler>.

rating   number     

0.5 to 5 in steps of 0.5.

categories   object     

Each 0.5 to 5, or null when not rated.

gameplay   number|null     
performance   number|null     
aesthetics   number|null     
minecraft_version   string|null     

As the reviewer entered it; may list several, comma-separated.

playtime_hours   integer|null     
completion_hours   integer|null     
play_status   string|null     

One of playing, played, completed, plan_to_play, on_hold, dropped.

pack_version   string|null     

The modpack version reviewed.

helpful_votes   integer     
unhelpful_votes   integer     
is_verified_developer   boolean     

Written by one of the project's verified developers.

public_moderator_note   string|null     

Plain text.

images   object[]     
url   string     
caption   string|null     

Plain text.

developer_response   object|null     

The developer's reply, if any.

content   string     

Plain text.

responded_at   string|null     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
project   object     

The project summary: id, name, slug, type, logo_url, available, rating and links.

url   string|null     

The review's page on ModDex.

created_at   string|null     
edited_at   string|null     
updated_at   string|null     
links   object     
first   string     
last   string     
prev   string|null     
next   string|null     
meta   object     
current_page   integer     
last_page   integer     
per_page   integer     
total   integer     

Show a review.

One approved review, written or a quick rating (stars only). Pending, rejected and deleted reviews, and reviews of a project that no longer has a page, are 404.

Text is profanity-masked unless unmasked=1.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/reviews/77" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/reviews/77"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/reviews/77';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/reviews/77'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Found):


{
    "data": {
        "id": 77,
        "is_quick_rating": false,
        "title": "Essential",
        "content": "Doubles my FPS.",
        "content_html": "<p>Doubles my FPS.</p>",
        "rating": 5,
        "categories": {
            "gameplay": null,
            "performance": 5,
            "aesthetics": null
        },
        "minecraft_version": "1.21.1",
        "playtime_hours": 300,
        "completion_hours": null,
        "play_status": "playing",
        "pack_version": null,
        "helpful_votes": 12,
        "unhelpful_votes": 0,
        "is_verified_developer": false,
        "public_moderator_note": null,
        "images": [
            {
                "url": "https://cdn.moddex.gg/review-images/77/1.webp",
                "caption": null
            }
        ],
        "developer_response": {
            "content": "Thanks!",
            "responded_at": "2026-09-02T09:00:00Z",
            "author": {
                "id": 3,
                "name": "jellysquid3",
                "username": "jellysquid3",
                "avatar_url": null,
                "profile_url": "https://moddex.gg/user/jellysquid3",
                "roles": [],
                "reputation": {
                    "points": 10,
                    "tier": "explorer",
                    "tier_label": "Explorer"
                }
            }
        },
        "author": {
            "id": 9,
            "name": "Steve",
            "username": "steve",
            "avatar_url": "https://cdn.moddex.gg/avatars/9-96.webp",
            "profile_url": "https://moddex.gg/user/steve",
            "roles": [
                "moderator"
            ],
            "reputation": {
                "points": 420,
                "tier": "contributor",
                "tier_label": "Contributor"
            }
        },
        "project": {
            "id": 1234,
            "name": "Sodium",
            "slug": "sodium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
            "available": true,
            "rating": {
                "average": 4.8,
                "bayesian": 4.6,
                "count": 52,
                "written_count": 31
            },
            "links": {
                "web": "https://moddex.gg/mod/sodium",
                "reviews": "https://moddex.gg/mod/sodium#reviews",
                "write_review": "https://moddex.gg/mod/sodium#review-form",
                "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
            }
        },
        "url": "https://moddex.gg/mod/sodium/reviews/77",
        "created_at": "2026-09-01T10:00:00Z",
        "edited_at": null,
        "updated_at": "2026-09-02T09:00:00Z"
    }
}
 

Example response (404, Not public):


{
    "message": "Not found.",
    "code": "not_found",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/reviews/{id}

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The review ID. Example: 77

Query Parameters

unmasked   boolean  optional    

Return text without profanity masking.

Response

Response Fields

data   object     
id   integer     
is_quick_rating   boolean     

Stars only: no title or text.

title   string|null     

Plain text.

content   string|null     

The Markdown the author wrote. Plain text: escape it.

content_html   string|null     

Sanitized HTML. Spoilers are wrapped in <span data-spoiler>.

rating   number     

0.5 to 5 in steps of 0.5.

categories   object     

Each 0.5 to 5, or null when not rated.

gameplay   number|null     
performance   number|null     
aesthetics   number|null     
minecraft_version   string|null     

As the reviewer entered it; may list several, comma-separated.

playtime_hours   integer|null     
completion_hours   integer|null     
play_status   string|null     

One of playing, played, completed, plan_to_play, on_hold, dropped.

pack_version   string|null     

The modpack version reviewed.

helpful_votes   integer     
unhelpful_votes   integer     
is_verified_developer   boolean     

Written by one of the project's verified developers.

public_moderator_note   string|null     

Plain text.

images   object[]     
url   string     
caption   string|null     

Plain text.

developer_response   object|null     

The developer's reply, if any.

content   string     

Plain text.

responded_at   string|null     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
project   object     

The project summary: id, name, slug, type, logo_url, available, rating and links.

url   string|null     

The review's page on ModDex.

created_at   string|null     
edited_at   string|null     
updated_at   string|null     

Catalog vocabulary

The values /v2/projects filters accept, for building a filter UI or validating input. The lists are small and rarely change, so cache them (responses are max-age=3600).

List the catalog filters.

Every /v2/projects parameter, with:

Also every sort with its default direction, and the paging limits. Minecraft versions are listed by /v2/minecraft-versions; minecraft_version_groups are the values mc_exact=0 takes.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/catalog/filters" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/catalog/filters"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/catalog/filters';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/catalog/filters'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "parameters": [
            {
                "name": "q",
                "type": "string",
                "list": false,
                "values": null,
                "description": "Full-text search, 3 to 200 characters. Returns at most 1000 matches."
            },
            {
                "name": "loaders",
                "type": "slug",
                "list": true,
                "max_values": 50,
                "exclude_parameter": "loaders_exclude",
                "mode_parameter": null,
                "values": [
                    {
                        "slug": "fabric",
                        "name": "Fabric"
                    },
                    {
                        "slug": "neoforge",
                        "name": "NeoForge"
                    }
                ],
                "description": "Mod loader slugs. With `minecraft_versions`, one file must carry both the loader and the version."
            },
            {
                "name": "featured",
                "type": "boolean",
                "list": false,
                "min": null,
                "max": null,
                "values": null,
                "description": "Only staff picks."
            }
        ],
        "modes": [
            "any",
            "all"
        ],
        "minecraft_version_groups": [
            "1.21",
            "1.20",
            "pre-1.7"
        ],
        "sorts": [
            {
                "sort": "relevance",
                "default_direction": "desc"
            },
            {
                "sort": "bayesian_rating",
                "default_direction": "desc"
            },
            {
                "sort": "name",
                "default_direction": "asc"
            }
        ],
        "default_sort": "bayesian_rating",
        "default_sort_with_q": "relevance",
        "per_page": {
            "default": 20,
            "max": 50
        },
        "max_page_depth": 10000
    }
}
 

Request      

GET api/v2/catalog/filters

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Response

Response Fields

data   object     
parameters   object[]     

One entry per /v2/projects parameter.

name   string     
type   string     

boolean takes 1/0/true/false; date takes ISO 8601. One of string, enum, slug, minecraft_version, project_id, boolean, number, integer, date.

list   boolean     

Takes a comma-separated list.

max_values   integer     

List parameters: the most values one request may send.

exclude_parameter   string|null     

List parameters: the _exclude twin, if any.

mode_parameter   string|null     

List parameters: the any/all companion, if any.

min   number|null     

Scalar parameters.

max   number|null     

Scalar parameters.

values   object[]|null     

Every valid value; null when the vocabulary isn't listed here.

slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

description   string     
modes   string[]     

Values the *_mode parameters take. One of any, all.

minecraft_version_groups   string[]     

Version groups for mc_exact=0, newest first.

sorts   object[]     
sort   string     
default_direction   string     

One of asc, desc.

default_sort   string     
default_sort_with_q   string     
per_page   object     
default   integer     
max   integer     
max_page_depth   integer     

page × per_page may not exceed this.

List Minecraft versions.

Every version the catalog knows, newest first. Each version is a valid minecraft_versions filter value.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/minecraft-versions?type=release" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/minecraft-versions"
);

const params = {
    "type": "release",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/minecraft-versions';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'release',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/minecraft-versions'
params = {
  'type': 'release',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "version": "1.21.1",
            "type": "release",
            "released_at": "2024-08-08"
        },
        {
            "version": "24w33a",
            "type": "snapshot",
            "released_at": "2024-08-15"
        }
    ]
}
 

Request      

GET api/v2/minecraft-versions

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Only this release type, such as release or snapshot. Example: release

Response

Response Fields

data   object[]     

Newest first.

version   string     

What filters and project responses use.

type   string     

Release type, such as release or snapshot.

released_at   string|null     

Release date (ISO 8601 date), when known.

List mod loaders.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/loaders" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/loaders"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/loaders';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/loaders'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "slug": "fabric",
            "name": "Fabric"
        },
        {
            "slug": "forge",
            "name": "Forge"
        },
        {
            "slug": "neoforge",
            "name": "NeoForge"
        },
        {
            "slug": "quilt",
            "name": "Quilt"
        }
    ]
}
 

Request      

GET api/v2/loaders

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Response

Response Fields

data   object[]     
slug   string     

What the matching /v2/projects filter takes.

name   string     

Display name.

List tags.

Genres, features, themes and environments: every value the matching /v2/projects filter takes. Not paginated.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/tags?type=genre" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/tags"
);

const params = {
    "type": "genre",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/tags';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'genre',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/tags'
params = {
  'type': 'genre',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "slug": "tech",
            "name": "Tech",
            "type": "genre",
            "description": "Focuses on automation and resource processing through scientific and mechanical means, utilizing systems like electricity (RF/FE/etc), air pressure, or rotation.",
            "category": null
        },
        {
            "slug": "storage-organization",
            "name": "Storage & Organization",
            "type": "feature",
            "description": "Features systems for better item storage and organization.",
            "category": "QoL & Utility"
        }
    ]
}
 

Request      

GET api/v2/tags

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

genre, feature, theme or environment. Example: genre

Response

Response Fields

data   object[]     
slug   string     

What the matching filter (genres, features, themes, environment) takes.

name   string     
type   string     

One of genre, feature, theme, environment.

description   string|null     

Plain text.

category   string|null     

The group a feature is listed under; null for other types.

Sync

Follow what changes on ModDex, for example to post new reviews or to keep the projects you show up to date. Each feed lists changes oldest first and is read forward with a cursor.

  1. Start with since (changes at or after that time).
  2. Follow meta.next_cursor (or links.next) while meta.has_more is true.
  3. Store the last next_cursor, and pass it again later to get what changed since. On the last page links.next is null, but next_cursor is still set.

A cursor carries its since, so don't send both. A cursor that has been edited, or belongs to the other feed, is a 422 with code: invalid_cursor; start over without it.

Delivery is at least once. A row that changes again while you read comes round again, so apply rows by id. A change reaches the feed 5 minutes after it's made, so nothing that commits late is skipped. Responses are cached for up to 5 minutes as well, so allow 10 minutes in total.

Sync projects.

Every project change in order. Each row is one of:

If you store projects, delete a tombstoned one and its reviews.

Tag, loader and Minecraft version changes bump a project back into the feed. Rating, download and other counts change often, so expect popular projects to come round regularly.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/sync/projects?since=2026-10-01T00%3A00%3A00Z" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/sync/projects"
);

const params = {
    "since": "2026-10-01T00:00:00Z",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/sync/projects';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'since' => '2026-10-01T00:00:00Z',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/sync/projects'
params = {
  'since': '2026-10-01T00:00:00Z',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, A live row and two tombstones):


{
    "data": [
        {
            "id": 1234,
            "name": "Sodium",
            "slug": "sodium",
            "type": "mod",
            "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
            "available": true,
            "rating": {
                "average": 4.8,
                "bayesian": 4.6,
                "count": 52,
                "written_count": 31
            },
            "links": {
                "web": "https://moddex.gg/mod/sodium",
                "reviews": "https://moddex.gg/mod/sodium#reviews",
                "write_review": "https://moddex.gg/mod/sodium#review-form",
                "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
            },
            "summary": "A modern rendering engine for Minecraft.",
            "downloads_count": 98000000,
            "last_updated_at": "2026-09-30T12:00:00Z",
            "published_at": "2020-01-07T00:00:00Z",
            "curseforge": {
                "id": 394468,
                "slug": "sodium",
                "url": "https://www.curseforge.com/minecraft/mc-mods/sodium"
            },
            "modrinth": {
                "id": "AANobbMI",
                "slug": "sodium",
                "url": "https://modrinth.com/mod/sodium"
            },
            "minecraft_versions": [
                "1.21.1"
            ],
            "loaders": [
                {
                    "slug": "fabric",
                    "name": "Fabric"
                }
            ],
            "genres": [],
            "features": [
                {
                    "slug": "performance-optimization",
                    "name": "Performance & Optimization"
                }
            ],
            "themes": [],
            "environment": [
                {
                    "slug": "client-only",
                    "name": "Client Only"
                }
            ],
            "client_side": "required",
            "server_side": "unsupported",
            "counts": {
                "dependencies": 0,
                "dependents": 4200,
                "modpack_dependents": 3900
            },
            "featured": null
        },
        {
            "id": 5678,
            "removed": true,
            "reason": "merged",
            "canonical_id": 1234
        },
        {
            "id": 9012,
            "removed": true,
            "reason": "deleted"
        }
    ],
    "links": {
        "next": "https://moddex.gg/api/v2/sync/projects?cursor=eyJmZWVkIjoicHJvamVjdHMi",
        "prev": null
    },
    "meta": {
        "per_page": 100,
        "next_cursor": "eyJmZWVkIjoicHJvamVjdHMi",
        "prev_cursor": null,
        "has_more": true
    }
}
 

Example response (422, Edited cursor):


{
    "message": "The cursor is invalid.",
    "code": "invalid_cursor",
    "hint": "Pass back a next_cursor exactly as a response gave it, to the same feed. To start over, omit cursor.",
    "docs_url": "https://moddex.gg/api/docs"
}
 

Request      

GET api/v2/sync/projects

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

since   string  optional    

Only changes at or after this time: an ISO 8601 date (midnight UTC) or a date-time with a time zone. Omit it to start from the oldest change. Example: 2026-10-01T00:00:00Z

cursor   string  optional    

meta.next_cursor from the previous page.

per_page   integer  optional    

1 to 100. Default 100.

Response

Response Fields

data   object[]     

Live rows in the list shape, or tombstones: tell them apart by removed.

id   integer     
removed   boolean     

Present, and true, only on a tombstone.

reason   string     

One of deleted, merged.

canonical_id   integer     

With reason: merged: the project this listing was merged into.

links   object     
next   string|null     

This feed continued from next_cursor; null once has_more is false (keep next_cursor to poll later).

prev   null     

The feeds only go forward.

meta   object     
per_page   integer     
next_cursor   string     

Always set. On the last page it points just past the last row, ready to poll with later.

prev_cursor   null     

The feeds only go forward.

has_more   boolean     

True when more rows are ready now.

Sync reviews.

Every public written review that changed, in order, in the review shape (as in "Show a review"). Quick ratings (stars only) count toward each project's rating but aren't in this feed.

This feed has no tombstones. A review leaves ModDex when it is unapproved, deleted, its author deletes their account, or its project is removed, and some of those leave no trace to send. If you store reviews, check them against "List public review IDs" at least daily and delete every one it doesn't list. A project tombstone in the projects feed removes that project's reviews too.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/sync/reviews?since=2026-10-01T00%3A00%3A00Z" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/sync/reviews"
);

const params = {
    "since": "2026-10-01T00:00:00Z",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/sync/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'since' => '2026-10-01T00:00:00Z',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/sync/reviews'
params = {
  'since': '2026-10-01T00:00:00Z',
}
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Reviews):


{
    "data": [
        {
            "id": 77,
            "is_quick_rating": false,
            "title": "Essential",
            "content": "Doubles my FPS.",
            "content_html": "<p>Doubles my FPS.</p>",
            "rating": 5,
            "categories": {
                "gameplay": null,
                "performance": 5,
                "aesthetics": null
            },
            "minecraft_version": "1.21.1",
            "playtime_hours": 300,
            "completion_hours": null,
            "play_status": "playing",
            "pack_version": null,
            "helpful_votes": 12,
            "unhelpful_votes": 0,
            "is_verified_developer": false,
            "public_moderator_note": null,
            "images": [],
            "developer_response": null,
            "author": {
                "id": 9,
                "name": "Steve",
                "username": "steve",
                "avatar_url": null,
                "profile_url": "https://moddex.gg/user/steve",
                "roles": [],
                "reputation": {
                    "points": 420,
                    "tier": "contributor",
                    "tier_label": "Contributor"
                }
            },
            "project": {
                "id": 1234,
                "name": "Sodium",
                "slug": "sodium",
                "type": "mod",
                "logo_url": "https://cdn.modrinth.com/data/AANobbMI/icon.png",
                "available": true,
                "rating": {
                    "average": 4.8,
                    "bayesian": 4.6,
                    "count": 52,
                    "written_count": 31
                },
                "links": {
                    "web": "https://moddex.gg/mod/sodium",
                    "reviews": "https://moddex.gg/mod/sodium#reviews",
                    "write_review": "https://moddex.gg/mod/sodium#review-form",
                    "badge": "https://moddex.gg/badges/projects/sodium/rating.svg?type=mod"
                }
            },
            "url": "https://moddex.gg/mod/sodium/reviews/77",
            "created_at": "2026-09-01T10:00:00Z",
            "edited_at": null,
            "updated_at": "2026-09-01T10:00:00Z"
        }
    ],
    "links": {
        "next": null,
        "prev": null
    },
    "meta": {
        "per_page": 50,
        "next_cursor": "eyJmZWVkIjoicmV2aWV3cyJ9",
        "prev_cursor": null,
        "has_more": false
    }
}
 

Request      

GET api/v2/sync/reviews

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

since   string  optional    

Only changes at or after this time: an ISO 8601 date (midnight UTC) or a date-time with a time zone. Omit it to start from the oldest change. Example: 2026-10-01T00:00:00Z

cursor   string  optional    

meta.next_cursor from the previous page.

per_page   integer  optional    

1 to 50. Default 50.

unmasked   boolean  optional    

Return text without profanity masking.

Response

Response Fields

data   object[]     

author and project are as of this response; their own changes don't bump a review.

id   integer     
is_quick_rating   boolean     

Stars only: no title or text.

title   string|null     

Plain text.

content   string|null     

The Markdown the author wrote. Plain text: escape it.

content_html   string|null     

Sanitized HTML. Spoilers are wrapped in <span data-spoiler>.

rating   number     

0.5 to 5 in steps of 0.5.

categories   object     

Each 0.5 to 5, or null when not rated.

gameplay   number|null     
performance   number|null     
aesthetics   number|null     
minecraft_version   string|null     

As the reviewer entered it; may list several, comma-separated.

playtime_hours   integer|null     
completion_hours   integer|null     
play_status   string|null     

One of playing, played, completed, plan_to_play, on_hold, dropped.

pack_version   string|null     

The modpack version reviewed.

helpful_votes   integer     
unhelpful_votes   integer     
is_verified_developer   boolean     

Written by one of the project's verified developers.

public_moderator_note   string|null     

Plain text.

images   object[]     
url   string     
caption   string|null     

Plain text.

developer_response   object|null     

The developer's reply, if any.

content   string     

Plain text.

responded_at   string|null     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
author   object     
id   integer|null     

Null for a deleted account.

name   string     

"Deleted User" for a deleted account.

username   string|null     
avatar_url   string|null     
profile_url   string|null     
roles   string[]     

The staff badge the profile shows, if any. One of admin, moderator, tag_curator.

reputation   object|null     

Null for a deleted account.

points   integer     
tier   string     
tier_label   string     
project   object     

The project summary: id, name, slug, type, logo_url, available, rating and links.

url   string|null     

The review's page on ModDex.

created_at   string|null     
edited_at   string|null     
updated_at   string|null     
links   object     
next   string|null     

This feed continued from next_cursor; null once has_more is false (keep next_cursor to poll later).

prev   null     

The feeds only go forward.

meta   object     
per_page   integer     
next_cursor   string     

Always set. On the last page it points just past the last row, ready to poll with later.

prev_cursor   null     

The feeds only go forward.

has_more   boolean     

True when more rows are ready now.

List public review IDs.

The ID of every review the reviews feed would serve right now, ascending, unpaginated. If you store reviews, delete any that isn't listed. Refreshed every 5 minutes.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2/sync/reviews/ids" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2/sync/reviews/ids"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2/sync/reviews/ids';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2/sync/reviews/ids'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, IDs):


{
    "data": [
        3,
        77,
        104
    ]
}
 

Request      

GET api/v2/sync/reviews/ids

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Response

Response Fields

data   integer[]     

Review IDs, ascending.

API root.

Identifies the API version and links to the documentation. Every caller gets the same response. Your rate-limit details are in the X-RateLimit-* headers, not the body.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v2" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v2"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v2';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v2'
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "name": "ModDex API",
        "version": "v2",
        "docs_url": "https://moddex.gg/api/docs"
    }
}
 

Request      

GET api/v2

Headers

Content-Type        

Example: application/json

Accept        

Example: application/json

Response

Response Fields

data   object     
name   string     
version   string     
docs_url   string     

v1 (deprecated)

Deprecated: frozen, token-only, and switched off six months after v2 becomes generally available. See "Migrating from v1".

User

Endpoints for the authenticated API token holder.

Show the authenticated user.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns the profile for the user associated with the current Sanctum token, including reputation rank, social links, and privacy settings for library, follows, and user-directory visibility.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/user" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/user"
);

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/user';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/user'
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "id": 1,
        "name": "Steve",
        "username": "steve",
        "email": "[email protected]",
        "email_verified_at": "2026-01-15T12:00:00+00:00",
        "bio": "Minecraft mod enthusiast.",
        "avatar_url": "https://moddex.gg/storage/avatars/1.png",
        "rank": "contributor",
        "social_links": {
            "curseforge": null,
            "modrinth": "https://modrinth.com/user/steve",
            "github": "https://github.com/steve",
            "discord_username": "steve#0001",
            "discord_server": null,
            "reddit": null,
            "x": null,
            "bluesky": null
        },
        "library_is_public": true,
        "follows_is_public": false,
        "user_directory_is_public": true,
        "two_factor_enabled": false,
        "created_at": "2025-06-01T00:00:00+00:00"
    }
}
 

Example response (401, Unauthenticated):


{
    "message": "Unauthenticated."
}
 

Example response (403, Missing read ability):


{
    "message": "Invalid ability provided."
}
 

Example response (403, Unverified email):


{
    "message": "Your email address is not verified."
}
 

Request      

GET api/user

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

Projects

Endpoints for browsing and viewing Minecraft mods and modpacks.

List projects.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns a paginated list of active Minecraft mods and modpacks with community ratings, download counts, taxonomy tags, and supported Minecraft versions. Use type to filter mods vs modpacks, sort to rank by rating or popularity, and featured to surface editor picks.

bayesian_rating adjusts for review count. Projects with few reviews are pulled toward the site-wide average, preventing a single 5-star review from outranking a project with hundreds of reviews.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/projects?type=mod&sort=average_rating&direction=desc&featured=1&per_page=15" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/projects"
);

const params = {
    "type": "mod",
    "sort": "average_rating",
    "direction": "desc",
    "featured": "1",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/projects';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'mod',
            'sort' => 'average_rating',
            'direction' => 'desc',
            'featured' => '1',
            'per_page' => '15',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/projects'
params = {
  'type': 'mod',
  'sort': 'average_rating',
  'direction': 'desc',
  'featured': '1',
  'per_page': '15',
}
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "id": 1,
            "name": "Create",
            "slug": "create",
            "summary": "Aesthetic Technology that empowers the Player",
            "type": "mod",
            "logo_url": "https://...",
            "average_rating": 4.5,
            "bayesian_rating": 4.2,
            "total_ratings": 12,
            "total_reviews": 8,
            "written_reviews_count": 8,
            "downloads_count": 500000,
            "minecraft_versions": [
                "1.20.1",
                "1.21.1"
            ],
            "mod_loaders": [
                "Forge",
                "NeoForge"
            ],
            "genres": [
                "Tech"
            ],
            "last_updated_at": "2026-03-15T00:00:00+00:00"
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": "..."
    },
    "meta": {
        "current_page": 1,
        "last_page": 5,
        "per_page": 15,
        "total": 72
    }
}
 

Request      

GET api/v1/projects

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Filter by project type (mod or modpack). Example: mod

sort   string  optional    

Sort field (name, average_rating, bayesian_rating, total_ratings, total_reviews, downloads_count, last_updated_at). total_ratings and total_reviews both rank by total ratings (quick ratings plus written reviews). last_updated_at ranks by the newer of the CurseForge and Modrinth update dates. Default: name. Example: average_rating

direction   string  optional    

Sort direction (asc or desc). Default: desc. Example: desc

featured   boolean  optional    

Return only featured projects. Example: true

per_page   integer  optional    

Results per page (max 50). Default: 15. Example: 15

Show a mod.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns full details for a single mod, including category ratings (gameplay, performance, aesthetics), platform-specific data from CurseForge and Modrinth (descriptions, authors, screenshots, download counts), taxonomy tags (genres, features, themes), and external links.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/mods/create" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/mods/create"
);

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/mods/create';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/mods/create'
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "id": 1,
        "name": "Create",
        "slug": "create",
        "summary": "Aesthetic Technology that empowers the Player",
        "type": "mod",
        "logo_url": "https://...",
        "license": "Create Mod License",
        "average_rating": 4.5,
        "gameplay_rating": 4,
        "performance_rating": 4.5,
        "aesthetics_rating": 5,
        "total_ratings": 12,
        "total_reviews": 8,
        "written_reviews_count": 8,
        "downloads_count": 500000,
        "minecraft_versions": [
            "1.20.1",
            "1.21.1"
        ],
        "mod_loaders": [
            "Forge",
            "NeoForge"
        ],
        "genres": [
            "Tech"
        ],
        "features": [
            "Automation & Processing",
            "Building Improvements",
            "Redstone Improvements"
        ],
        "themes": [
            "Industrial",
            "Steampunk/Dieselpunk"
        ],
        "platform_urls": {
            "curseforge": "https://...",
            "modrinth": null,
            "source": null,
            "issues": null,
            "wiki": null,
            "discord": null
        },
        "curseforge": {
            "id": 328085,
            "description": "<p>Full HTML description...</p>",
            "authors": [
                {
                    "name": "simibubi",
                    "url": null
                }
            ],
            "screenshots": [],
            "downloads_count": 500000,
            "updated_at": "2026-03-15T00:00:00+00:00",
            "created_at": "2023-01-01T00:00:00+00:00",
            "delisted_at": null
        },
        "modrinth": null,
        "last_updated_at": "2026-03-15T00:00:00+00:00",
        "curseforge_created_at": "2023-01-01T00:00:00+00:00"
    }
}
 

Example response (404, Not Found):


{
    "message": "Not Found"
}
 

Request      

GET api/v1/mods/{project_slug}

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_slug   string     

The mod slug. Example: create

List mod reviews.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns paginated written reviews for a mod. Only approved, published reviews with written content are included. Quick ratings (star-only, no text) and pending/rejected reviews are excluded. Each review includes category ratings, the author's Minecraft version and playtime context, and community vote counts.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/mods/create/reviews?sort=created_at&direction=desc&per_page=15" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/mods/create/reviews"
);

const params = {
    "sort": "created_at",
    "direction": "desc",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/mods/create/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'sort' => 'created_at',
            'direction' => 'desc',
            'per_page' => '15',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/mods/create/reviews'
params = {
  'sort': 'created_at',
  'direction': 'desc',
  'per_page': '15',
}
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "id": 1,
            "is_quick_rating": false,
            "title": "Amazing mod!",
            "content": "This mod completely changed how I play Minecraft...",
            "rating": 4.5,
            "gameplay_rating": 4,
            "performance_rating": 4.5,
            "aesthetics_rating": 5,
            "minecraft_version": "1.20.1",
            "playtime_hours": 500,
            "play_status": "completed",
            "pack_version": null,
            "helpful_votes": 5,
            "unhelpful_votes": 0,
            "is_verified_developer": false,
            "author": {
                "id": 1,
                "name": "Steve"
            },
            "project": {
                "id": 1,
                "name": "Create",
                "slug": "create",
                "type": "mod"
            },
            "created_at": "2026-03-01T00:00:00+00:00",
            "edited_at": null,
            "public_moderator_note": null
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": "..."
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 15,
        "total": 3
    }
}
 

Request      

GET api/v1/mods/{project_slug}/reviews

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_slug   string     

The mod slug. Example: create

Query Parameters

sort   string  optional    

Sort field (created_at, rating, helpful_votes, unhelpful_votes). Default: created_at. Example: created_at

direction   string  optional    

Sort direction (asc or desc). Default: desc. Example: desc

per_page   integer  optional    

Results per page (max 50). Default: 15. Example: 15

Show a modpack.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns full details for a single modpack, including category ratings (gameplay, performance, aesthetics), platform-specific data from CurseForge and Modrinth (descriptions, authors, screenshots, download counts), taxonomy tags (genres, features, themes), and external links.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/modpacks/rlcraft" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/modpacks/rlcraft"
);

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/modpacks/rlcraft';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/modpacks/rlcraft'
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "id": 42,
        "name": "RLCraft",
        "slug": "rlcraft",
        "summary": "A hardcore survival modpack.",
        "type": "modpack",
        "logo_url": "https://...",
        "license": "All Rights Reserved",
        "average_rating": 4.7,
        "gameplay_rating": 4.8,
        "performance_rating": 4.2,
        "aesthetics_rating": 4.5,
        "total_ratings": 230,
        "total_reviews": 95,
        "written_reviews_count": 95,
        "downloads_count": 25000000,
        "minecraft_versions": [
            "1.12.2"
        ],
        "mod_loaders": [
            "Forge"
        ],
        "genres": [
            "Adventure/Exploration",
            "Survival",
            "RPG",
            "Magic"
        ],
        "features": [
            "Difficulty: Challenging",
            "Realism & Immersion",
            "Dragons",
            "Combat Focused"
        ],
        "themes": [
            "Fantasy",
            "Medieval"
        ],
        "platform_urls": {
            "curseforge": "https://...",
            "modrinth": null,
            "source": null,
            "issues": null,
            "wiki": null,
            "discord": null
        },
        "curseforge": {
            "id": 285109,
            "description": "<p>Full HTML description...</p>",
            "authors": [
                {
                    "name": "Shivaxi",
                    "url": null
                }
            ],
            "screenshots": [],
            "downloads_count": 25000000,
            "updated_at": "2026-03-15T00:00:00+00:00",
            "created_at": "2019-01-01T00:00:00+00:00",
            "delisted_at": null
        },
        "modrinth": null,
        "last_updated_at": "2026-03-15T00:00:00+00:00",
        "curseforge_created_at": "2019-01-01T00:00:00+00:00"
    }
}
 

Example response (404, Not Found):


{
    "message": "Not Found"
}
 

Request      

GET api/v1/modpacks/{project_slug}

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_slug   string     

The modpack slug. Example: rlcraft

List modpack reviews.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns paginated written reviews for a modpack. Only approved, published reviews with written content are included. Quick ratings (star-only, no text) and pending/rejected reviews are excluded. Each review includes category ratings, the author's Minecraft version and playtime context, and community vote counts.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/modpacks/rlcraft/reviews?sort=created_at&direction=desc&per_page=15" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/modpacks/rlcraft/reviews"
);

const params = {
    "sort": "created_at",
    "direction": "desc",
    "per_page": "15",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/modpacks/rlcraft/reviews';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'sort' => 'created_at',
            'direction' => 'desc',
            'per_page' => '15',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/modpacks/rlcraft/reviews'
params = {
  'sort': 'created_at',
  'direction': 'desc',
  'per_page': '15',
}
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "id": 7,
            "is_quick_rating": false,
            "title": "Brutal but rewarding",
            "content": "RLCraft is the hardest modpack I've ever played...",
            "rating": 4.5,
            "gameplay_rating": 4.8,
            "performance_rating": 4,
            "aesthetics_rating": 4.5,
            "minecraft_version": "1.12.2",
            "playtime_hours": 320,
            "play_status": "completed",
            "pack_version": "2.9.3",
            "helpful_votes": 18,
            "unhelpful_votes": 1,
            "is_verified_developer": false,
            "author": {
                "id": 1,
                "name": "Steve"
            },
            "project": {
                "id": 42,
                "name": "RLCraft",
                "slug": "rlcraft",
                "type": "modpack"
            },
            "created_at": "2026-03-01T00:00:00+00:00",
            "edited_at": null,
            "public_moderator_note": null
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": "..."
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 15,
        "total": 3
    }
}
 

Request      

GET api/v1/modpacks/{project_slug}/reviews

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

project_slug   string     

The modpack slug. Example: rlcraft

Query Parameters

sort   string  optional    

Sort field (created_at, rating, helpful_votes, unhelpful_votes). Default: created_at. Example: created_at

direction   string  optional    

Sort direction (asc or desc). Default: desc. Example: desc

per_page   integer  optional    

Results per page (max 50). Default: 15. Example: 15

Reviews

Endpoints for browsing community reviews.

Show a review.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns full details for a single review by ID. Only approved reviews on a live project are accessible; pending or rejected reviews, and reviews of a removed project, return 404. Includes the review author, associated project, category ratings, Minecraft version context, playtime, and community vote counts.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/reviews/1" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/reviews/1"
);

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/reviews/1';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/reviews/1'
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, Success):


{
    "data": {
        "id": 1,
        "is_quick_rating": false,
        "title": "Amazing mod!",
        "content": "This mod completely changed how I play Minecraft...",
        "rating": 4.5,
        "gameplay_rating": 4,
        "performance_rating": 4.5,
        "aesthetics_rating": 5,
        "minecraft_version": "1.20.1",
        "playtime_hours": 500,
        "play_status": "completed",
        "pack_version": null,
        "helpful_votes": 5,
        "unhelpful_votes": 0,
        "is_verified_developer": false,
        "author": {
            "id": 1,
            "name": "Steve"
        },
        "project": {
            "id": 1,
            "name": "Create",
            "slug": "create",
            "type": "mod"
        },
        "created_at": "2026-03-01T00:00:00+00:00",
        "edited_at": null,
        "public_moderator_note": null
    }
}
 

Example response (404, Not Found):


{
    "message": "Not Found"
}
 

Request      

GET api/v1/reviews/{id}

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   integer     

The review ID. Example: 1

Tags

Endpoints for browsing project taxonomy tags (genres, features, themes, mod loaders, Minecraft versions).

List tags.

requires authentication deprecated:v1 is switched off six months after v2 becomes generally available. Use v2.

Returns the taxonomy tags used to categorize projects. Filter by type to get a specific category: genre (Technology, Magic, Adventure...), feature (Redstone, Worldgen, Mobs...), theme (Automation, Exploration...), or dev_environment. Mod loaders and Minecraft versions are not tags. Read the mod_loaders and minecraft_versions fields on project responses instead.

Example request:
curl --request GET \
    --get "https://moddex.gg/api/v1/tags?type=genre&per_page=50" \
    --header "Authorization: Bearer {YOUR_AUTH_KEY}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://moddex.gg/api/v1/tags"
);

const params = {
    "type": "genre",
    "per_page": "50",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_AUTH_KEY}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://moddex.gg/api/v1/tags';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_AUTH_KEY}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'type' => 'genre',
            'per_page' => '50',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://moddex.gg/api/v1/tags'
params = {
  'type': 'genre',
  'per_page': '50',
}
headers = {
  'Authorization': 'Bearer {YOUR_AUTH_KEY}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200, Success):


{
    "data": [
        {
            "id": 1,
            "name": "Technology",
            "slug": "technology",
            "type": "genre",
            "description": "Mods focused on technology and automation."
        }
    ],
    "links": {
        "first": "...",
        "last": "...",
        "prev": null,
        "next": null
    },
    "meta": {
        "current_page": 1,
        "last_page": 1,
        "per_page": 50,
        "total": 12
    }
}
 

Request      

GET api/v1/tags

Headers

Authorization        

Example: Bearer {YOUR_AUTH_KEY}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

type   string  optional    

Filter by tag type (genre, feature, theme, dev_environment). Example: genre

per_page   integer  optional    

Results per page (max 100). Default: 50. Example: 50

Recipes

These are worked examples of the integrations people build most often. The code is TypeScript using fetch, typed with a client generated from the OpenAPI spec:

npx openapi-typescript https://moddex.gg/api/docs.openapi -o moddex.d.ts

Every recipe uses this small helper. A 404 from a lookup means "not on ModDex", so it returns null; anything else that isn't a success throws with the error code.

import type { components } from "./moddex";

export type Schemas = components["schemas"];

const API = "https://moddex.gg/api/v2";

export async function moddex<T>(path: string, init: RequestInit = {}): Promise<T | null> {
    const response = await fetch(API + path, {
        ...init,
        headers: { "X-Client": "my-app/1.0.0", ...init.headers },
    });

    if (response.status === 404) {
        return null;
    }

    if (!response.ok) {
        const error = (await response.json()) as Schemas["Error"];
        throw new Error(`ModDex ${response.status} ${error.code}: ${error.message}`);
    }

    return (await response.json()) as T;
}

Browser extension on Modrinth or CurseForge

On a project page, one request gets the rating, the links and the newest reviews. Take the slug from the page URL:

const slug = location.pathname.split("/")[2]; // modrinth.com/mod/sodium
const page = await moddex<Schemas["LookupReviewListResponse"]>(`/lookup/modrinth/${encodeURIComponent(slug)}/reviews?per_page=5`);

if (page !== null) {
    const { rating, links } = page.meta.project;
    // rating.average is null when nobody has rated the project yet.
    renderSummary(rating.average, rating.count, links.web, links.write_review);
    page.data.forEach(renderReview);
}
GET /api/v2/lookup/modrinth/sodium/reviews?per_page=5
{
    "data": [{"id": 77, "title": "Essential", "content_html": "<p>Doubles my FPS.</p>", "rating": 5, "author": {"name": "Steve", "profile_url": "https://moddex.gg/user/steve"}}],
    "meta": {
        "current_page": 1, "last_page": 7, "per_page": 5, "total": 31,
        "project": {"id": 1234, "name": "Sodium", "rating": {"average": 4.8, "bayesian": 4.6, "count": 52, "written_count": 31}, "links": {"web": "https://moddex.gg/mod/sodium", "write_review": "https://moddex.gg/mod/sodium#review-form"}},
        "matched": {"key": "modrinth_slug", "value": "sodium", "via_facet": false, "via_alias": false, "alternatives": []}
    }
}

(Shortened: every object carries all its fields; see "Look up by platform and value, with the project's reviews".)

On a list page (search results, a collection), look the whole page up in one batch. Links carry the project type, so pass the cards' links rather than bare slugs, and sort them so the same page hits the same cache entry:

const urls = [...document.querySelectorAll<HTMLAnchorElement>("a.project-card")].map((a) => a.href).sort();
const batch = await moddex<Schemas["BatchLookupResponse"]>(`/lookup/batch?urls=${urls.map(encodeURIComponent).join(",")}`);

for (const [url, project] of Object.entries(batch?.data.urls ?? {})) {
    if (project !== null && !("ambiguous" in project)) {
        renderBadge(url, project.rating, project.links.web);
    }
}

Encode each link on its own and join them with plain commas. If you encode the joined list (URLSearchParams, urlencode), the commas between links are encoded too, and the request is a 422.

Mount ModDex content in a Shadow DOM (see Output safety), and set anything that isn't *_html with textContent:

function renderReview(review: Schemas["Review"]): void {
    const host = document.createElement("div");
    const root = host.attachShadow({ mode: "closed" });
    const title = document.createElement("h4");
    title.textContent = review.title ?? "";
    const body = document.createElement("div");
    body.innerHTML = review.content_html ?? "";
    root.append(title, body);
    document.querySelector("#moddex-reviews")?.append(host);
}

Credit ModDex next to the reviews (see Attribution), and point "Write a review" at links.write_review.

The browser's HTTP cache does the caching for you and revalidates with the ETag. A project that isn't on ModDex returns a 404 that's cached for 60 seconds.

Launcher or mod manager

Show a rating next to each installed mod. Hash the jars in the mods folder and look them up 100 at a time:

import { createHash } from "node:crypto";
import { readFile, readdir } from "node:fs/promises";

const jars = (await readdir(modsDir)).filter((name) => name.endsWith(".jar"));
const sha1ByJar = new Map<string, string>();
for (const jar of jars) {
    sha1ByJar.set(jar, createHash("sha1").update(await readFile(`${modsDir}/${jar}`)).digest("hex"));
}

const hashes = [...sha1ByJar.values()];
for (let start = 0; start < hashes.length; start += 100) {
    const chunk = hashes.slice(start, start + 100).join(",");
    const result = await moddex<Schemas["FileBatchLookupResponse"]>(`/lookup/files/batch?sha1=${chunk}`);

    for (const [sha1, match] of Object.entries(result?.data.sha1 ?? {})) {
        if (match !== null) {
            showRating(sha1, match.project.rating, match.project.links.web);
        }
    }
}

SHA1 matching works for files published on Modrinth. For CurseForge files, use the file IDs your launcher already has from its CurseForge manifest: /lookup/files/batch?curseforge_file_id=5432101,5432102. ModDex doesn't store CurseForge fingerprints, so a CurseForge jar can't be matched by its content.

Discord bot

When someone pastes a link, look it up:

const found = await moddex<Schemas["ExplicitLookupResponse"]>(`/lookup?url=${encodeURIComponent(pastedLink)}`);
if (found !== null) {
    reply(`${found.data.name}: ${found.data.rating.average ?? "unrated"} ★ (${found.data.rating.count} ratings) ${found.data.links.web}`);
}

For a search command, q takes 3 to 200 characters and sorts by relevance:

const results = await moddex<Schemas["ProjectListResponse"]>(`/projects?q=${encodeURIComponent(query)}&per_page=5`);

For a "new reviews" channel, follow the reviews sync feed and post the ones for projects you track. (Polling /v2/reviews?since= would miss reviews approved after moderation, because they keep the date they were written.) The feed lists a review when it becomes public and again whenever it changes, so keep track of what you've already posted:

const tracked = new Set([1234, 5678]);
const posted = new Set<number>();
const startedAt = new Date().toISOString();
let cursor: string | null = null; // store it between runs

async function postNewReviews(): Promise<void> {
    for (;;) {
        const page: Schemas["ReviewSyncResponse"] | null = await moddex<Schemas["ReviewSyncResponse"]>(cursor === null ? `/sync/reviews?since=${encodeURIComponent(startedAt)}` : `/sync/reviews?cursor=${encodeURIComponent(cursor)}`);
        if (page === null) {
            return;
        }

        for (const review of page.data) {
            if (tracked.has(review.project.id) && !posted.has(review.id)) {
                posted.add(review.id);
                post(`${review.project.name}: ${review.rating} ★ ${review.url}`);
            }
        }

        cursor = page.meta.next_cursor;
        if (!page.meta.has_more) {
            return;
        }
    }
}

The first call starts from since, so the bot only posts reviews from when it started. After that, call it every few minutes. A review reaches the feed 5 minutes after it changes.

Run a bot from a server with a token, and ask for a higher limit if many servers use it.

Website widget

To show staff picks with their blurbs:

const picks = await moddex<Schemas["ProjectListResponse"]>("/projects?featured=1&per_page=6");
picks?.data.forEach((project) => card(project.name, project.featured?.blurb ?? project.summary, project.links.web));

In a README, use the rating badge. The links.badge URL is an SVG that always shows the current rating.

[![ModDex rating](https://moddex.gg/badges/projects/sodium/rating.svg?type=mod)](https://moddex.gg/mod/sodium?ref=my-readme)

Catalog UI

Build the filter panel from /v2/catalog/filters: every parameter, its type, whether it takes a list, its _exclude and any/all companions, and the valid values for small vocabularies. Every slug in a response is a valid filter value, so "more like this" is one step:

const project = await moddex<Schemas["ProjectResponse"]>("/projects/1234");

if (project !== null && project.data.genres.length > 0) {
    const genres = project.data.genres.map((genre) => genre.slug).join(",");
    const more = await moddex<Schemas["ProjectListResponse"]>(`/projects?type=${project.data.type}&genres=${genres}&genres_mode=any`);
}

Migrating from v1

v1 (/api/v1) is frozen: it gets security fixes only and is switched off six months after v2 becomes generally available. After that, v1 answers 410 with code: api_version_retired. Until then, v1 responses carry Deprecation and Sunset headers once the date is set.

The main differences:

Routes

v1 v2
GET /v1/projects GET /v2/projects (default sort is now bayesian_rating desc, not name)
GET /v1/mods/{slug} GET /v2/lookup/moddex/{slug}?type=mod
GET /v1/modpacks/{slug} GET /v2/lookup/moddex/{slug}?type=modpack
GET /v1/mods/{slug}/reviews GET /v2/lookup/moddex/{slug}/reviews?type=mod
GET /v1/modpacks/{slug}/reviews GET /v2/lookup/moddex/{slug}/reviews?type=modpack
GET /v1/reviews/{id} GET /v2/reviews/{id}
GET /v1/tags GET /v2/tags (genres, features, themes, environments; type=dev_environment is now type=environment), /v2/loaders, /v2/minecraft-versions
GET /api/user unchanged; still the way to check a token

Project fields

v1 v2
average_rating (0.0 when unrated) rating.average (null when unrated)
bayesian_rating rating.bayesian
total_ratings rating.count
total_reviews, written_reviews_count rating.written_count
gameplay_rating, performance_rating, aesthetics_rating ratings.categories.* with include=ratings (histograms; the average is the count-weighted mean)
mod_loaders[] (names) loaders[] ({slug, name})
genres[], features[], themes[] (names) genres[], features[], themes[] ({slug, name})
platform_urls.curseforge, platform_urls.modrinth curseforge.url, modrinth.url
platform_urls.source, .issues, .wiki, .discord unchanged
curseforge.description curseforge.description_html with include=description
modrinth.description modrinth.description and modrinth.description_html with include=description
curseforge.authors, modrinth.authors authors[]: one credit list with each platform's URL and username
curseforge_created_at curseforge.created_at; published_at is the earliest platform date
sources[].mod_loaders (names) sources[].loaders ({slug, name})
license (a string) license.name, with license.open_source and license.categories
(none) available, links, featured, counts, latest_version, environment, community_tags_count

Review fields

v1 v2
content (raw) content (masked unless unmasked=1) and content_html (sanitized)
gameplay_rating, performance_rating, aesthetics_rating categories.gameplay, .performance, .aesthetics
author: {id, name} author: {id, name, username, avatar_url, profile_url, roles, reputation}
project: {id, name, slug, type} project: the project summary, with rating and links
(none) content_html, completion_hours, images, developer_response, url, updated_at

Review sorts change from sort=created_at|rating|helpful_votes|unhelpful_votes plus direction to sort=newest|oldest|rating|helpful, and per_page defaults to 20 instead of 15.

What each version lists

/v1/projects lists every project whose status is active. /v2/projects lists what the website's catalog lists: it leaves out projects delisted on every platform, and includes staff-archived ones. Looking a project up directly works the same in both, delisted or not; v2 marks a delisted project available: false, and gives null for the URL of a listing its platform no longer shows.

API changelog

Additive changes (a new endpoint, field, parameter, include block or error code) ship at any time and are listed here. Build clients that ignore fields they don't know. Breaking changes (removing or renaming anything, changing a type or a default) only come with a new version: the old one keeps working for at least six months, and says so in Deprecation and Sunset headers. Changes are announced in the ModDex Discord.

2026-10-19: v2 public launch

Attribution

When you show ModDex ratings or reviews, credit ModDex where you show them:

Logos, served from ModDex itself (no third-party request):

Asset SVG PNG
Icon moddex-icon.svg moddex-icon-512.png
Wordmark, for dark backgrounds moddex-logo-on-dark.svg moddex-logo-on-dark.png
Wordmark, for light backgrounds moddex-logo-on-light.svg moddex-logo-on-light.png

Don't recolor or distort the logo. The rating badge (links.badge) is the simplest way to show a live rating anywhere an image can go.

Using the API means accepting the Terms of Service, including their API section: personal and non-commercial use only, credit ModDex, and remove content within 7 days of its removal from ModDex.