<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://theblockheads.wiki/index.php?action=history&amp;feed=atom&amp;title=Cloud_API</id>
	<title>Cloud API - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://theblockheads.wiki/index.php?action=history&amp;feed=atom&amp;title=Cloud_API"/>
	<link rel="alternate" type="text/html" href="https://theblockheads.wiki/index.php?title=Cloud_API&amp;action=history"/>
	<updated>2026-10-12T23:45:15Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://theblockheads.wiki/index.php?title=Cloud_API&amp;diff=25686&amp;oldid=prev</id>
		<title>Eli: /* Connect to world */</title>
		<link rel="alternate" type="text/html" href="https://theblockheads.wiki/index.php?title=Cloud_API&amp;diff=25686&amp;oldid=prev"/>
		<updated>2026-09-18T01:49:11Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Connect to world&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 21:49, 17 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l77&quot;&gt;Line 77:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 77:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;badName&amp;lt;/code&amp;gt;: The nickname is already taken&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;badName&amp;lt;/code&amp;gt;: The nickname is already taken&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;illegalName&amp;lt;/code&amp;gt;: Nickname too long or contains illegal characters&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;illegalName&amp;lt;/code&amp;gt;: Nickname too long or contains illegal characters&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;bannedName&amp;lt;/code&amp;gt;: Nickname is banned&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;bannedName&amp;lt;/code&amp;gt;: Nickname is banned &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;(Unknown when or why this would ever be used)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;unavailable&amp;lt;/code&amp;gt;: World is unavailable due to server error&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;unavailable&amp;lt;/code&amp;gt;: World is unavailable due to server error&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;maintenance&amp;lt;/code&amp;gt;: World is unavailable due to server maintenance&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;** &amp;lt;code&amp;gt;maintenance&amp;lt;/code&amp;gt;: World is unavailable due to server maintenance&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key my_wiki:diff:1.41:old-25685:rev-25686:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Eli</name></author>
	</entry>
	<entry>
		<id>https://theblockheads.wiki/index.php?title=Cloud_API&amp;diff=25685&amp;oldid=prev</id>
		<title>Eli: pretty much just pasting from my github here but feels like a good thing to have on the wiki</title>
		<link rel="alternate" type="text/html" href="https://theblockheads.wiki/index.php?title=Cloud_API&amp;diff=25685&amp;oldid=prev"/>
		<updated>2026-09-18T01:47:00Z</updated>

		<summary type="html">&lt;p&gt;pretty much just pasting from my github here but feels like a good thing to have on the wiki&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Work in progress|Document the create world endpoint}}&lt;br /&gt;
