BUILD WITH MCLADDER
Developer API
Public game data for your bots, community tools and statistics. One versioned contract, clear access rules and predictable responses.
API base URL
https://mcladder.com/api/v1Contract version 1.0.0
A community bot
Show the leaderboard in your community. No player account access needed.
A stats page
Combine public profiles with completed matches for your own dashboards.
An online counter
Show how many players are online, playing or looking for a match.
First request
Choose curl, JavaScript or PowerShell and run the ready-to-use request. The API address is filled in automatically; the response is JSON your app can read.
MCLADDER_API_BASE="https://mcladder.com/api/v1"
curl --fail-with-body "$MCLADDER_API_BASE/live"Copy the example and run it on your computer or server. This page never sends it and does not ask for a key.
{
"data": {
"online": 42,
"inMatch": 28,
"searching": 6,
"asOf": "2026-09-06T12:00:00.000Z",
"stale": false
}
}You ask. The API answers.
Your app sends a GET request. The API checks access and limits, then returns JSON. It cannot change a wallet or grant items.
Public reads do not require a key. Examples are illustrative, contain no credentials and are never executed by this page.
- Your app
- mcladder API
- Public data
Access and privacy
Public data
Read public profiles, leaderboard entries, completed matches, season information and selected catalogs. Private fields and internal match data are not included.
Trusted integrations
An administrator issues a server-side key with selected read permissions, an expiry and usage limits. A partner key never grants access to another player's account or bypasses privacy rules.
Get a key in three steps
- 1Describe your app and the public data it needs.
- 2An administrator assigns permissions, an expiry and a shared budget.
- 3Save the key once and use it only from your server.
MCLADDER_API_BASE="https://mcladder.com/api/v1"
curl --fail-with-body "$MCLADDER_API_BASE/leaderboard?limit=10" \
-H "Authorization: Bearer $MCLADDER_API_KEY"Keep keys on your server, never in browser code, a public repository or a URL. Store the secret securely when it is first shown. Revoke a compromised key immediately.
Permissions are checked by the server on every request. An invalid or revoked key is rejected, not silently treated as anonymous access.
Limits and retries
IP limits, integration quotas and shared capacity protections apply together. More keys do not create more quota for the same integration. Use bounded pages and avoid polling unchanged data aggressively.
Short burst
How many requests may start at once. The allowance refills over time.
Refill rate
How quickly your request allowance recovers, measured per minute.
Daily budget
The shared daily budget for an integration, not for each of its keys. Currently, each GET request uses one unit.
In-flight requests
How many requests can be processing at the same time. A completed request frees its slot.
An example, not your assigned quota
A bucket holds 10 requests and refills at 30 per minute. After spending all 10, wait about 2 seconds for the next request. A second key does not refill it.
Something went wrong?
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
On 429, respect Retry-After. On a temporary 503, retry with an increasing delay and jitter. Do not automatically retry 400, 401 or 403 without correcting the request or access.
Live overview
Live counts refer to players, not matches. asOf is the last successful sample time; stale marks a cached sample after a temporary failure. With no successful sample, the API returns 503. Opponents, identities and live task progress are not included.
curl --fail-with-body "https://mcladder.com/api/v1/live"{
"data": {
"online": 42,
"inMatch": 28,
"searching": 6,
"asOf": "2026-09-06T12:00:00.000Z",
"stale": false
}
}Turn the response into a counter
- Online
- 42
- In a match
- 28
- Looking for a match
- 6
Example data · not a live feed
Public match webhooks
Administrators can approve an HTTPS subscription for match.published, match.updated and match.removed. It sends the latest public state, coalescing intermediate changes, with no initial history backfill. Delivery is disabled by default.
A result changes. Your app is notified.
- Public result changes
- Signed HTTPS delivery
- Verify and save
- Confirm with 2xx
A subscription is not enough: delivery must also be enabled by the operator. Your receiver needs a public HTTPS address.
Verify the signature over the raw body and a recent timestamp before processing. Deduplicate event IDs, compare match revisions numerically and ignore older versions. A removal deletes the public copy. Store the event durably before returning 2xx.
After an outage
Recheck your saved matches with GET /matches/…: replace the public copy on 200 and remove it on 404. On 429, 503 or a network error, retry later—do not delete the copy. There is no history backfill; player profile edits alone do not emit match events.
Signature verification · Node.js
Verify the original request bytes before parsing JSON. This helper checks the signature and timestamp; your app must still validate the schema, deduplicate and store the event.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyWebhook(rawBody, headers, secret,
nowSeconds = Math.floor(Date.now() / 1000)) {
const timestamp = headers["x-mcladder-timestamp"];
const signature = headers["x-mcladder-signature"];
if (!Buffer.isBuffer(rawBody) || rawBody.length > 32768
|| typeof secret !== "string" || !secret
|| typeof timestamp !== "string" || !/^\d{1,12}$/.test(timestamp)
|| Math.abs(nowSeconds - Number(timestamp)) > 300
|| typeof signature !== "string" || !/^v1=[0-9a-f]{64}$/.test(signature)) {
throw new Error("invalid_webhook");
}
const expected = createHmac("sha256", secret)
.update(timestamp + ".").update(rawBody).digest();
const received = Buffer.from(signature.slice(3), "hex");
if (!timingSafeEqual(expected, received)) throw new Error("invalid_webhook");
const event = JSON.parse(rawBody.toString("utf8"));
if (event?.id !== headers["x-mcladder-event-id"]) {
throw new Error("invalid_event_id");
}
return event;
}Endpoint reference
Endpoint addresses, parameters and schemas come directly from the OpenAPI contract. Explanations are translated; code and API identifiers keep their original form.
GET/players/{player}Get a public player profile
Deleted profiles return 404. Calibration redacts Elo, peak and rank. Presence, premium expiry, private settings, bans and admin fields are excluded. Name/country follow public profile policy.
x-required-scope: players:readParameters
playerRequired
Path parameterCanonical dashed UUID or known Minecraft username (1–16 letters/digits/underscores). DB identity lookup only, no external account discovery.
Type: string
Request example
curl --fail-with-body "https://mcladder.com/api/v1/players/YOUR_PLAYER"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/Player"
}
}
}GET/leaderboardGet current public leaderboard
Current global season/live rating only. Shared eligibility requires both calibration and leaderboard minimum games; hidden/deleted players are excluded. Stable tie-breakers: Elo, peak Elo, wins, UUID. Country filtering re-numbers places within that country. There is no archived season leaderboard in v1.
x-required-scope: leaderboard:readParameters
limitOptional
Query parameterPage size. Unknown and repeated parameters are rejected.
Type: integerDefault: 25Allowed range: 1–100offsetOptional
Query parameterOffset in current ordering; live data may move between requests. Deep exports are intentionally unavailable.
Type: integerDefault: 0Allowed range: 0–10000countryOptional
Query parameterPublic country code, e.g. RU, DE, or supported custom region RU-TA. Unknown codes are rejected; omit for all countries.
Type: string
Request example
curl --fail-with-body "https://mcladder.com/api/v1/leaderboard"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LeaderboardEntry"
},
"maxItems": 100
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
}GET/players/{player}/matchesList a player's completed public matches
Anonymous privacy always applies, even with an owner/admin cookie or partner key. Hidden premium history returns an empty page with hidden=true. Deleted profiles return 404. Pending verification, pending review, annulled and incomplete matches are excluded. Historical rating visibility is preserved; no seed, replay, inventory or raw event metadata.
x-required-scope: matches:readParameters
playerRequired
Path parameterCanonical dashed UUID or known Minecraft username (1–16 letters/digits/underscores). DB identity lookup only, no external account discovery.
Type: stringlimitOptional
Query parameterPage size. Unknown and repeated parameters are rejected.
Type: integerDefault: 25Allowed range: 1–100offsetOptional
Query parameterOffset in current ordering; live data may move between requests. Deep exports are intentionally unavailable.
Type: integerDefault: 0Allowed range: 0–10000
Request example
curl --fail-with-body "https://mcladder.com/api/v1/players/YOUR_PLAYER/matches"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data",
"pagination",
"hidden"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Match"
},
"maxItems": 100
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
},
"hidden": {
"type": "boolean"
}
}
}GET/matches/{match}Get one completed public match
The direct match record has the same public visibility as the anonymous match page, independently of a player's private history listing. Only terminal public records. Historical participant calibration is never reopened; no seeds, inventory, raw end metadata, events or replay downloads.
x-required-scope: matches:readParameters
matchRequired
Path parameterCanonical dashed UUID or canonical 16-hex short ID (case-insensitive).
Type: string
Request example
curl --fail-with-body "https://mcladder.com/api/v1/matches/YOUR_MATCH"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/Match"
}
}
}GET/seasonsList season metadata
Active season first, then season number and ID descending. This endpoint contains metadata only, not archive standings, aggregate records or future scheduled announcements.
x-required-scope: seasons:readParameters
limitOptional
Query parameterPage size. Unknown and repeated parameters are rejected.
Type: integerDefault: 25Allowed range: 1–100offsetOptional
Query parameterOffset in current ordering; live data may move between requests. Deep exports are intentionally unavailable.
Type: integerDefault: 0Allowed range: 0–10000
Request example
curl --fail-with-body "https://mcladder.com/api/v1/seasons"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Season"
},
"maxItems": 100
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
}GET/seasons/{season}Get season metadata
Lookup by positive integer ID or public lowercase slug. Metadata only; archived season leaderboard and scheduled announcements are intentionally excluded.
x-required-scope: seasons:readParameters
seasonRequired
Path parameterPositive integer ID (up to 2147483647) or lowercase slug (letters, digits, hyphens; max64).
Type: string
Request example
curl --fail-with-body "https://mcladder.com/api/v1/seasons/YOUR_SEASON"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/Season"
}
}
}GET/catalogs/ranksGet active rank presentation catalog
Public names, colors, authoritative icon URLs and minimum Elo. No effect configuration or inactive drafts. Relative icon URLs resolve against the API origin; existing media cache/revision policies apply.
x-required-scope: catalogs:readParameters
No parameters are required.
Request example
curl --fail-with-body "https://mcladder.com/api/v1/catalogs/ranks"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data",
"revision"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Rank"
},
"maxItems": 1000
},
"revision": {
"type": "string"
}
}
}GET/catalogs/mapsGet active map rotation catalog
Only active maps. Images use the existing public map-image endpoint. No seeds, world files, spawn geometry or admin settings.
x-required-scope: catalogs:readParameters
No parameters are required.
Request example
curl --fail-with-body "https://mcladder.com/api/v1/catalogs/maps"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Map"
},
"maxItems": 1000
}
}
}GET/catalogs/match-conditionsGet localized match-condition presentation
Static authoritative condition presentation catalog. No runtime probability, gates, rule parameters or administrative configuration.
x-required-scope: catalogs:readParameters
No parameters are required.
Request example
curl --fail-with-body "https://mcladder.com/api/v1/catalogs/match-conditions"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MatchCondition"
}
}
}
}GET/liveGet aggregate live activity
One shared coalesced sample per API process per second. Only aggregate counts are public: no player names, UUIDs, opponents, match cards, seeds, game progress, spectator streams or OBS secrets. Cached reads do not reserve a request database connection. After a sampling failure the last good snapshot is returned with stale=true and its original asOf; before any successful sample, returns 503. No query parameters are accepted.
x-required-scope: live:readParameters
No parameters are required.
Request example
curl --fail-with-body "https://mcladder.com/api/v1/live"Responses
- 200
- Public data received successfully. Cookies and API keys do not change which fields are visible.
- 400
- Check the address, parameters and allowed values. Unknown or repeated parameters are not accepted.
- 401
- The key is invalid, expired or revoked. Check your key; the request does not become anonymous automatically.
- 403
- The key lacks the required permission. Ask an administrator to check its access.
- 404
- The record was not found or is not public. Check the identifier.
- 413
- This read request does not need a body. Remove the request body and try again.
- 429
- The request limit was reached. Wait the number of seconds in Retry-After; another key for the same integration does not increase its quota.
- 503
- The service is temporarily unavailable. Try again later with an increasing delay.
Show response schema
{
"type": "object",
"additionalProperties": false,
"required": [
"data"
],
"properties": {
"data": {
"$ref": "#/components/schemas/LiveSnapshot"
}
}
}