API สาธารณะ & คีย์ API

เข้าถึงพื้นที่ทำงานผ่านโปรแกรม — อ่านโปรเจกต์ เซสชัน เหตุการณ์กำหนดเองและเซกเมนต์ รวมถึงแนบ ID ลูกค้ากับเซสชัน — ปกป้องด้วยคีย์ API ที่จำกัดเฉพาะพื้นที่ทำงาน

1. ภาพรวม

API ของ MousePlayer ดึงข้อมูลจากพื้นที่ทำงานไปแดชบอร์ด คลังข้อมูล หรือเครื่องมือภายในของคุณได้ นอกจากแนบ ID ลูกค้ากับเซสชัน (identify ต้องมีคีย์สิทธิ์เขียน ดูขอบเขตคีย์) API เป็นแบบ อ่านอย่างเดียว ไม่แก้หรือลบข้อมูลผ่าน API

  • URL หลัก: https://www.mouseplayer.com/api/v1/
  • ทุกคำตอบเป็น JSON
  • ทุกคำขอยืนยันด้วยคีย์ API และจำกัดอัตโนมัติเฉพาะพื้นที่ทำงานเจ้าของคีย์ — คีย์พื้นที่หนึ่งไม่มีวันเห็นข้อมูลอีกพื้นที่ แม้โดยบังเอิญ
  • บันทึกเล่นย้อนหลังเต็ม (เมาส์และภาพสแนปช็อต DOM) ไม่ เปิดผ่าน API คุณได้เมทาดาทาเซสชัน การดูหน้า เหตุการณ์กำหนดเอง และเซกเมนต์ — พอสร้างรายงานและแดชบอร์ดโดยไม่ส่งข้อมูลเล่นย้อนหลังดิบไปมา

2. การยืนยันตัวตน

สร้างและจัดการคีย์ในส่วน คีย์ API ของเมนูบัญชี (/api-keys) เจ้าของและผู้ดูแลพื้นที่ทำงานเท่านั้นที่สร้างหรือเพิกถอนคีย์ได้

เก็บคีย์เป็นความลับ คีย์ให้สิทธิ์อ่านทุกสิ่งในพื้นที่ทำงาน แสดงคีย์เต็มเพียงครั้งเดียวทันทีหลังสร้าง — เก็บในตัวจัดการรหัสผ่านหรือคลังความลับ หากสูญหายให้เพิกถอนแล้วสร้างใหม่

ส่งคีย์เป็นโทเค็น Bearer ในส่วนหัว Authorization ของทุกคำขอ:

# List projects in your workspace curl -H "Authorization: Bearer mp_live_..." \ https://www.mouseplayer.com/api/v1/projects

คีย์ที่ขาด ผิดรูปแบบ หรือเพิกถอนแล้วจะได้รับคำตอบ 401:

{ "error": "Invalid or missing API key. Use: Authorization: Bearer <key>" }

แพ็กเกจที่ต้องใช้

REST API เป็นส่วนหนึ่งของแพ็กเกจ Business และ Enterprise ใช้แพ็กเกจของ เจ้าของ พื้นที่ทำงาน สมาชิกที่เชิญจึงใช้สิทธิ์ตามนั้น ตรวจสอบใน ทุกคำขอ ไม่ใช่เฉพาะตอนสร้างคีย์ — หากลดแพ็กเกจพื้นที่ทำงาน คีย์เดิมหยุดทำงานและตอบ 403

ขอบเขตคีย์

คีย์แต่ละรายการมีขอบเขตในคำนำหน้า มองก็ทราบหน้าที่ — ไม่ว่าใน .env ทิกเก็ต หรือเทอร์มินัล

คำนำหน้าความหมาย
mp_ro_อ่านอย่างเดียว อ่านโปรเจกต์ เซสชัน เหตุการณ์ และเซกเมนต์ เปลี่ยนสิ่งใดไม่ได้
mp_rw_อ่านและเขียน ทุกอย่างข้างต้นพร้อมแนบ ID ลูกค้าผ่านปลายทาง identify
เลือกขอบเขตตอนสร้าง ค่าเริ่มต้นอ่านอย่างเดียว ใช้คีย์อ่านในปลายทางเขียนจะตอบ 403 พร้อมข้อความระบุสิทธิ์คีย์และสิ่งที่ปลายทางต้องการ เปลี่ยนขอบเขตภายหลังไม่ได้ — สร้างใหม่แล้วเพิกถอนคีย์เก่า