&lt;br /&gt;
The now-defunct Blockheads Cloud used an HTTP API for communication between the client and server. This page documents its endpoints.&lt;br /&gt;
&lt;br /&gt;
= Authentication =&lt;br /&gt;
&lt;br /&gt;
The API uses a very insecure method of &amp;quot;authentication&amp;quot;, which is detailed below.&lt;br /&gt;
&lt;br /&gt;
== Challenge ==&lt;br /&gt;
&lt;br /&gt;
All cloud sessions start with the client making a POST request to the &amp;lt;code&amp;gt;https://cloud.theblockheads.net/api/challenge&amp;lt;/code&amp;gt; endpoint, containing the following URL-encoded fields:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt;: The version of the Blockheads client.&lt;br /&gt;
&lt;br /&gt;
The server responds with a JSON object containing the following properties:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;: Must be &amp;lt;code&amp;gt;ok&amp;lt;/code&amp;gt; for a successful request. &amp;lt;code&amp;gt;badVersion&amp;lt;/code&amp;gt; indicates that the client version is not supported. The client will show a generic error for any other value.&lt;br /&gt;
* &amp;lt;code&amp;gt;baseUrl&amp;lt;/code&amp;gt;: The base URL to be used for future API requests.&lt;br /&gt;
* &amp;lt;code&amp;gt;authToken&amp;lt;/code&amp;gt;: An arbitrary string chosen by the server. The client will use it in the method described below.&lt;br /&gt;
&lt;br /&gt;
== Authenticate ==&lt;br /&gt;
&lt;br /&gt;
The client will now make a POST request to &amp;lt;code&amp;gt;${baseUrl}/authenticate&amp;lt;/code&amp;gt; containing the following URL-encoded fields:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;appVersion&amp;lt;/code&amp;gt;: The version of the Blockheads client.&lt;br /&gt;
* &amp;lt;code&amp;gt;authKey&amp;lt;/code&amp;gt;: The client encodes this as follows:&lt;br /&gt;
** Take the static string &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;-AcwL&amp;amp;jt#qWhq%dlo^xRAaTlCkQt$kgl&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
** Append the user&amp;#039;s iCloud account ID (TODO: what value is used on android?)&lt;br /&gt;
** Append the &amp;lt;code&amp;gt;authToken&amp;lt;/code&amp;gt; from the challenge response&lt;br /&gt;
** Hash to MD5&lt;br /&gt;
* &amp;lt;code&amp;gt;crystals&amp;lt;/code&amp;gt;: The amount of time crystals the user has (integer).&lt;br /&gt;
* &amp;lt;code&amp;gt;dId&amp;lt;/code&amp;gt;: The user&amp;#039;s device ID&lt;br /&gt;
* &amp;lt;code&amp;gt;forceBeta&amp;lt;/code&amp;gt;: Unknown what exactly this means, but the client seems to always send &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;icId&amp;lt;/code&amp;gt;: The user&amp;#039;s iCloud ID&lt;br /&gt;
* &amp;lt;code&amp;gt;platform&amp;lt;/code&amp;gt;: Can be &amp;lt;code&amp;gt;iOS&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Android/Google Play&amp;lt;/code&amp;gt;. The game was on the Amazon app store at one point so there could be a value for that too.&lt;br /&gt;
&lt;br /&gt;
The server responds with a JSON object containing the following properties:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;: Must be &amp;lt;code&amp;gt;ok&amp;lt;/code&amp;gt; for a successful request. &amp;lt;code&amp;gt;banned&amp;lt;/code&amp;gt; indicates that the user is cloud-banned. The client will show a generic error for any other value.&lt;br /&gt;
* &amp;lt;code&amp;gt;sId&amp;lt;/code&amp;gt;: The session ID. Arbitrary and server-chosen&lt;br /&gt;
* &amp;lt;code&amp;gt;spId&amp;lt;/code&amp;gt;: The user&amp;#039;s support ID. Arbitrary and server-chosen; the official cloud used a 6-character alphabetic string. The client does not enforce this.&lt;br /&gt;
&lt;br /&gt;
= Worlds =&lt;br /&gt;
&lt;br /&gt;
== Search Worlds / Random World ==&lt;br /&gt;
&lt;br /&gt;
The same endpoint is used for both searching and the Random World button.&lt;br /&gt;
&lt;br /&gt;
The client sends a POST request to &amp;lt;code&amp;gt;${baseUrl}/world/search&amp;lt;/code&amp;gt; with the following fields:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;sId&amp;lt;/code&amp;gt;: The session ID from the authentication response&lt;br /&gt;
* &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: The string to search for in the world name. If omitted, the client is requesting a random world.&lt;br /&gt;
* &amp;lt;code&amp;gt;pvp&amp;lt;/code&amp;gt;: If specified, only return worlds with PVP enabled (&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) or disabled (&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt;: If specified, only return worlds with custom rules enabled (&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) or disabled (&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;expert&amp;lt;/code&amp;gt;: If specified, only return worlds with expert mode enabled (&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) or disabled (&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;wIds&amp;lt;/code&amp;gt; (array): Request specific worlds by ID. Cannot be used with any of the other options except &amp;lt;code&amp;gt;sId&amp;lt;/code&amp;gt;. This is used to update information about worlds in the client&amp;#039;s cache.&lt;br /&gt;
&lt;br /&gt;
The server responds with a JSON object containing the following properties:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;: Must be &amp;lt;code&amp;gt;ok&amp;lt;/code&amp;gt; for a successful request.&lt;br /&gt;
* &amp;lt;code&amp;gt;worlds&amp;lt;/code&amp;gt;: JSON array, containing an object for each world returned with the following fields:&lt;br /&gt;
** &amp;lt;code&amp;gt;wId&amp;lt;/code&amp;gt;The world ID. The client does not care if this is a string or integer.&lt;br /&gt;
** &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: The name of the world&lt;br /&gt;
** &amp;lt;code&amp;gt;players&amp;lt;/code&amp;gt;: The number of players currently connected to the world&lt;br /&gt;
&lt;br /&gt;
== Connect to world ==&lt;br /&gt;
&lt;br /&gt;
The client sends a POST request to &amp;lt;code&amp;gt;${baseUrl}/world/connect&amp;lt;/code&amp;gt; with the following fields:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;sId&amp;lt;/code&amp;gt;: The session ID from the authentication response&lt;br /&gt;
* &amp;lt;code&amp;gt;wId&amp;lt;/code&amp;gt;: The world ID to connect to&lt;br /&gt;
* &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: The nickname the client wants to use&lt;br /&gt;
&lt;br /&gt;
The server responds with a JSON object containing the following properties:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;: Must be &amp;lt;code&amp;gt;ok&amp;lt;/code&amp;gt; for a successful request. Other values:&lt;br /&gt;
** &amp;lt;code&amp;gt;badName&amp;lt;/code&amp;gt;: The nickname is already taken&lt;br /&gt;
** &amp;lt;code&amp;gt;illegalName&amp;lt;/code&amp;gt;: Nickname too long or contains illegal characters&lt;br /&gt;
** &amp;lt;code&amp;gt;bannedName&amp;lt;/code&amp;gt;: Nickname is banned&lt;br /&gt;
** &amp;lt;code&amp;gt;unavailable&amp;lt;/code&amp;gt;: World is unavailable due to server error&lt;br /&gt;
** &amp;lt;code&amp;gt;maintenance&amp;lt;/code&amp;gt;: World is unavailable due to server maintenance&lt;br /&gt;
** &amp;lt;code&amp;gt;noTime&amp;lt;/code&amp;gt;: World has no credit&lt;br /&gt;
** &amp;lt;code&amp;gt;startup&amp;lt;/code&amp;gt; The server must be started. The client waits 2 seconds and tries again.&lt;br /&gt;
* &amp;lt;code&amp;gt;ip&amp;lt;/code&amp;gt;: The IP address of the server hosting the world&lt;br /&gt;
* &amp;lt;code&amp;gt;port&amp;lt;/code&amp;gt;: The port the world is hosted on&lt;br /&gt;
* &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt;: The key for the client to use when connecting to the world. Used to validate that the user is authenticated to their nickname. Generated as follows:&lt;br /&gt;
** Take the string given to the server binary in the &amp;lt;code&amp;gt;--cloud_salt&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
** Append the user&amp;#039;s alias&lt;br /&gt;
** Hash to MD5&lt;/div&gt;</summary>
		<author><name>Eli</name></author>
	</entry>
</feed>