ดูสินค้ารายชิ้น

GET/api/v1/products/{product_id}
สิทธิ์ที่ต้องใช้:catalog:read

ดูรายละเอียดล่าสุดและ ราคาจริงที่ใช้สั่งซื้อได้ ของสินค้าหนึ่งชิ้น · สิ่งที่ต้องทำต่อขึ้นกับ type ของสินค้าชิ้นนั้น · cdkey กับ account1price ที่ได้จากหน้านี้คือค่าที่ต้องส่งเป็น expected_price ตอนสั่งซื้อ และใช้แค่ product_id ก็สั่งได้เลย · account2 — ยังสั่งจากหน้านี้ไม่ได้ เพราะสินค้ามือสองหนึ่งรายการมีบัญชีขายอยู่หลายชิ้น คนละสภาพคนละราคา ต้องไปต่อที่ GET /api/v1/products/{product_id}/items เลือกบัญชีมาหนึ่งชิ้น แล้วใช้ราคาและ item_id ของชิ้นนั้นแทน

available ที่ไม่มีค่า แปลว่ายังไม่ได้ตรวจ ไม่ใช่ของหมด

ฟิลด์นี้มีได้แค่ false (ยืนยันแล้วว่าหมด) กับ null (ยังไม่ได้ตรวจกับต้นทาง) ไม่มีค่า true — เอนด์พอยต์แคตตาล็อกตอบจากข้อมูลที่ร้านมีอยู่แล้ว ไม่ได้ไปถามต้นทางทุกครั้งที่เรียก สินค้าส่วนใหญ่จึงกลับมาเป็น null ซึ่งเป็นความจริง คือรอบนี้ไม่มีใครไปตรวจสต็อกของสินค้าชิ้นนั้น · ห้ามเทียบ available === true และห้ามเขียนเงื่อนไขทำนองว่าไม่ใช่ true คือของหมด — อ่านแบบนั้นคือซ่อนแคตตาล็อกเกือบทั้งก้อน ซึ่งเป็นสินค้าที่ขายได้จริง ออกจากหน้าร้านของคุณเอง · ให้ซ่อนเฉพาะชิ้นที่เป็น false · สต็อกจริงถูกตรวจกับต้นทางอีกครั้ง ตอนสั่งซื้อ ซึ่งเป็นจุดเดียวที่คำตอบเรื่องของมีหรือไม่มีเชื่อถือได้

ราคาที่ได้กลับมาหักส่วนลดแล้ว ห้ามหักซ้ำอีกรอบ

price คือจำนวนบาทที่ คีย์ใบนี้ต้องจ่าย ไม่ใช่ราคาป้ายของร้าน และ discount_percent บอกว่าหักออกจากราคาป้ายไปแล้วกี่เปอร์เซ็นต์ · เอาส่วนลดของคุณไปหักซ้ำอีกรอบจะได้ราคาที่ระบบไม่มีวันยอมรับ แล้วทุกคำสั่งซื้อจะถูกปฏิเสธเรื่องราคาโดยไม่มีอะไรบอกว่าทำไม · ส่วนลดของคุณตั้งไว้เป็นตัวเลขเดียว แต่ สินค้าแต่ละประเภทมีเพดานของตัวเอง และนอกจากนั้นสินค้าแต่ละชิ้นยังมี ราคาขั้นต่ำ ของตัวเอง ที่ดันราคากลับขึ้นมาเมื่อหักส่วนลดแล้วจะต่ำกว่าที่เรารับได้ (แต่ไม่เกินราคาป้าย) นี่คือเหตุผลที่ discount_percent ต่ำกว่าเพดานได้ — ทั้งสองกรณีมีให้ดูในคำตอบของหน้านี้แล้ว · คุณอ่านส่วนลดที่คิดเสร็จแล้วรายประเภทได้จาก GET /api/v1/me ที่ฟิลด์ discount.effective_percent แต่ อย่าคำนวณราคาเองฝั่งคุณ ให้ใช้ราคาที่เอนด์พอยต์นี้คืนมา · ราคาขยับตลอดเวลา จะเก็บไว้นานแค่ไหนก็ได้ แต่ต้องอ่านใหม่ทุกครั้งก่อนสั่งซื้อ

การปฏิเสธที่ด่านยืนยันตัวตนเกิดกับเอนด์พอยต์นี้ด้วย

