minecraft.wiki-mirror/wiki_backup/Mojang API.txt
2024-12-24 06:17:34 -05:00

752 lines
28 KiB
Text

This page provides documentation for '''API''' endpoints provided by [[Mojang Studios]] which allows user to query player data and make changes programmatically.
Currently, the API is rate limited at 600 requests per 10 minutes. <ref>http://wiki.vg/Mojang_API ([https://web.archive.org/web/20241129034336/wiki.vg/Mojang_API Internet Archive])</ref>
== Request and response ==
For requests with a payload, the following restrictions apply:
* Request must include the <code>Content-Type</code> header, which must be <samp>application/json</samp>. Otherwise, the server returns HTTP 415.
* Payload must be a valid json. Otherwise, the server returns HTTP 400.
If the request is successful, the server:
* Returns a successful response code (HTTP 2XX)
* Returns an empty payload (with HTTP 204) or a valid json
Otherwise, if the request fails, the server returns a non-2XX HTTP status code with this payload:
<div class="treeview">
* {{Nbt|compound}}: Root tag.
** {{Nbt|string|error}}: Error identifier
** {{Nbt|string|errorMessage}}: Description of the error
** {{Nbt|string|cause}}: Description of the cause of the error
</div>
These are some common causes:
{| class="wikitable mw-collapsible mw-collapsed"
! HTTP status code
! {{cd|error}}
! {{cd|errorMessage}}
! Explanation
|-
| rowspan=3 | 400
| IllegalArgumentException
| rowspan=3 | Depends on the endpoint
| Incorrect or invalid argument in the request.
|-
| MismatchedInputException
| rowspan=2 | JSON payload does not meet the required schema or payload is not an invalid JSON.
|-
| JsonParseException
|-
| rowspan=2 | 401
| (empty payload)
| (empty payload)
| Endpoint requires authentication, but request header does not have an <code>Authorization</code> header or the token is invalid.
|-
| Unauthorized
| The request requires user authentication
| Endpoint requires authentication, but request header does not have an <code>Authorization</code> header.
|-
| rowspan=2 | 403
| ForbiddenOperationException
| Forbidden
| Invalid auth token.
|-
| {{tc|n/a}}
| Your account has been suspended. Please contact customer service.
| Account has been banned/suspended state by triggering a high volume of erroneous requests. See [[#Account suspensions]].
|-
| 404
| Not Found
| The server has not found anything matching the request URI
| Endpoint does not exist.
|-
| 405
| Method Not Allowed
| The method specified in the request is not allowed for the resource identified by the request URI
| Request method is not supported.
|-
| 415
| Unsupported Media Type
| The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method
| {{cd|Content-Type}} request header does not match the type the endpoint allows.
|}
=== Account suspensions ===
A Minecraft account can be entered into a banned/suspended state by triggering a high volume of erroneous requests, such as a high volume of 429s while uploading a skin.
These suspensions appear to be temporary, although this is speculation and the exact functionality of this automatic suspension system is unknown.
POST <nowiki>https://api.minecraftservices.com/authentication/login_with_xbox</nowiki>
Returns 403 with the following JSON data
<syntaxhighlight lang="json">
{
"path": "/authentication/login_with_xbox",
"details": {
"reason": "ACCOUNT_SUSPENDED"
},
"errorMessage": "Your account has been suspended. Please contact customer service."
}
</syntaxhighlight>
Other services will report that the account is banned, such as servers serving the otherwise unused message <nowiki>You are banned from playing online</nowiki>.
These suspensions typically clear within 24 hours but may require contacting Minecraft support if they don't.
== Query player information ==
These endpoints do not need an access token, and some endpoints can query registered account that do not own the game.
=== Query player's UUID ===
; Input
Player's name (case insensitive).
; Request (GET)
<code><nowiki>https://api.mojang.com/users/profiles/minecraft/</nowiki><''player name''></code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|id}}: [[UUID]] of the player.
** {{Nbt|string|name}}: Name of the player, case sensitive.
** {{Nbt|bool|legacy}}: Included in response if the account has not migrated to Mojang account.
** {{Nbt|bool|demo}}: Included in response if the account does not own the game.
</div>
; Example
<code><nowiki>https://api.mojang.com/users/profiles/minecraft/jeb_</nowiki></code><br>Player <samp>jeb_</samp>'s UUID.
<syntaxhighlight lang="json">
{
"name": "jeb_",
"id": "853c80ef3c3749fdaa49938b674adae6"
}</syntaxhighlight>
; Error
* HTTP 404 is returned if no player with such name exists.
=== Query player UUIDs in batch ===
; Payload
A JSON array with less than 10 player names (case insensitive).
; Request (POST)
* <code><nowiki>https://api.mojang.com/profiles/minecraft</nowiki></code>
* <code><nowiki>https://api.minecraftservices.com/minecraft/profile/lookup/bulk/byname</nowiki></code>
; Response
<div class="treeview">
* {{Nbt|list}} The UUID list for all the players. For players that does not exist, no result is returned.
** {{Nbt|compound}} Player name.
*** {{Nbt|string|id}}: Player's UUID.
*** {{Nbt|string|id}}: [[UUID]] of the player.
*** {{Nbt|string|name}}: Name of the player, case sensitive.
*** {{Nbt|bool|legacy}}: Included in response if the account has not migrated to Mojang account.
*** {{Nbt|bool|demo}}: Included in response if the account does not own the game.
</div>
; Example
Request with payload <code><nowiki>["jeb_","notch"]</nowiki></code>.
<syntaxhighlight lang="json">
[
{
"id": "853c80ef3c3749fdaa49938b674adae6",
"name": "jeb_"
},
{
"id": "069a79f444e94726a5befca90e38aaf5",
"name": "Notch"
}
]</syntaxhighlight>
{| class="wikitable mw-collapsible mw-collapsed"
! HTTP status code
! {{cd|error}}
! {{cd|errorMessage}}
! Explanation
|-
| rowspan=3 | 400
| rowspan=3 | CONSTRAINT_VIOLATION
| rowspan=2 | size must be between 1 and 10
| RequestPayload is an empty array.
|-
| RequestPayload is has more than 10 elements.
|-
| Invalid profile name
| RequestPayload includes an empty string.
|}
=== Query player's skin and cape ===
; Input
Player UUID and whether the request is [[wikipedia:Digital signature|signed]].
; Request (GET)
<code><nowiki>https://sessionserver.mojang.com/session/minecraft/profile/</nowiki><''UUID''></code> or<br><code><nowiki>https://sessionserver.mojang.com/session/minecraft/profile/</nowiki><''UUID''>?unsigned=false</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|id}}: Player's [[UUID]].
** {{Nbt|string|name}}: Player name, case sensitive.
** {{Nbt|boolean|legacy}}: Included in response if the account has not migrated to Mojang account.
** {{Nbt|list|properties}}: A list of player properties.
*** {{Nbt|string|name}}: Name of the property. For now, the only property that exists is <code>textures</code>.
*** {{Nbt|string|signature}}: Signature signed with <samp>Yggdrasil</samp> private key as Base64 string, only exists when <code>unsigned=false</code>.
*** {{Nbt|string|value}}: [[wikipedia:Base64|Base64]] string with all player textures (skin and cape). The decoded string includes:
**** {{Nbt|compound}} Texture object.
***** {{Nbt|int|timestamp}}: [[wikipedia:Unix time|Unix time]] in milliseconds the texture is accessed.
***** {{Nbt|string|profileId}}: Player's UUID without dashes.
***** {{Nbt|string|profileName}}: Player name.
***** {{Nbt|boolean|signatureRequired}}: Only exists when <code>unsigned=false</code>.
***** {{Nbt|compound|textures}}: Texture.
****** {{Nbt|compound|SKIN}}: [[Skin]] texture. This does not exist if the player does not have a custom skin.
******* {{Nbt|string|url}}: URL to the skin texture.
******* {{Nbt|compound|metadata}}: Optional. Metadata for the skin.
******** {{Nbt|string|model}}: <code>slim</code>. Only exists when skin model is <samp>Alex</samp>. When skin model is <samp>Steve</samp>, this metadata does not exist.
****** {{Nbt|compound|CAPE}}: [[Cape]] texture. If the player does not have a cape, this does not exist.
******* {{Nbt|string|url}}: URL to the cape texture.
</div>
; Example
<code><nowiki>https://sessionserver.mojang.com/session/minecraft/profile/853c80ef3c3749fdaa49938b674adae6</nowiki></code><br>Returns:
<syntaxhighlight lang="json">
{
"id": "853c80ef3c3749fdaa49938b674adae6",
"name": "jeb_",
"properties":
[
{
"name": "textures",
"value": "ewogICJ0aW1lc3R..."
}
]
}
</syntaxhighlight>
Content in {{Nbt|string|value}} after Base64 decoded:
<syntaxhighlight lang="json">
{
"timestamp" : 1653838459263,
"profileId" : "853c80ef3c3749fdaa49938b674adae6",
"profileName" : "jeb_",
"textures" : {
"SKIN" : {
"url" : "http://textures.minecraft.net/texture/7fd9ba42a7c81eeea22f1524271ae85a8e045ce0af5a6ae16c6406ae917e68b5"
},
"CAPE" : {
"url" : "http://textures.minecraft.net/texture/9e507afc56359978a3eb3e32367042b853cddd0995d17d0da995662913fb00f7"
}
}
}
</syntaxhighlight>
; Error
{| class="wikitable mw-collapsible mw-collapsed"
! HTTP status code
! {{cd|error}}
! {{cd|errorMessage}}
! Explanation
|-
| 204
| (empty payload)
| (empty payload)
| This UUID does not have an associated player
|-
| 400
| (empty)
| Not a valid UUID: <''inputted argument''>
| UUID is invalid.
|}
== Microsoft authentication ==
{{for|overview on the authentication steps|Microsoft authentication}}
Authentication for Microsoft accounts. Before using Microsoft auth, an [https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app Microsoft Azure Application] must be created to obtain [https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow OAuth 2.0] client ID and token, which can then be used to obtain a Microsoft token. When obtaining the token, the {{cd|scope}} parameter should include {{samp|XboxLive.signin}} to obtain an Xbox Live token.
=== Obtain an Xbox Live token with Microsoft token ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|compound|Properties}}: Authentication properties
*** {{Nbt|string|AuthMethod}}: Login method. This should be <code>RPS</code>.
*** {{Nbt|string|SiteName}}: Website name. This should be <code>user.auth.xboxlive.com</code>.
*** {{Nbt|string|RpsTicket}}: Ticket used for logging in. Value should be <code>d=<''Microsoft access token''></code>.
** {{Nbt|string|RelyingParty}}: Replying party. This should be <code>http://auth.xboxlive.com</code>.
** {{Nbt|string|TokenType}}: Type of the access token. This should be <code>JWT</code>.
</div>
; Request (POST)
<code><nowiki>https://user.auth.xboxlive.com/user/authenticate</nowiki></code>
SSL renegotiation required in SSL implementation.
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|IssueInstant}}: Time when obtaining the Xbox Live token.
** {{Nbt|string|NotAfter}}: Time the Xbox Live token is expired.
** {{Nbt|string|Token}}: Xbox Live access token.
** {{Nbt|compound|DisplayClaims}}: Unknown.
*** {{Nbt|list|xui}}: Unknown.
**** {{Nbt|compound}}
***** {{Nbt|string|uhs}}: User hashcode.
</div>
=== Obtain an XSTS token with Xbox Live token ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|compound|Properties}}: Auth properties.
*** {{Nbt|string|SandboxId}}: Sandbox ID. This should be <code>RETAIL</code>.
*** {{Nbt|list|UserTokens}}: User's Xbox Live token.
**** {{Nbt|string}}: User's Xbox Live token obtained in the previous step.
** {{Nbt|string|RelyingParty}}: Replying party. This should be <code>rp://api.minecraftservices.com/</code>.
** {{Nbt|string|TokenType}}: Type of the access token. This should be <code>JWT</code>.
</div>
; Request (POST)
<code><nowiki>https://xsts.auth.xboxlive.com/xsts/authorize</nowiki></code>
SSL renegotiation required in SSL implementation.
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|IssueInstant}}: Time when obtaining the XSTS token.
** {{Nbt|string|NotAfter}}: Time the XSTS token is expired.
** {{Nbt|string|Token}}: XSTS access token.
** {{Nbt|compound|DisplayClaims}}: Unknown.
*** {{Nbt|list|xui}}: Unknown.
**** {{Nbt|compound}}
***** {{Nbt|string|uhs}}: User hashcode.
</div>
; Error
HTTP 401 is returned if an error occurs in obtaining the XSTS token.
=== Obtain Minecraft access token with XSTS token ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|identityToken}}: Identity token. The value should be <code>XBL3.0 x=<''User hashcode''>;<''XSTS access token''></code>.
</div>
; Request (POST)
<code><nowiki>https://api.minecraftservices.com/authentication/login_with_xbox</nowiki></code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|username}}: UUID (not the UUID for the player)
** {{Nbt|list|roles}}: Unknown, empty.
** {{Nbt|string|access_token}}: Minecraft access token.
** {{Nbt|string|token_type}}: Token type. This is always <code>Bearer</code>.
** {{Nbt|string|expires_in}}: Time period until the token expires in seconds.
</div>
=== Check if the account owns Minecraft ===
; Request header
<code>Authorization</code> should be <code>Bearer <''Minecraft access token''></code>.
; Request (GET)
<code><nowiki>https://api.minecraftservices.com/entitlements/mcstore</nowiki></code>
; Response
If the account owns Minecraft, returns:
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|list|items}}: Data and signatures.
*** {{Nbt|string|name}}: Data name, either <code>product_minecraft</code> or <code>game_minecraft</code>.
*** {{Nbt|string|signature}}: JWT signature for the data.
** {{Nbt|string|signature}}: JWT signature.
** {{Nbt|string|keyID}}: Unknown.
</div>
If the account does not own Minecraft or is playing with Xbox Game Pass, empty payload is returned.
== Player config ==
These endpoints are at <code><nowiki>https://api.minecraftservices.com</nowiki></code>, and all requires the <code>Authorization</code> header in request with value <samp>Bearer <''Minecraft access token''></samp>. HTTP 401 is returned if token is missing or invalid.
=== Query player profile ===
; Request (GET)
<code>/minecraft/profile</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|id}}: Player's UUID.
** {{Nbt|string|name}}: Player name.
** {{Nbt|list|skins}}: A list of info of all the skins the player owns.
*** {{Nbt|compound}}: A skin.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the skin.
**** {{Nbt|string|variant}}: Skin variant. <code>CLASSIC</code> for the Steve model and <code>SLIM</code> for the Alex model.
** {{Nbt|list|capes}}: A list of info of all the capes the player owns.
*** {{Nbt|compound}}: A cape.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the cape.
**** {{Nbt|string|alias}}: Alias for the cape.
</div>
=== Query player attributes ===
; Request (GET)
<code>/player/attributes</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|compound|privileges}}: Player's privileges
*** {{Nbt|compound|onlineChat}}: Privilege of accepting chat messages
**** {{Nbt|boolean|enable}}
*** {{Nbt|compound|multiplayerServer}}: Privilege of joining servers.
**** {{Nbt|boolean|enable}}
*** {{Nbt|compound|multiplayerRealms}}: Privilege of joining Realms.
**** {{Nbt|boolean|enable}}
*** {{Nbt|compound|telemetry}}: Privilege of sending telemetry.
**** {{Nbt|boolean|enable}}
*** {{Nbt|compound|optionalTelemetry}}: Privilege of sending optional telemetry.
**** {{Nbt|boolean|enable}}
** {{Nbt|compound|profanityFilterPreferences}}: Profanity filter settings.
*** {{Nbt|boolean|profanityFilterOn}}: If Realms profanity filter is on.
** {{Nbt|compound|banStatus}}: Player's ban status
*** {{Nbt|compound|bannedScopes}}: Scope in which the player is banned.
**** {{Nbt|compound}}: Ban scope. If the player is not banned, these objects do not exist. Only <code>MULTIPLAYER</code> exists.
***** {{Nbt|string|banId}}: UUID of the ban.
***** {{Nbt|string|expires}}: When the ban expires. This does not exist if the player is permanently banned.
***** {{Nbt|string|reason}}: Reason for the ban.
***** {{Nbt|string|reasonMessage}}: Ban message displayed.
</div>
=== Modify player attributes ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|compound|profanityFilterPreferences}}: Realms profanity filter options.
*** {{Nbt|boolean|profanityFilterOn}}: If filter is on.
</div>
; Request (POST)
<code>/player/attributes</code>
; Response
The same as [[#Query player attributes]].
=== Get list of blocked users ===
; Request (GET)
<code>/privacy/blocklist</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|list|blockedProfiles}}: A list of blocked players whose chat messages and Realms invitations are ignored.
*** {{Nbt|string}}: UUID for the blocked player.
</div>
=== Get keypair for signature ===
; Request (POST)
<code>/player/certificates</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|compound|keyPair}}: Keypair used for signature.
*** {{Nbt|string|privateKey}}: Private key. Starts with {{cd|-----BEGIN RSA PRIVATE KEY-----}} and ends with {{cd|-----END RSA PRIVATE KEY-----}}.
*** {{Nbt|string|publicKey}}: Public key. Starts with{{cd|-----BEGIN RSA PUBLIC KEY-----}} and ends with {{cd|-----END RSA PUBLIC KEY-----}}.
** {{Nbt|string|publicKeySignature}}: Deprecated, see below.
** {{Nbt|string|publicKeySignatureV2}}: Public key signature.
** {{Nbt|string|expiresAt}}: When the keypair expires.
** {{Nbt|string|refreshedAfter}}: When the keypair should be refreshed.
</div>
=== Query player's name change information ===
; Request (GET)
<code>/minecraft/profile/namechange</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|changedAt}}: The last time the name has been changed.
** {{Nbt|string|createdAt}}: The time the player profile is created.
** {{Nbt|boolean|nameChangeAllowed}}: If the player can change name.
</div>
=== Check gift code validity ===
; Request (GET)
<code>/productvoucher/giftcode</code>
; Response
Returns HTTP 200 or 204 if the gift code is valid. Otherwise returns HTTP 404.
=== Check name availability ===
; Request (GET)
<code>/minecraft/profile/name/<''name to be checked''>/available</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|status}}: Status of the name. <code>DUPLICATE</code> means the name is taken. <code>AVAILABLE</code> means the name is available.<code>NOT_ALLOWED</code> means the name does not meet requirements.
</div>
=== Change name ===
; Input
Name to change to
; Request (PUT)
<code>/minecraft/profile/name/<''name to change to''></code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|id}}: Player's UUID.
** {{Nbt|string|name}}: Player name.
** {{Nbt|list|skins}}: A list of info of all the skins the player owns.
*** {{Nbt|compound}}: A skin.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the skin.
**** {{Nbt|string|variant}}: Skin variant. <code>CLASSIC</code> for the Steve model and <code>SLIM</code> for the Alex model.
** {{Nbt|list|capes}}: A list of info of all the capes the player owns.
*** {{Nbt|compound}}: A cape.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the cape.
**** {{Nbt|string|alias}}: Alias for the cape.
</div>
; Error
{| class="wikitable mw-collapsible mw-collapsed"
! HTTP status code
! {{cd|error}}
! {{cd|errorMessage}}
! Explanation
|-
| 400
| CONSTRAINT_VIOLATION
| changeProfileName.profileName: Invalid profile name
| Name does not meet requirement. The name must have less than or equal to 16 characters and must consist of alphanumericals and underscores.
|-
| 403
| (empty)
| Could not change name for profile
| Cannot change name. If <code>detail.status</code> is <samp>DUPLICATE</samp>, the name has already been taken.
|-
| 429
| -
| -
| To many rename requests sent.
|}
=== Change skin ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|variant}}: Skin variant. <code>classic</code> for the Steve model and <code>slim</code> for the Alex model.
** {{Nbt|string|url}}: URL to the skin.
</div>
; Request (POST)
<code>/minecraft/profile/skins</code>
; Response
Returns empty payload if operation succeeds.
=== Upload skin ===
; Payload
Payload is made up of two parts:
* {{cd|variant}}: Skin variant. <code>classic</code> for the Steve model and <code>slim</code> for the Alex model.
* {{cd|file}}: Image data for the new skin. See example below.
; Request (POST)
<code>/minecraft/profile/skins</code>
; Example
<syntaxhighlight lang="bash">
curl -X POST -H "Authorization: Bearer <access token>" -F variant=classic -F file="@steeevee.png;type=image/png" https://api.minecraftservices.com/minecraft/profile/skins
</syntaxhighlight>
; Response
Returns empty payload if upload succeeds.
=== Reset skin ===
; Input
Player's UUID.
; Request (DELETE)
<code><nowiki>https://api.mojang.com/user/profile/</nowiki><''UUID''>/skin</code>
; Response
Returns empty payload if reset succeeds.
=== Hide cape ===
; Request (DELETE)
<code>/minecraft/profile/capes/active</code>
; Response
Returns empty payload if operation succeeds.
=== Show cape ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|capeId}}: UUID for the cape to activate
</div>
; Request (PUT)
<code>/minecraft/profile/capes/active</code>
; Response
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|id}}: Player's UUID.
** {{Nbt|string|name}}: Player name.
** {{Nbt|list|skins}}: A list of info of all the skins the player owns.
*** {{Nbt|compound}}: A skin.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the skin.
**** {{Nbt|string|variant}}: Skin variant. <code>CLASSIC</code> for the Steve model and <code>SLIM</code> for the Alex model.
** {{Nbt|list|capes}}: A list of info of all the capes the player owns.
*** {{Nbt|compound}}: A cape.
**** {{Nbt|string|id}}: Cape's UUID.
**** {{Nbt|string|state}}: Usage status for the cape.
**** {{Nbt|string|url}}: URL to the cape.
**** {{Nbt|string|alias}}: Alias for the cape.
</div>
; Error
{| class="wikitable mw-collapsible mw-collapsed"
! HTTP status code
! {{cd|error}}
! {{cd|errorMessage}}
! Explanation
|-
| 400
| (empty)
| profile does not own cape
| The player does not own the cape.
|}
== Server ==
=== Query blocked server list ===
; Request (GET)
<code><nowiki>https://sessionserver.mojang.com/blockedservers</nowiki></code>
; Response
A text file where every line is the SHA-1 hash of a blocked server. Servers that are known to be blocked can be found at [https://github.com/Reecepbcups/FollowTheEULA/blob/master/blockedServersList.txt here].
=== Verify login session on client ===
; Payload
<div class="treeview">
* {{Nbt|compound}} Root tag
** {{Nbt|string|accessToken}}: Minecraft access token.
** {{Nbt|string|selectedProfile}}: Player UUID without dashes.
** {{Nbt|string|serverId}}: Server ID. See below.
</div>
Server ID is obtained from the following algorithm:
<syntaxhighlight lang="java">
public static String generateServerId(String baseServerId, // Base server ID, usually an empty string""
PublicKey publicKey, // Server's RSA public key
SecretKey secretKey // The symmetric AES secret key used between server and client
) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
messageDigest.update(baseServerId.getBytes("ISO_8859_1"));
messageDigest.update(secretKey.getEncoded());
messageDigest.update(publicKey.getEncoded());
byte[] digestData = messageDigest.digest();
return new BigInteger(digestData).toString(16);
}
</syntaxhighlight>
; Request (POST)
<code><nowiki>https://sessionserver.mojang.com/session/minecraft/join</nowiki></code>
; Response
Returns HTTP 204 if authentication passes.
=== Verify login session on server ===
; Input
Case insensitive player name, server ID obtained by the above algorithm and the client IP (optional).
; Request (GET)
<code><nowiki>https://sessionserver.mojang.com/session/minecraft/hasJoined?</nowiki>username=<''player name''>&serverId=<''Server ID''>&ip=<''Client IP''></code>
; Response
Returns [[#Query player's skin and cape|this payload]] if verification passes.
== History ==
{{HistoryTable
|{{HistoryLine||April 14, 2014|link=https://github.com/Mojang/AccountsClient|Mojang API is released.}}
|{{HistoryLine||November 2020|link=https://bugs.mojang.com/browse/WEB-3367|Endpoint for obtaining player UUID no longer supports the {{cd|at}} parameter.}}
|{{HistoryLine||October 8, 2021|link=https://bugs.mojang.com/browse/WEB-2303?focusedCommentId=1086543&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-1086543|Endpoint for querying Mojang API status is removed. The endpoint was <code><nowiki>https://status.mojang.com/check</nowiki></code>.}}
|{{HistoryLine||May 8, 2022|link={{tweet|Mojang_Ined|1501541417784852484}}|Endpoint for querying Minecraft sales is removed. The endpoint was <code><nowiki>https://api.mojang.com/orders/statistics</nowiki></code>.}}
|{{HistoryLine||September 13, 2022|link=https://help.minecraft.net/hc/en-us/articles/8969841895693-Username-History-API-Removal-FAQ-|The endpoint for querying names a player used to use is removed. The endpoint was <code><nowiki>https://api.mojang.com/user/profiles/</nowiki><''UUID''>/names</code>.}}
}}
== References ==
This article is partially adapted from [[Special:PermaLink/2777487|Mojang API]] on wiki.vg.
== Examples ==
* [https://github.com/hawezo/MojangSharp C#] - Full API wrapper
* [https://github.com/CmlLib/MojangAPI C#] - Full API wrapper with Mojang/Microsoft Authentication
* [https://github.com/spnda/dart_minecraft Dart] - Almost full API wrapper with Mojang Authentication
* [https://github.com/Lukaesebrot/mojango Go] - Full API wrapper
* [https://github.com/PhilipBorgesen/minecraft/tree/master/profile Go] - UUIDs or names to profiles with skins, capes and name histories
* [https://github.com/summer/mojang Python] - Full API Wrapper. Also supports authentication & parts of the Minecraft website
* [https://github.com/Lucino772/pymojang Python] - Pymojang is a full wrapper around de Mojang API and Mojang Authentication API. Also support RCON, Query and Server List Ping
* [https://github.com/SynchronousX/mojang-api Python] - Full API wrapper (not updated since 2018)
* [https://github.com/techkid6/AccountsClientPython Python] - UUIDs or names to profiles (not updated since 2018)
* [https://github.com/elyby/mojang-api PHP] - Complete Mojang's API wrapper
* [https://github.com/Davidoc26/mojang-api PHP] - Almost full API wrapper with Mojang Authentication. Also support head rendering
* [https://github.com/MineTheCube/MojangAPI PHP] - UUIDs or names to profiles with skins, heads and name histories
* [https://gist.github.com/ezfe/a71feccd3a837a2592f1 PHP] - UUIDs to names
* [https://github.com/ozzyfant/AccountsClientPHP PHP] - UUIDs to names, names to uuids
* [https://github.com/SparklingComet/java-mojang-api Java] - Almost full API Wrapper
* [https://github.com/dpkgsoft/mojang Java] - Almost full API Wrapper with auth
* [https://github.com/novastosha/NMoyang Java] - Almost full API with Mojang Authentication and can also work as a console Application.
* [https://github.com/thechunknetwork/mojang-api JavaScript] - UUIDs or names to profiles with skins, capes and name histories
== References ==
{{reflist}}
== Navigation ==
{{Navbox Java Edition technical|General}}
[[Category:Java Edition protocol]]
{{license wiki.vg}}
[[de:Mojang API]]
[[zh:Mojang API]]