Files
pages/packages/api-client/README.md
Calum H. 70e2138248 feat: base api-client impl (#4694)
* feat: base api-client impl

* fix: doc

* feat: start work on module stuff

* feat: migrate v2/v3 projects into module system

* fix: lint & README.md contributing

* refactor: remove utils old api client prototype

* fix: lint

* fix: api url issues

* fix: baseurl in error.vue

* fix: readme

* fix typo in readme

* Update apps/frontend/src/providers/api-client.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* Update packages/api-client/src/features/verbose-logging.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

* Update packages/api-client/src/features/retry.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Calum H. <hendersoncal117@gmail.com>

---------

Signed-off-by: Calum H. <hendersoncal117@gmail.com>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-12 20:29:12 +00:00

5.2 KiB

Modrinth Monorepo Cover

@modrinth/api-client

TypeScript License: GPL-3.0

A flexible, type-safe API client for Modrinth's APIs (Labrinth, Kyros & Archon). Works across Node.js, browsers, Nuxt, and Tauri with a feature system for authentication, retries, circuit breaking and other custom processing of requests and responses.

Installation

pnpm add @modrinth/api-client
# or
npm install @modrinth/api-client
# or
yarn add @modrinth/api-client

Usage

Plain JavaScript/Node.js

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

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

// Explicitly make a request using client.request
const project: any = await client.request('/project/sodium', { api: 'labrinth', version: 2 })

// Example for archon (Modrinth Servers)
const servers = await client.request('/servers?limit=10', { api: 'archon', version: 0 })

// Or use the provided wrappers for better type support.
const project: ProjectV2 = await client.projects_v2.get('sodium')

Nuxt

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

// Alternatively you can create a singleton of the client and provide it via DI.
export const useModrinthClient = () => {
	const config = useRuntimeConfig()

	// example using the useAuth composable from our frontend, replace this with whatever you're using to store auth token
	const auth = await useAuth()

	return new NuxtModrinthClient({
		userAgent: 'my-nuxt-app/1.0.0', // leave blank to use default user agent from fetch function
		rateLimitKey: import.meta.server ? config.rateLimitKey : undefined,
		features: [
			new AuthFeature({
				token: async () => auth.value.token,
			}),
			new CircuitBreakerFeature({
				storage: new NuxtCircuitBreakerStorage(),
			}),
		],
	})
}

const client = useModrinthClient()
const project = await client.request('/project/sodium', { api: 'labrinth', version: 2 })

Tauri

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

const version = await getVersion()
const client = new TauriModrinthClient({
	userAgent: `modrinth/theseus/${version} (support@modrinth.com)`,
	features: [new AuthFeature({ token: 'mrp_...' })],
})

const project = await client.request('/project/sodium', { api: 'labrinth', version: 2 })

Overriding Base URLs

By default, the client uses the production base URLs:

  • labrinthBaseUrl: https://api.modrinth.com/ (Labrinth API)
  • archonBaseUrl: https://archon.modrinth.com/ (Archon/Servers API)

You can override these for staging environments or custom instances:

const client = new GenericModrinthClient({
	userAgent: 'my-app/1.0.0',
	labrinthBaseUrl: 'https://staging-api.modrinth.com/',
	archonBaseUrl: 'https://staging-archon.modrinth.com/',
	features: [new AuthFeature({ token: 'mrp_...' })],
})

// Now requests will use the staging URLs
await client.request('/project/sodium', { api: 'labrinth', version: 2 })
// -> https://staging-api.modrinth.com/v2/project/sodium

You can also use custom URLs directly in requests:

// One-off custom URL (useful for Kyros nodes or dynamic endpoints)
await client.request('/some-endpoint', {
	api: 'https://eu-lim16.nodes.modrinth.com/',
	version: 0,
})

Features

Authentication

Supports both static and dynamic tokens:

// Static token
new AuthFeature({ token: 'mrp_...' })

// Dynamic token (e.g., from auth state)
const auth = await useAuth()
new AuthFeature({
	token: async () => auth.value.token,
})

Retry

Automatically retries failed requests with configurable backoff:

new RetryFeature({
	maxAttempts: 3,
	backoffStrategy: 'exponential',
	initialDelay: 1000,
	maxDelay: 15000,
})

Circuit Breaker

Prevents cascade failures by opening circuits after repeated failures:

new CircuitBreakerFeature({
	maxFailures: 3,
	resetTimeout: 30000,
	failureStatusCodes: [500, 502, 503, 504],
})

Documentation

This package is self-documenting through TypeScript types and JSDoc comments. Use your IDE's IntelliSense to explore available methods, classes, and configuration options.

For Modrinth API endpoints and routes, refer to the Modrinth API Documentation.

Contributing

  • Modules are available in the modules/<api>/... folders.
    • When a module has different versions available, you should do it like so: modules/labrinth/projects/v2.ts etc.
    • Types for a module's requests should be made available in modules/<api>/module/types.ts or .../types/v2.ts.
    • You should expose these types in the modules/types.ts file.
  • When creating a new module, add it to the modules/index.ts's MODULE_REGISTRY for it to become available in the api client class.

Dont forget to run pnpm fix before committing.

License

Licensed under GPL-3.0 - see the LICENSE file for details.