ボット向けサーバーAPI
Millida HostingのクライアントAPIについて説明します。キーの発行、権限、サーバー管理、独自のボットやスクリプトからのコンソールストリーミングを扱います。
更新日 2026年10月13日
コントロールパネルでできることはすべて、自分のコードからも実行できます。スケジュールでサーバーを起動したり、Discord にステータスを表示したり、ボットからコマンドを送信したりできます。
キー
API は有料プランであればどこでも利用できます。ファイル、SFTP、チームアクセスと同じ場所です。無料プランではキーは発行されません。キーは同じ共有アクセスを、ボット向けに提供するものだからです。
「プレイヤーとアクセス」セクション → 「API キー」 → 「発行」。キーに許可されている操作を確認してください。権限は共有アクセスと同じです。
キーが表示されるのは一度だけです。保存されるのはフィンガープリントのみです。紛失した場合は、新しいキーを発行し、古いキーを無効化してください。
キーは Authorization: Bearer mhk_live_... ヘッダーで渡します。
メソッド
ベース URL — https://millida.net/v2/hosting/api。
| メソッド | 動作 | 必要な権限 |
|---|---|---|
GET /server | サーバーカード | console |
GET /status | ステータスとオンライン状況 | console |
POST /start | 起動 | start |
POST /stop | 停止 | start |
POST /restart | 再起動 | start |
POST /command | コンソールへのコマンド | console |
GET /console | ライブログ(SSE) | console |
GET /files?path= | ファイル一覧 | files |
GET /files/configs | フォームが読み取る設定ファイル | files |
GET /files/config?path= | 型付きのファイル設定 | files |
POST /files/config | ファイル設定の変更 | files |
GET /backups | バックアップ一覧 | backups |
POST /backups | バックアップの作成 | backups |
GET /antibot | 対ボット設定、バックエンド、ファイアウォールルール | protection |
PUT /antibot | 保護設定の変更 | protection |
GET /antibot/overview?range= | hour、day、week の接続数と拒否数 | protection |
POST /antibot/backends | バックエンドの追加 {"address":"host:port","label":"..."} | protection |
DELETE /antibot/backends/{id} | バックエンドの削除 | protection |
POST /antibot/rules | ファイアウォールルール {"kind":"allow"|"deny","cidr":"1.2.3.0/24"} | protection |
DELETE /antibot/rules/{id} | ルールの削除 | protection |
POST /antibot/verify-domain/check | 確認ページ用ドメインの DNS チェック | protection |
例: サーバーを起動してオンラインになるまで待機する
KEY="mhk_live_xxx"
API="https://millida.net/v2/hosting/api"
curl -sX POST "$API/start" -H "Authorization: Bearer $KEY"
until curl -s "$API/status" -H "Authorization: Bearer $KEY" | grep -q RUNNING; do
sleep 5
done
echo "server online"
バックアップはバックグラウンドで作成されます
POST /backups はすぐに {"id":"..."} を返しますが、アーカイブ自体はノード上で組み立てられます。数ギガバイトのワールドであれば数分かかります。準備状況は GET /backups の status フィールドで確認してください。pending — まだ組み立て中、ready — ストレージに保存済み(このときに実際の sizeMb が表示されます)、failed — 組み立てに失敗。
ID=$(curl -sX POST "$API/backups" -H "Authorization: Bearer $KEY" | jq -r .id)
until curl -s "$API/backups" -H "Authorization: Bearer $KEY" \
| jq -e --arg id "$ID" '.[] | select(.id==$id) | select(.status=="ready")' >/dev/null; do
sleep 15
done
echo "backup ready"
バックアップの実行中は、同じサーバーで 2 つ目のバックアップを作成できません。ノードは 1 つずつ処理します。
ライブコンソール
GET /console は Server-Sent Events ストリームを返します。各行は data: プレフィックス付きで届きます。WebSocket は不要です。SSE はあらゆるプロキシを通過します。
知っておくべきこと
- キーによるすべての操作はログに記録されます。サーバーログには実行者として「API key N」と表示されます。人とボットの両方がサーバーを操作する場合にまさに必要なものです。
- レート制限はアドレスごとではなくキーごとに計算されます。IP を変えても制限は回避できず、同じオフィスネットワークの隣人が制限を消費することもありません。通常の自動化には十分な余裕がありますが、1 秒ごとにステータスをポーリングすると制限に達します。10〜15 秒に 1 回で十分です。コンソールストリームは 1 分間に最大 10 回まで開けます。メッセージごとに新しい接続を開かず、1 つの接続を維持してください。
- サーバーが停止された場合や、プランが有料でなくなった場合、キーは即座に機能しなくなります。そのために手動で無効化する必要はありません。
- サーバーごとに最大 5 つのキー。不要なものは無効化してください。
対ボット保護
GET /antibot は設定を 2 つのフィールドで返します。config — サーバー自身の設定です。存在しないうちは null で、サーバーはデフォルト(default フィールド)で保護されています。effective は常に存在します。これは現在有効な設定、または最初の編集後にサーバーが適用する設定です。値はここから読み取ってください。
PUT /antibot は変更したいフィールドのみを受け付けます。
curl -sX PUT "$API/antibot" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"preset":"balanced"}'
レベル(preset): off、under_attack、balanced、aggressive、custom。レベルはチェック値を自動的に展開するため、手動で設定する場合は custom を選択し、チェックを送信してください。checkCaptcha、checkPhysics、checkKeepAlive、checkTeleport、checkBrand、checkPing、checkTransfer、checkClientSettings — それぞれ off、under_attack、always のいずれかです。アドレスリスト(vpnMode、datacenterMode、torMode)— off、log、block。地理フィルター — geoMode(off、allow、deny)と geoCountries(国コード、例: ["RU","BY"])。
転送シークレットは API では発行も変更もできません。パネルでオーナーにのみ表示されます。
設定ファイルの設定
GET /files/config?path=server.properties は解析済みのファイルを返します。各エントリには型、現在の値、「再起動が必要」フラグが含まれます。
{
"path": "server.properties",
"format": "properties",
"options": [
{ "key": "pvp", "type": "boolean", "value": "true", "owner": "sync", "requiresRestart": false },
{ "key": "difficulty", "type": "select", "value": "normal", "values": ["peaceful", "easy", "normal", "hard"], "owner": "sync", "requiresRestart": false },
{ "key": "server-port", "type": "integer", "value": "25565", "owner": "platform", "requiresRestart": true }
]
}
owner はそのエントリに対して何ができるかを示します。platform — 値はホスティング側が設定し、編集は拒否されます。sync — エントリはパネルとファイルの両方に存在します。file — ファイルのみが認識しています。
書き込みでは送信したキーのみが変更され、ファイル内のその他はすべてそのまま残ります。
curl -sX POST "$API/files/config" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"path":"server.properties","values":{"pvp":"false","difficulty":"hard"}}'
フォームは .properties、.yml/.yaml、.toml を読み取ります。パネルが関知しないプラグインの設定ファイルも含まれます。フィールドの型は値から推測されます。ネストされたキーはドットで指定します。settings.bungeecord、advanced.compression-threshold。
ファイル全体は引き続き GET/PUT /files/content?path= で利用できます。どちらのパスも同じ場所に書き込みます。
Node.js と Python の既成クライアント
以下は最小構成のクライアントです。ステータスを確認し、サーバーを起動してチャットに書き込みます。キーは環境変数 MILLIDA_KEY から取得します。git に入るコードに貼り付けないでください。エラー応答は message フィールドを持つ JSON です。ボットはこれをログに記録してください。
Node.js 18 以上(組み込みの fetch):
const API = 'https://millida.net/v2/hosting/api';
const KEY = process.env.MILLIDA_KEY;
async function call(method, path, body) {
const res = await fetch(`${API}${path}`, {
method,
headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
body: body ? JSON.stringify(body) : undefined,
});
if (!res.ok) throw new Error(`${method} ${path}: ${res.status} ${await res.text()}`);
return res.status === 204 ? null : res.json();
}
const status = await call('GET', '/status');
if (status.status !== 'RUNNING') await call('POST', '/start');
await call('POST', '/command', { command: 'say Hello from the bot' });
Python 3 と requests ライブラリ、さらにライブコンソールの読み取り:
import os
import requests
API = "https://millida.net/v2/hosting/api"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['MILLIDA_KEY']}"
def call(method, path, body=None):
res = session.request(method, API + path, json=body, timeout=15)
res.raise_for_status()
return res.json() if res.content else None
status = call("GET", "/status")
if status["status"] != "RUNNING":
call("POST", "/start")
call("POST", "/command", {"command": "say Hello from the bot"})
with session.get(API + "/console", stream=True, timeout=None) as stream:
for line in stream.iter_lines(decode_unicode=True):
if line and line.startswith("data:"):
print(line[5:].strip())