3. ขีดจำกัดอัตราคำขอ

แต่ละคีย์จำกัดที่ 60 คำขอต่อนาที นับในหน้าต่างเวลาเลื่อน เมื่อเกินจะได้คำตอบ 429 จนกว่าหน้าต่างจะว่าง:

{ "error": "Rate limit exceeded. Max 60 requests per minute." }

ต้องการขีดจำกัดสูงกว่านี้หรือไม่ ติดต่อ ฝ่ายช่วยเหลือ และบอกกรณีใช้งาน

4. ปลายทาง

GET/api/v1/projects

แสดงทุกโปรเจกต์ (ทรัพยากรที่ติดตาม) ในพื้นที่ทำงาน

{ "data": [ { "channelid": "955a45df5ee842cb", "domain": "yourdomain.com", "status": "active", "total_traffic_bytes": 27304765, "created_at": "2026-07-19 22:06:39", "last_used": "2026-08-05 01:12:55" } ] }

GET/api/v1/projects/{channelid}/sessions

แสดงเซสชันผู้เข้าชมที่บันทึกของโปรเจกต์ ใหม่ที่สุดก่อน แบ่งหน้าได้

พารามิเตอร์คำค้นคำอธิบาย
pageเลขหน้า ค่าเริ่มต้น 1
per_pageผลลัพธ์ต่อหน้า ค่าเริ่มต้น 25 สูงสุด 100
sinceเฉพาะเซสชันที่เริ่มวันนั้นหรือหลังจากนั้น (YYYY-MM-DD)
untilเฉพาะเซสชันที่เริ่มวันนั้นหรือก่อนหน้านั้น
{ "data": [ { "session_id": "s_kfmist058_1785795295504", "visitor_id": "v_sv90jdpzo_1785795296042", "custom_user_id": null, "country": "DE", "device_type": "desktop", "is_bot": 0, "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41", "duration_seconds": 105 } ], "pagination": { "page": 1, "per_page": 25, "total": 142, "total_pages": 6 } }

GET/api/v1/sessions/{session_id}

เมทาดาทาเซสชันเดียวพร้อมการดูหน้า ตั้งใจไม่รวมข้อมูลเล่นย้อนหลังเต็ม — ใช้โปรแกรมเล่นในแดชบอร์ดเพื่อดู

{ "data": { "session_id": "s_kfmist058_1785795295504", "channelid": "955a45df5ee842cb", "visitor_id": "v_sv90jdpzo_1785795296042", "country": "DE", "asn_org": "Deutsche Telekom AG", "referrer": "https://duckduckgo.com/", "device_type": "desktop", "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41", "duration_seconds": 105, "pageviews": [ { "pageview_id": 1199, "url": "https://yourdomain.com/pricing", "page_title": "Pricing", "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41" } ] } }

GET/api/v1/sessions/{session_id}/events

เหตุการณ์กำหนดเองที่เกิดในเซสชัน (เหตุการณ์เดียวกับที่ส่งด้วย mp('event', ...)) พร้อมพารามิเตอร์

{ "data": [ { "event_id": 61, "pageview_id": 1199, "event_name": "add_to_cart", "created_at": "2026-08-04 00:14:59", "params": { "item_id": "SKU_98765", "price": 299.99 } } ] }

GET/api/v1/projects/{channelid}/segments

แสดงเซกเมนต์ผู้เข้าชมที่กำหนดสำหรับโปรเจกต์ ทั้งเฉพาะโปรเจกต์และทั้งพื้นที่ทำงาน

{ "data": [ { "segment_id": 4, "name": "High Intent Visitors", "description": "Pageviews > 5", "badge_color": "cyan", "is_global": 0, "created_at": "2026-08-03 00:00:43" } ] }

5. แนบ ID ลูกค้าจากหลังบ้าน

เบราว์เซอร์มักไม่รู้ว่าใครนั่งอยู่ ผลิตภัณฑ์ B2B ทราบตัวตนหลังลงชื่อเข้าใช้ — ในหลังบ้าน ร้านค้าทราบตอนยืนยันคำสั่งซื้อ ปลายทางนี้สำหรับจังหวะนั้นโดยตรง

POST /api/v1/sessions/{session_id}/identify
Authorization: Bearer mp_live_xxxxxxxxxxxx
Content-Type: application/json

