Files
modrinth/packages/api-client
734720e11e feat: instances v2 (#6431)
* feat: base of instances v2

* feat: use old profiles with compat layer

* prototype: instances v2

* fix: install_from using profile

* fix: skins migration fix

* fix: frontend still using profile path

* fix: add update proj multiselect guard

* fix: cargo fmt

* fix: content missing fields

* feat: break up app-lib/api/instance.rs

* fix: check_content_updates mismatch

* fix: updater modal cleanup w/new structure

* feat: better update all handling

* fix: remove preview_update_all

* fix: feedback on bulk update + lint

* fix: rem transitions

* fix: change to jsonb

* feat: app db backup after update

* fix: lint

* fix: sqlx prepare + use sqlx macros

* fix: lint

* fix: bugs

* feat: defuck the installing process up

* fix: bug of hell

* fix: shear

* fix: fmt

* fix: install progress spacing + change mc/content/overrides to bytes

* fix: lint

* fix: prepr

* fix: navtabs anim not working in app

* fix: worlds.vue improvements + browse page fixes

* feat: optimise queries + adapter fns

* fix: lint

* fix: lint

* feat: shared modrinth-content-management crate (#6469)

* feat: disable warnings setting

* feat: add instances shortcuts (#6329)

* Add modrinth://launch deep link to start a profile

Support external profile launching via modrinth://launch/{profile_path} for integrations such as Stream Deck.

* Change route to /launch/profile/{id} for future extensibility

* fix: ensure profile path is url decoded

* fix: URL-decode profile path from deep link

* fix: use urlencoding crate for URL decoding

* feat: implement app instance shortcuts

* feat: change windows shortcut creation to use windows api instead

* feat: implement creating a shortcut launching world/server

* format

* fmt

* fix multiline inline tables

* pnpm prepr

* feat: move create shortcut to last item

* refactor: split up shortcuts.rs for individual platforms

* refactor: turn profile launch url into url type

* use string literal and add safety comment

* pt2

* refactor: rename anything that's profile into instance

* update mac shortcut

---------

Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com>

---------

Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com>
Co-authored-by: DJCheesusReal <134006619+DJCheesusReal@users.noreply.github.com>
2026-06-25 21:19:29 +00:00
..
2026-06-25 21:19:29 +00:00

@modrinth/api-client

TypeScript License: LGPL-3.0

Platform-agnostic TypeScript client for Modrinth's API across Node.js, browsers, Nuxt, and Tauri.

⚠️ We use this internally to power modrinth.com, Modrinth App, and Modrinth Hosting frontends. It may break without any notice, but you are welcome to use it.

Installation

pnpm add @modrinth/api-client

Tauri apps also need the optional peer dependency:

pnpm add @modrinth/api-client @tauri-apps/plugin-http

Usage

Generic Node.js or Browser Client

import { AuthFeature, GenericModrinthClient, type Labrinth } from '@modrinth/api-client'

const client = new GenericModrinthClient({
	userAgent: 'my-app/1.0.0',
	features: [new AuthFeature({ token: process.env.MODRINTH_TOKEN })],
})

const project: Labrinth.Projects.v2.Project = await client.labrinth.projects_v2.get('sodium')
const members = await client.labrinth.projects_v3.getMembers(project.id)

You can still make direct requests through the same platform layer:

const project = await client.request<Labrinth.Projects.v2.Project>('/project/sodium', {
	api: 'labrinth',
	version: 2,
})

Nuxt

import { AuthFeature, CircuitBreakerFeature, NuxtCircuitBreakerStorage, NuxtModrinthClient } from '@modrinth/api-client'

export const useModrinthClient = async () => {
	const config = useRuntimeConfig()

	return new NuxtModrinthClient({
		userAgent: 'my-nuxt-app/1.0.0',
		rateLimitKey: import.meta.server ? config.rateLimitKey : undefined,
		features: [
			new AuthFeature({
				token: process.env.MODRINTH_TOKEN,
			}),
			new CircuitBreakerFeature({
				storage: new NuxtCircuitBreakerStorage(),
			}),
		],
	})
}

Tauri

import { getVersion } from '@tauri-apps/api/app'
import { AuthFeature, TauriModrinthClient } from '@modrinth/api-client'

const client = new TauriModrinthClient({
	userAgent: async () => `modrinth/theseus/${await getVersion()} (support@modrinth.com)`,
	features: [new AuthFeature({ token: process.env.MODRINTH_TOKEN })],
})

const project = await client.labrinth.projects_v2.get('sodium')

API Modules

Modules are available as nested properties on the client:

client.labrinth.projects_v2
client.labrinth.projects_v3
client.labrinth.versions_v3

Types are exported from the package root:

import type { Labrinth } from '@modrinth/api-client'

const project: Labrinth.Projects.v3.Project = await client.labrinth.projects_v3.get('sodium')

Modrinth Hosting API Modules

  • These modules are internal to Modrinth and are only supported inside the Modrinth Hosting panel in Modrinth App and on modrinth.com. They should not be expected to work in third-party clients today. We are discussing how to safely expose access to your own server through these APIs in the future.

Base URLs

By default, the client uses Modrinth production services:

  • labrinthBaseUrl: https://api.modrinth.com

Override them for staging or custom deployments:

const client = new GenericModrinthClient({
	userAgent: 'my-app/1.0.0',
	labrinthBaseUrl: 'https://staging-api.modrinth.com',
})

External APIs can be targeted per request by passing a full URL as api and disabling auth:

await client.request('/endpoint', {
	api: 'https://example.com',
	version: 1,
	skipAuth: true,
})

Features

Features wrap requests before they reach the platform implementation:

import { AuthFeature, CircuitBreakerFeature, RetryFeature } from '@modrinth/api-client'

const client = new GenericModrinthClient({
	features: [new AuthFeature({ token: async () => process.env.MODRINTH_TOKEN }), new RetryFeature({ maxAttempts: 3, backoffStrategy: 'exponential' }), new CircuitBreakerFeature({ maxFailures: 3, resetTimeout: 30_000 })],
})

Built-in features include authentication, node auth, retries, circuit breaking, panel version headers, and verbose logging.

Uploads

Upload endpoints return an UploadHandle<T> with progress and cancellation support:

const upload = client.kyros.files_v0.uploadFile(path, file)

upload.onProgress(({ progress }) => {
	console.log(Math.round(progress * 100))
})

await upload.promise

Uploads use XMLHttpRequest for progress tracking and are only available in browser-capable contexts. NuxtModrinthClient.upload() throws during SSR.

Third-Party API Typings

  • This package also includes some third-party API modules and typings used by Modrinth internals. They are not part of the stable public API surface and should be used at your own risk.

Development

pnpm --filter @modrinth/api-client build
pnpm --filter @modrinth/api-client lint
# or pnpm prepr:frontend:lib in turborepo root.

When adding a module, add it to src/modules/index.ts so it is included in the typed client structure.

License

Licensed under LGPL-3.0. See LICENSE.