ห้ารหัสของด่านยืนยันตัวตน — invalid_key (401) · key_revoked (401) · insufficient_scope (403) · quota_exceeded (429) · too_many_inflight (429) — เกิดได้กับทุกเอนด์พอยต์ รวมทั้งเอนด์พอยต์นี้ เพราะถูกโยนตั้งแต่ก่อนคำขอจะเดินไปถึงตรรกะของหน้านี้เลยสักบรรทัด (scope ที่ต้องมีคือค่าที่ประกาศไว้หัวหน้านี้) · แท็บคำตอบด้านบนจึงไล่เฉพาะสิ่งที่เอนด์พอยต์นี้เองตอบ ไม่ได้แปลว่าห้ารหัสนั้นเกิดที่นี่ไม่ได้ · รายละเอียดครบทุกตัวอยู่ที่ หน้าเอนด์พอยต์ตัวตนที่ /developers/access/me ที่เดียว ทั้ง HTTP status ของแต่ละตัว · ตัวไหนกินโควตารายวันบ้าง · header อะไรกลับมาบ้าง · และทำไม 429 สองตัวต้องรับมือคนละแบบ — จงใจไม่คัดลอกมาไว้ทุกหน้า เพราะสำเนาที่สองคือที่ที่ลืมแก้ตามในวันที่กติกาเปลี่ยน

ข้อมูลที่ต้องส่ง

Path

ชื่อชนิดวิธีใช้
product_idบังคับstring
รหัสสินค้า — ค่าเดียวกับฟิลด์ id ที่รายการสินค้าคืนมา · ค่านี้ถูกตัดช่องว่างหัวท้ายก่อนใช้ ค่าที่มีแต่ช่องว่างจึงถูกปฏิเสธตั้งแต่ต้นทางด้วย 400 bad_request โดยไม่ไปค้นอะไรเลย

Header

ชื่อชนิดวิธีใช้
Authorizationบังคับstring
คีย์ของคุณในรูป Bearer <คีย์> ต้องส่งมาทุกคำขอ ไม่มีวิธียืนยันตัวตนทางอื่น

ข้อมูลที่ได้รับ

ชื่อชนิดวิธีใช้
productอ็อบเจกต์
สินค้าที่ขอมา · รูปร่างเหมือนหนึ่งรายการในลิสต์ของ GET /api/v1/products เป๊ะทุกฟิลด์ ต่างกันแค่ ราคาที่นี่คิดราคาขั้นต่ำรายสินค้าให้แล้ว จึงเป็นราคาที่ใช้สั่งซื้อได้จริง
product.idสตริง หรือ null
รหัสสินค้า เป็นค่าเดียวกับ product_id ที่ใช้ตอนสั่งซื้อ และใช้ตอนขอรายการบัญชีมือสองรายชิ้น
product.gameสตริง หรือ null
ชื่อสินค้าที่แสดงให้ลูกค้าเห็น
product.platformสตริง หรือ null
platform ของสินค้า — ค่าเดียวกับที่ใช้เป็นพารามิเตอร์ platform ของรายการสินค้า
product.typeสตริง หรือ null
ประเภทสินค้า และเป็นฟิลด์ที่บอกว่าจะสั่งซื้อชิ้นนี้ยังไง: cdkey (คีย์เกม)
รายละเอียดและข้อควรระวัง
  • account1 (บัญชีเกมใหม่ที่ยังไม่เคยถูกใช้)
  • account2 (บัญชีเกมมือสอง)
  • สองประเภทแรกซื้อด้วย product_id อย่างเดียว ส่วน account2 ต้องไปเลือกบัญชีรายชิ้นก่อน แล้วส่ง item_id ของชิ้นนั้นไปกับคำสั่งซื้อด้วย
product.slugสตริง หรือ null
ชื่อที่ normalize แล้ว ใช้ประกอบลิงก์หน้าร้าน และเป็นค่าเดียวกับที่พารามิเตอร์ search ของรายการสินค้าเทียบด้วย
product.imageสตริง หรือ null
URL ปกแนวตั้ง · เป็น null เมื่อไม่มีรูปที่ใช้ได้
product.ratingตัวเลข หรือ null
คะแนนของเกมจากแหล่งข้อมูลของเรา — ไม่ใช่คะแนนรีวิวของร้าน
product.genresอาร์เรย์ของสตริง
แนวเกม · ค่าไหนในนี้ก็ใช้เป็นพารามิเตอร์ genre ของรายการสินค้าได้ · อาร์เรย์ว่างแปลว่าไม่มีการบันทึกแนวไว้
product.availablefalse หรือ null
สถานะของในสต็อก มีแค่สองค่าเท่านั้น
รายละเอียดและข้อควรระวัง
  • false = ยืนยันแล้วว่าหมด
  • null = ยังไม่ได้ตรวจ ไม่ได้แปลว่าหมด
  • ฟิลด์นี้ไม่มีค่า true ให้ซ่อนเฉพาะชิ้นที่เป็น false และห้ามเขียนเงื่อนไขที่รอค่า true
product.priceตัวเลข
ยอดที่คีย์นี้ต้องจ่าย หน่วยบาท หักส่วนลดและคิดราคาขั้นต่ำให้เรียบร้อยแล้ว
รายละเอียดและข้อควรระวัง
  • สำหรับ cdkey และ account1 นี่คือค่าที่ส่งเป็น expected_price ได้เลย
  • ส่วน account2 ห้ามใช้ค่านี้ ให้ใช้ราคาของบัญชีรายชิ้นที่คุณเลือกแทน