{"user_id": "customer-4711"}

// 200 OK
{"data": {"session_id": "s_a1b2c3", "user_id": "customer-4711",
          "changed": true, "previous": null, "webhook_queued": true}}

ID ปรากฏในรายการเซสชัน ค้นหาได้ และเว็บฮุก session_identified ทำงาน — จึงไปถึง CRM

เรียกสองครั้งด้วย ID เดิมได้อย่างปลอดภัย คำตอบกลับมาพร้อม "changed": false และไม่ส่งเว็บฮุก คำสั่งซื้อซ้ำไม่สร้างผู้สนใจรายที่สอง
สถานะเมื่อใด
400ขาดช่องข้อมูล หรือ user_id ยาวเกิน 128 อักขระ หรือมีอักขระควบคุม เราปฏิเสธแทนตัด — ID ที่ถูกย่อเงียบๆ จับคู่ CRM ไม่ได้แต่ยังดูสำเร็จ
404ไม่มีเซสชัน หรือ ไม่อยู่ในพื้นที่ทำงาน ตั้งใจใช้คำตอบเดียวกันทั้งคู่
403แพ็กเกจพื้นที่ทำงานไม่มี API

6. เว็บฮุก: ตรวจลายเซ็น

ตั้งเว็บฮุกแยกโปรเจกต์ในส่วน การเชื่อมต่อ ซึ่งมีความลับลงลายเซ็นด้วย ทุกการส่งมีส่วนหัว:

ส่วนหัวความหมาย
X-MousePlayer-Eventชื่อเหตุการณ์ เช่น session_identified
X-MousePlayer-Timestampวินาที Unix — ส่วนหนึ่งของข้อความลงลายเซ็น
X-MousePlayer-Attemptครั้งแรกเป็น 1 สูงขึ้นเมื่อลองใหม่
X-MousePlayer-Signaturesha256=<hex>

ลายเซ็นเป็น HMAC-SHA256 ของ timestamp + "." + raw body โดยใช้ความลับลงลายเซ็นของโปรเจกต์เป็นคีย์

// PHP
$erwartet = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($erwartet, $signature)) { http_response_code(401); exit; }

// Node
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
                                     .update(timestamp + '.' + rawBody).digest('hex');
ลงลายเซ็นบนเนื้อหา ดิบ ก่อนแยก JSON การ serialize ใหม่เปลี่ยนลำดับคีย์และช่องว่าง ลายเซ็นจึงไม่ตรง ปฏิเสธเวลาที่เก่ากว่าไม่กี่นาทีด้วย — นั่นคือหน้าที่เวลา

การส่งและลองใหม่

ลองส่งใหม่หลัง 1 นาที 5 นาที 15 นาที 1 ชั่วโมง และ 6 ชั่วโมง แล้วเลิก 4xx ที่ไม่ใช่ 408 และ 429 จะ ไม่ ลองใหม่ — หมายถึง "ไม่ใช่แบบนี้" ไม่ใช่ "ยังไม่ใช่ตอนนี้" ตอบ 2xx เร็วแล้วทำงานภายหลัง การส่งหมดเวลาใน 10 วินาที

เหตุการณ์ที่มี

