Instance API: ผู้เล่น
GET / PUT / DELETE ผู้เล่นของ Instance พร้อม request body, response และตัวอย่างทุก endpoint
Instance API คืออะไร
จัดการผู้เล่นของ Instanceจากโปรแกรมของคุณ: ดูรายชื่อ เพิ่ม และลบ ทำงานเหมือนหน้า ผู้เล่น ในแท็บของ Instance ทุกประการ (ผู้เล่นที่เพิ่มด้วย API ก็ถูกตรวจกับ Mojang ในเบื้องหลังเหมือนการเพิ่มด้วยมือ) ต้องใช้ Basic auth ของแอป ดู ภาพรวมและแนวคิด API
ในหน้าแอป ส่วน Instance ต้องเลือก Instance นั้นให้แอปก่อน และติ๊กสิทธิ์ที่ต้องใช้ (players:read สำหรับ GET, players:write สำหรับ PUT และ DELETE)
สิทธิ์และการตอบกลับเมื่อไม่มีสิทธิ์
| สถานการณ์ | ผลลัพธ์ |
|---|---|
| Instance ไม่มีอยู่ | 404 Instance not found |
| มีอยู่ แต่แอปไม่ได้รับ Instance นี้ | 404 Instance not found (ตอบเหมือนกรณีแรก เพื่อไม่ให้เดาชื่อ Instance ได้) |
| แอปได้รับ Instance นี้ แต่ไม่มีสิทธิ์ที่ต้องใช้ | 403 This application has no PLAYERS_READ access to that instance (หรือ PLAYERS_WRITE) |
| ตรวจตัวตนของแอปไม่ผ่าน | 401 Invalid client credentials |
GET /instances
/api/v1/instancesรายการ Instance ที่แอปนี้ได้รับ พร้อมสิทธิ์ ไม่ต้องใช้สิทธิ์ใดๆ เรียกเพื่อตรวจว่าตั้งค่าถูกหรือหาชื่อ Instance (name) ที่ใช้ใน path
Request: ไม่มี body ไม่มีพารามิเตอร์
type ApplicationScope = "PLAYERS_READ" | "PLAYERS_WRITE";
interface InstanceGrant {
name: string; // ตัวระบุของ Instance ใช้ใน path เช่น "wanwera"
title: string; // ชื่อที่แสดง
scopes: ApplicationScope[]; // สิทธิ์ที่แอปมีต่อ Instance นี้ (อย่างน้อย 1)
}
// 200
interface ListInstancesResponse {
statusCode: 200;
data: InstanceGrant[]; // เรียงตามเวลาที่ได้รับ เก่าไปใหม่ ว่างได้ถ้ายังไม่ได้รับ Instance ใด
}curl -u "$CLIENT_ID:$CLIENT_SECRET" https://api-dms-launcher.mckimkung.in.th/api/v1/instances{
"statusCode": 200,
"data": [
{ "name": "wanwera", "title": "WANWERA", "scopes": ["PLAYERS_READ", "PLAYERS_WRITE"] },
{ "name": "lobby", "title": "Lobby", "scopes": ["PLAYERS_READ"] }
]
}GET /instances/{name}/players
/api/v1/instances/{name}/playersสิทธิ์ที่ต้องมี: PLAYERS_READ
พารามิเตอร์ใน path:
| ชื่อ | ชนิด | รายละเอียด |
|---|---|---|
name | string | ฟิลด์ name ของ Instance (ตรงตัวพิมพ์เล็กใหญ่) ต้อง URL-encode ถ้ามีอักขระพิเศษ |
Request body: ไม่มี ไม่มี query string และไม่แบ่งหน้า (ส่งผู้เล่นทั้งหมดกลับมา)
type PlayerStatus = "ACTIVE" | "PENDING" | "NOT_FOUND";
interface InstancePlayer {
uuid: string | null; // 32 หลักตัวพิมพ์เล็ก ไม่มีขีด เป็น null ได้ในสถานะ PENDING ที่ยังรู้แค่ชื่อ
name: string | null; // ชื่อผู้เล่น เป็น null ได้ในสถานะ PENDING ที่ยังรู้แค่ uuid
status: PlayerStatus;
joinedAt: string; // ISO 8601 UTC เวลาที่ถูกเพิ่มเข้า Instance
}
// 200
interface ListPlayersResponse {
statusCode: 200;
data: InstancePlayer[]; // เรียงตามเวลาที่เพิ่มเข้ามา ใหม่ไปเก่า
}| status | ความหมาย | uuid / name |
|---|---|---|
| ACTIVE | ผู้เล่นที่ตรวจกับ Mojang แล้ว | มีทั้งสองค่า |
| PENDING | เพิ่มแล้ว กำลังรอระบบตรวจกับ Mojang เป็นกลุ่ม (ปกติไม่กี่วินาทีถึงนาที) เมื่อตรวจเสร็จจะเปลี่ยนเป็น ACTIVE เอง | อย่างน้อยหนึ่งค่า อีกค่าอาจเป็น null |
| NOT_FOUND | Mojang ตอบว่าไม่มีผู้เล่นนี้ ระบบหยุดลองใหม่จนกว่าเจ้าของ Instance กดตรวจอีกครั้งในหน้าผู้เล่น | ค่าที่ถูกเพิ่มไว้ |
curl -u "$CLIENT_ID:$CLIENT_SECRET" https://api-dms-launcher.mckimkung.in.th/api/v1/instances/wanwera/players{
"statusCode": 200,
"data": [
{ "uuid": "069a79f444e94726a5befca90e38aaf5", "name": "Notch", "status": "ACTIVE", "joinedAt": "2026-10-06T08:30:00.000Z" },
{ "uuid": "853c80ef3c3749fdaa49938b674adae6", "name": null, "status": "PENDING", "joinedAt": "2026-10-06T08:31:12.000Z" }
]
}PUT /instances/{name}/players
/api/v1/instances/{name}/playersสิทธิ์ที่ต้องมี: PLAYERS_WRITE เพิ่มผู้เล่นเข้า Instance ส่งซ้ำได้ ไม่เพิ่มคนที่มีอยู่แล้ว (นับเป็น duplicates)
Request body (application/json):
| ฟิลด์ | ชนิด | จำเป็น | ข้อกำหนด |
|---|---|---|---|
players | PlayerInput[] | ใช่ | อาร์เรย์ 1-100 รายการ เกินกว่านี้ตอบ 400 (ส่งแบ่งหลายครั้ง) |
players[].uuid | string | ใช่ | 1-64 ตัวอักษร ต้องเป็น UUID ของ Minecraft: 32 หลักฐานสิบหก มีขีดหรือไม่ก็ได้ ตัวพิมพ์เล็กหรือใหญ่ก็ได้ ถ้าไม่ใช่ UUID ที่อ่านได้ รายการนั้นไม่ถูกเพิ่มและถูกส่งกลับใน invalid |
players[].username | string | ไม่ | ไม่เกิน 32 ตัวอักษร เป็นคำใบ้สำหรับแสดงผลเท่านั้น ใช้เมื่อเป็นชื่อ Minecraft ที่ถูกต้อง (A-Z a-z 0-9 _ ยาว 1-16) ระบบไม่เชื่อชื่อนี้ ยึด uuid เป็นตัวระบุ และชื่อจริงมาจาก Mojang |
รายการต้องมี uuid เสมอ การส่งเฉพาะชื่อผู้เล่นผ่าน API นี้ไม่รองรับ (หน้าผู้เล่นบนเว็บรองรับการเพิ่มด้วยชื่อ แต่ API นี้ตั้งใจรับ uuid ที่ยืนยันแล้วเพื่อไม่ให้ชื่อที่เปลี่ยนมือกันได้ทำให้เพิ่มผิดคน)
interface PlayerInput {
uuid: string; // 1..64 ตัวอักษร ต้องอ่านเป็น UUID ได้ ไม่งั้นเข้า invalid
username?: string; // 0..32 ตัวอักษร คำใบ้แสดงผล ไม่ถูกเชื่อ
}
interface PutPlayersRequest {
players: PlayerInput[]; // 1..100 รายการ
}
// 200
interface PutPlayersResponse {
statusCode: 200;
data: {
added: number; // ผู้เล่นที่ระบบรู้จักอยู่แล้ว ถูกเพิ่มเข้า Instance ทันที (เป็น ACTIVE เลย)
pending: number; // รายการใหม่ที่เข้าคิวรอตรวจกับ Mojang (เป็น PENDING ก่อน)
duplicates: number; // รายการที่อยู่ใน Instance อยู่แล้ว (ไม่เพิ่มซ้ำ)
invalid: string[]; // ค่า uuid ที่ส่งมาแล้วอ่านไม่ได้ คืนตามที่ส่งมา ไม่ได้ทำอะไร
};
}ตัวเลข added + pending + duplicates + จำนวน invalid อาจน้อยกว่าจำนวนที่ส่ง เพราะ UUID ซ้ำกันในคำขอเดียวกันถูกรวมเป็นหนึ่ง (ไม่นับเป็น duplicates) ผู้เล่นที่เพิ่มด้วยวิธีนี้ถูกบันทึกที่มาเป็น Application: ชื่อแอป
curl -X PUT -u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"players":[{"uuid":"069a79f4-44e9-4726-a5be-fca90e38aaf5","username":"Notch"},{"uuid":"not-a-uuid"}]}' \
https://api-dms-launcher.mckimkung.in.th/api/v1/instances/wanwera/players{
"statusCode": 200,
"data": { "added": 1, "pending": 0, "duplicates": 0, "invalid": ["not-a-uuid"] }
}ข้อผิดพลาดของ PUT
| สถานะ | เมื่อไหร่ |
|---|---|
400 | Validation failed ไม่ส่ง players, ว่าง, เกิน 100 รายการ หรือชนิดฟิลด์ผิด (มีรายการ errors บอกตำแหน่ง) |
403 | ไม่มีสิทธิ์ PLAYERS_WRITE ต่อ Instance นี้ |
404 | ไม่พบ Instance หรือแอปไม่ได้รับ Instance นี้ |
DELETE /instances/{name}/players
/api/v1/instances/{name}/playersสิทธิ์ที่ต้องมี: PLAYERS_WRITE ลบผู้เล่นหลายคนตาม uuid คำขอ DELETE นี้มี body ซึ่งไลบรารีบางตัวตัดทิ้ง ถ้าไลบรารีของคุณส่ง body กับ DELETE ไม่ได้ ใช้แบบลบทีละคนด้านล่าง
Request body (application/json):
| ฟิลด์ | ชนิด | จำเป็น | ข้อกำหนด |
|---|---|---|---|
players | { uuid: string }[] | ใช่ | อาร์เรย์ 1-100 รายการ |
players[].uuid | string | ใช่ | 1-64 ตัวอักษร UUID ของผู้เล่นที่จะลบ (มีขีดหรือไม่ก็ได้) ถ้าอ่านไม่ได้จะเข้า invalid |
interface DeletePlayersRequest {
players: { uuid: string }[]; // 1..100 รายการ
}
// 200
interface DeletePlayersResponse {
statusCode: 200;
data: {
removed: number; // จำนวนแถวที่ถูกลบจริง
notOnInstance: string[]; // uuid (32 หลัก ตัวพิมพ์เล็ก) ที่ไม่ได้อยู่ใน Instance นี้ ไม่ได้ทำอะไร
invalid: string[]; // ค่าที่ส่งมาแล้วอ่านเป็น UUID ไม่ได้ คืนตามที่ส่งมา
};
}- ลบได้ทั้งผู้เล่นสถานะ ACTIVE และ PENDING ที่ทราบ uuid แล้ว ผู้เล่นที่ยังเป็น PENDING ซึ่งรู้แค่ชื่อ (ไม่มี uuid) ลบด้วย API นี้ไม่ได้ ให้ลบในหน้าผู้เล่น
- เรียกลบซ้ำได้ ครั้งที่สองจะได้
removed: 0และ uuid นั้นอยู่ในnotOnInstance - การลบผู้เล่นออกจาก Instance ไม่ลบบัญชีผู้เล่นออกจากระบบ ผู้เล่นคนเดิมยังอยู่ใน Instance อื่น
curl -X DELETE -u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"players":[{"uuid":"069a79f444e94726a5befca90e38aaf5"}]}' \
https://api-dms-launcher.mckimkung.in.th/api/v1/instances/wanwera/players{
"statusCode": 200,
"data": { "removed": 1, "notOnInstance": [], "invalid": [] }
}ลบทีละคน: DELETE /instances/{name}/players/{uuid}
/api/v1/instances/{name}/players/{uuid}สิทธิ์ที่ต้องมี: PLAYERS_WRITE ไม่มี request body ผลลัพธ์รูปแบบเดียวกับ DELETE ด้านบน (ชนิด DeletePlayersResponse)
| พารามิเตอร์ใน path | ชนิด | รายละเอียด |
|---|---|---|
name | string | name ของ Instance |
uuid | string | UUID ของผู้เล่น มีขีดหรือไม่ก็ได้ ถ้าอ่านไม่ได้จะอยู่ใน invalid (ตอบ 200 และ removed: 0) |
curl -X DELETE -u "$CLIENT_ID:$CLIENT_SECRET" \
https://api-dms-launcher.mckimkung.in.th/api/v1/instances/wanwera/players/069a79f4-44e9-4726-a5be-fca90e38aaf5ตัวอย่างการใช้งานจริง
เพิ่มผู้เล่นแล้วรอให้ระบบตรวจกับ Mojang เสร็จ:
const API = "https://api.example.com/api/v1";
const headers = {
Authorization: "Basic " + Buffer.from(CLIENT_ID + ":" + CLIENT_SECRET).toString("base64"),
"Content-Type": "application/json",
};
async function addPlayers(instance, uuids) {
const res = await fetch(API + "/instances/" + encodeURIComponent(instance) + "/players", {
method: "PUT",
headers,
body: JSON.stringify({ players: uuids.map((uuid) => ({ uuid })) }),
});
if (!res.ok) throw new Error((await res.json()).message);
const { data } = await res.json(); // { added, pending, duplicates, invalid }
// รายการ PENDING จะกลายเป็น ACTIVE (หรือ NOT_FOUND) เอง
if (data.pending > 0) {
for (let i = 0; i < 10; i++) {
await new Promise((r) => setTimeout(r, 3000));
const list = await (await fetch(API + "/instances/" + instance + "/players", { headers })).json();
if (!list.data.some((p) => p.status === "PENDING")) break;
}
}
return data;
}ดูชนิดข้อมูลทั้งหมดและตารางข้อผิดพลาดที่ อ้างอิงชนิดข้อมูลและข้อผิดพลาด