product.discount_percentตัวเลข
ส่วนลดที่คุณได้จริงกับสินค้าชิ้นนี้ หน่วยเปอร์เซ็นต์
รายละเอียดและข้อควรระวัง
  • หักออกจาก price ไปเรียบร้อยแล้ว ไม่ต้องเอาไปหักซ้ำ
  • ค่านี้ต่ำกว่าเพดานของประเภทสินค้าได้ เมื่อราคาไปชนราคาขั้นต่ำของสินค้าชิ้นนั้น

สถานะที่อาจได้รับ

สถานะรหัสความหมาย
200
cdkey / account1 — สั่งซื้อได้เลยที่ราคานี้
product.price คือค่าที่ต้องส่งเป็น expected_price และใช้แค่ product_id ก็สั่งซื้อได้แล้ว
รายละเอียดและข้อควรระวัง
  • product มีฟิลด์เหมือนกับหนึ่งรายการในลิสต์เป๊ะ คือ id
  • game
  • platform
  • type
  • slug
  • image
  • rating
  • genres
  • available
  • price
  • discount_percent
  • ฟิลด์ที่เป็น null แปลว่าค่านั้นอ่านไม่ได้หรือไม่มีอยู่ ไม่ใช่ค่าว่างที่มีความหมาย
  • สินค้าชิ้นเดียวกันนี้อยู่ในลิสต์ที่ราคา 440 ส่วนลด 12 แต่ที่นี่เป็น 450 กับ 10 เพราะหน้ารายการสินค้าข้ามการคิดราคาขั้นต่ำรายสินค้าไป ส่วนหน้านี้คิดให้ครบ จึงดันราคาขึ้นมาที่ขั้นต่ำ และส่วนลดที่ได้จริงเหลือ 10
  • ค่าที่ต้องส่งเป็น expected_price คือ 450 ไม่ใช่ 440
  • ทุกตัวอย่างในหน้านี้คือคำตอบที่คีย์สมมติซึ่งตั้งส่วนลดไว้ 12% ได้รับ และตัวเลขทั้งหมดเป็นของสมมติ ไม่มีอันไหนเป็นข้อมูลจริงของร้าน
200
account2 — ยังสั่งไม่ได้ ต้องไปเลือกบัญชีรายชิ้นก่อน
⚠️ price ของสินค้า account2 เป็นแค่ราคาเริ่มต้น (ชิ้นที่ถูกที่สุดเท่าที่ร้านรู้) ไม่ใช่ราคาที่คุณจะได้จ่าย
รายละเอียดและข้อควรระวัง
  • บัญชีมือสองแต่ละชิ้นไม่เหมือนกัน ราคาจริงจึงอยู่ที่ตัวบัญชีรายชิ้น
  • ขั้นตอนถัดไปคือเรียก GET /api/v1/products/{product_id}/items เลือกมาหนึ่งชิ้น แล้วใช้ price กับ item_id ของชิ้นนั้นตอนสั่งซื้อ
  • ราคาขั้นต่ำของสินค้าประเภทนี้ก็คิดกันที่ระดับชิ้นเช่นกัน ไม่ได้คิดที่ระดับสินค้า
400bad_request
ไม่ได้ใส่ product_id มาใน URL
ช่อง product_id ใน URL ว่างเปล่า หรือมีแต่ช่องว่าง (เราตัดช่องว่างหัวท้ายก่อนใช้เสมอ) · เติมค่าให้ถูกแล้วยิงใหม่ ไม่มีอะไรค้างอยู่กลางทาง
404product_not_found
ไม่มีสินค้ารหัสนี้ หรือถูกถอดออกจากการขายแล้ว
ลบสินค้าชิ้นนี้ออกจากแคตตาล็อกฝั่งคุณได้เลย ยิงซ้ำก็ไม่เปลี่ยนอะไร · สินค้าที่ถูกถอดออกกับสินค้าที่ไม่เคยมีอยู่ตอบด้วยรหัสเดียวกัน แยกจากกันไม่ได้โดยเจตนา
409price_unavailable
สินค้ามีอยู่ แต่ตอนนี้คิดราคาให้ไม่ได้
ข้ามชิ้นนี้ไปก่อนแล้วแจ้งเรา อย่าเพิ่งลบออกจากแคตตาล็อกฝั่งคุณ (ต่างจาก product_not_found ตรงที่สินค้ายังอยู่)
รายละเอียดและข้อควรระวัง
  • สาเหตุคือราคาป้ายของสินค้าชิ้นนี้อ่านไม่ได้
  • ไม่มีค่า หรือเป็นศูนย์หรือติดลบ
  • เราจึงไม่ประกาศราคาที่เรายืนยันไม่ได้ออกไป
อัปเดตล่าสุด 2026-09-07