เหตุการณ์ทำงานเมื่อ
session_identifiedเซสชันได้ ID ลูกค้าครั้งแรก — จากเบราว์เซอร์หรือ API
session_endedครั้งเดียวเมื่อเซสชันปิด
goal_reachedครั้งเดียวต่อเซสชันเมื่อเหตุการณ์กำหนดเองทำให้เป้าหมายสำเร็จ เฉพาะเป้าหมายประเภท "event" — ไม่ประเมินเป้าหมาย URL ระยะเวลา การดูหน้า หรือกรวย ส่งค่า goal_id, goal_name, goal_value และ currency
high_value_sessionเมื่อผู้เข้าชมข้ามเกณฑ์มูลค่าโปรเจกต์ครั้งแรกในวันนั้น เกณฑ์ มาจากการกระจายคะแนนของคุณ (เปอร์เซ็นไทล์ 90 ของ 90 วันล่าสุด) ไม่ใช่ค่าคงที่ และไม่มีจนกว่าจะให้คะแนนอย่างน้อย 20 คน ส่งค่า visitor_id, value_score, threshold และเซสชันที่น่าดูที่สุดในวันนั้น
funnel_dropoffเมื่อจบเซสชันที่เข้ากรวยแต่ไม่จบ ระบุขั้นตอนที่หยุด (dropped_at) การออกกลางคันคือการไม่มีเหตุการณ์ จึงทราบได้เมื่อเซสชันจบเท่านั้น ผู้ที่ไม่เคยเข้ากรวยไม่ใช่ออกกลางคันและไม่สร้างเหตุการณ์
high_friction_sessionครั้งเดียวต่อเซสชันเมื่อคะแนนอุปสรรคถึงเกณฑ์ครั้งแรก (ค่าเริ่มต้น 60 จาก 100) ส่งค่า friction_score พร้อมสัญญาณที่เป็นสาเหตุ (reasons) และสัญญาณที่ข้ามเกณฑ์ (trigger)
element_brokenครั้งเดียวเมื่อองค์ประกอบที่ติดตามไม่พบอะไรในทุกการดูหน้าที่ตรวจหลายวัน — มักหลังปรับเว็บใหม่ จะทำงานอีกเมื่อเครื่องหมายกลับมาตรงแล้วเสียอีกครั้ง เหตุการณ์นี้ ไม่ผูกกับเซสชันใด: session_id และ session_url เป็น null, link_url เปิดเครื่องหมายแทน และ subject_id ระบุเครื่องหมาย — เหมือนกันทุกเวอร์ชัน เพื่อให้ตัวเลือกใหม่ที่เสียอีกเชื่อมกับเหตุการณ์ที่เปิด ส่งค่า rule_id, rule_name, selector, page, checked_page_views, window_days และ last_matched ไม่มีข้อมูลผู้เข้าชม
element_recoveredแจ้งว่ากลับเป็นปกติสำหรับ element_broken ครั้งเดียวเมื่อเครื่องหมายพบองค์ประกอบจริงอีกครั้ง — การดูหน้าน้อยไปไม่เพียงพอ ส่งเฉพาะเมื่อ element_broken เคยส่งผ่านเว็บฮุก ไม่มีสวิตช์ของตนเอง การสมัคร element_broken รวมเหตุการณ์นี้ด้วย ใช้ค่า subject_id เดียวกัน PagerDuty จึงแก้เหตุการณ์และ Opsgenie ปิดแจ้งเตือน ส่งเพิ่ม matched_page_views และ checked_page_views
anomaly_detectedวันละครั้งเมื่อเมื่อวานต่างจาก 28 วันก่อนหน้าชัดเจน ทั้งเซสชันน้อยหรือมากขึ้นมาก อัตราเป้าหมายลด หรือเซสชันอุปสรรค/JS ผิดพลาดเพิ่ม ตัวชี้วัดและทิศทางเดียวกันเงียบหนึ่งสัปดาห์ (ปรับได้) เหตุการณ์นี้ ไม่ผูกกับเซสชันใด: session_id และ session_url เป็น null, link_url เปิดภาพรวมโปรเจกต์ และ subject_id ระบุตัวชี้วัด ทิศทาง และวัน ส่งค่า metric (sessions, goal_rate, friction_rate, js_error_rate, lcp_p75, inp_p75, cls_p75), direction, day, value, expected, sessions, robust_z, z_score และข้อความอ่านได้ summary กับ hint ไม่มีข้อมูลผู้เข้าชม สำหรับ Web Vitals ค่า measurements แทน sessions ส่วน page (ว่างสำหรับทั้งเว็บไซต์) และ device (desktop หรือ mobil) ระบุจุดที่เกิด link_url จึงเปิดแท็บ Web Vitals
rage_clickเมื่อพบคลิกด้วยความหงุดหงิด
error_detectedเมื่อเกิดข้อยกเว้นหน้าเว็บ
ceสมัครรวมเหตุการณ์กำหนดเองของคุณ โดย ไม่ รวมเหตุการณ์ข้างต้น — มีสวิตช์แยก

7. ข้อผิดพลาด & รหัสสถานะ

สถานะความหมาย
200สำเร็จ
401คีย์ API ขาด ผิดรูปแบบ หรือเพิกถอนแล้ว
404ไม่มีโปรเจกต์หรือเซสชันที่ขอ หรือไม่อยู่ในพื้นที่ทำงาน
429เกินขีดจำกัดอัตรา — ส่งเกิน 60 คำขอ/นาทีด้วยคีย์นี้
403แพ็กเกจพื้นที่ทำงานไม่มี REST API ข้อความระบุทั้งแพ็กเกจที่ต้องใช้และปัจจุบัน

8. หมายเหตุความปลอดภัย

  • คีย์อ่านอย่างเดียว (mp_ro_) เปลี่ยนอะไรไม่ได้ คีย์เขียน (mp_rw_) เพิ่มได้เฉพาะ ID ลูกค้า ไม่มีคีย์ใดลบข้อมูลหรือส่งออกข้อมูลเล่นย้อนหลังดิบได้
  • ทุกคำขอจำกัดพื้นที่ทำงานของคีย์อัตโนมัติ — ส่ง ID พื้นที่อื่นเพื่อดูข้อมูลคนอื่นไม่ได้
  • เพิกถอนคีย์ได้ทุกเมื่อที่ /api-keys มีผลทันที
  • ปฏิบัติต่อคีย์ API เหมือนรหัสผ่าน หากเผลอ commit ลงรีโพซิทอรีสาธารณะ ให้เพิกถอนทันทีแล้วสร้างใหม่

หน้าข้อมูลเหตุการณ์ที่จำกัดขนาด (API v1, 14 ตุลาคม 2026)

GET /api/v1/sessions/{session_id}/events คืนสูงสุด 100 เหตุการณ์โดยค่าเริ่มต้น ตั้ง per_page เป็นจำนวนเต็ม 1 ถึง 100 ตาม pagination.next_cursor โดยส่ง cursor ไม่เปลี่ยนในคำขอถัดไป ใช้เซสชันและพื้นที่ทำงานเดิม เรียงตาม created_at และ event_id เคอร์เซอร์ลงลายเซ็นและผูกกับเซสชัน/พื้นที่ทำงานนั้น ไม่คืนจำนวนรวมและเลขหน้า

อาร์เรย์ data และแผนที่ params เดิมยังมี pagination.returned คือจำนวนที่คืนจริง pagination.has_more ระบุว่ายังมีหน้า next_cursor เป็น null เมื่อจบ คำตอบจำกัด 524288 ไบต์ จึงอาจมีเหตุการณ์น้อยกว่า per_page แต่ละเหตุการณ์คืนสูงสุด 128 แถวพารามิเตอร์ params_truncated เป็น true หากมีมากกว่า สตริงแต่ละพารามิเตอร์ยังจำกัดฐานข้อมูล 255 อักขระ พารามิเตอร์ที่ตัดทอนไม่มีผ่านปลายทางนี้ ลด per_page ไม่เพิ่มเพดานพารามิเตอร์

ขนาดหน้าผิด เคอร์เซอร์เปลี่ยน หรือเป็นของเซสชัน/พื้นที่อื่นคืน 400 ข้อมูลเหตุการณ์เดี่ยวใหญ่เกินคืน 413 การตรวจสิทธิ์เดิมยังคืน 401, 403, 404 หรือ 409 ตามกรณี

ยังจำกัด 60 คำขอยืนยันตัวตนต่อคีย์ต่อนาที เกินแล้วคืน 429 พร้อม Retry-After: 60 หาก Redis หรือตัวจำกัดใช้ไม่ได้ คืน 503 พร้อม Retry-After: 5 ไม่ยอมให้ผ่านโดยไม่มีขีดจำกัด เคารพ Retry-After และเพิ่มช่วงรอสุ่ม อย่าลองซ้ำในลูปถี่ ฐานข้อมูลเหตุการณ์ล้มเหลวก็คืน 503 เคอร์เซอร์ไม่ตรึงสแนปช็อต การเพิ่มพร้อมกันที่มีเวลาเก่าอาจต้องสแกนใหม่

GET /api/v1/sessions/s_example/events?per_page=25
GET /api/v1/sessions/s_example/events?per_page=25&cursor=SIGNED_CURSOR

/api/v1/native เป็นเส้นทางควบคุมหลังบ้านเฉพาะ Dev สำหรับตัวอย่าง SDK เนทีฟ ยังคงปิดในระบบใช้งานจริง คีย์ Bearer หลังบ้านต้องมีสิทธิ์อ่านสำหรับ list/replay และเขียนสำหรับ register/grant/delete/disable มีการตรวจความพร้อม native-preview เพิ่มเติม ห้ามฝังคีย์ API พื้นที่ทำงานถาวรในแอปมือถือ