เอกสารอ้างอิง Chat API: บทสนทนา ข้อความ สถานะอ่านแล้ว และอีเวนต์

วิธีเรียก Hibira Chat API: คำขอที่ลงลายเซ็น บทสนทนาและสมาชิก ข้อความ การตามข้อความที่พลาด สถานะอ่านแล้วและจำนวนที่ยังไม่อ่าน โทเคนผู้ใช้สำหรับเบราว์เซอร์ ไฟล์แนบ พุช การกลั่นกรอง อีเวนต์ และขีดจำกัด

ก่อนเริ่มต้น

Chat API เก็บบทสนทนาและข้อความ แล้วส่งผ่านการเชื่อมต่อเรียลไทม์ที่แอปของคุณมีอยู่แล้ว เซิร์ฟเวอร์ของคุณเป็นผู้กำหนดว่าใครอยู่ในบทสนทนาใดและเป็นผู้เรียก API ส่วนไคลเอนต์แค่เชื่อมต่อ ลงชื่อเข้าใช้ และรับฟัง

  • อยู่ในช่วงเบต้า บัญชีใช้งานได้เมื่ออยู่ในเบต้าหรือมีแพ็กเสริม Chat ก่อนหน้านั้นทุกการเรียกจะได้ 403 the Chat API is not enabled for this app ลงชื่อในรายชื่อรอ เพื่อขอใช้งาน
  • Base URL: https://ws.hibira.io/apps/APP_ID/chat (ใช้โฮสต์ที่แสดงในหน้าแอปบนพอร์ทัล)
  • เนื้อหาเป็น JSON ข้อผิดพลาดตอบเป็น {"error": "..."} พร้อมสถานะ 4xx หรือ 5xx
  • ID ผู้ใช้เป็นของคุณเอง: ใช้ ID เดียวกับที่ไคลเอนต์ส่งให้ pusher.signin()

วิธีการทำงาน

  1. เซิร์ฟเวอร์ของคุณสร้างบทสนทนาและสมาชิก (PUT /conversations/{id})
  2. แต่ละไคลเอนต์เชื่อมต่อด้วย pusher-js แล้วเรียก pusher.signin() ในนามผู้ใช้ของตน ซึ่งจะสมัครรับ #server-to-user-<user_id> สมาชิกจึงไม่ต้องขออนุญาตช่องสำหรับแต่ละบทสนทนา
  3. เซิร์ฟเวอร์ของคุณส่งข้อความแทนผู้ใช้ (POST /conversations/{id}/messages) Hibira จะเก็บด้วยหมายเลขลำดับถัดไปของบทสนทนา (seq) แล้วส่ง chat.message ให้สมาชิกทุกคนและเรียกเว็บฮุก chat_message ของคุณ
  4. ไคลเอนต์ที่เคยออฟไลน์อ่านข้อความที่พลาดด้วย GET /conversations/{id}/messages?after=<seq ล่าสุดที่มี>

ทุกการเปลี่ยนแปลงจะถูกเก็บก่อนส่งอีเวนต์ใด ๆ หากแอปเกินโควตาข้อความรายวัน การเปลี่ยนแปลงยังถูกเก็บแต่จะไม่มีอีเวนต์ส่งออกไป ไคลเอนต์จึงตามให้ทันได้ด้วยการอ่าน

การลงลายเซ็นคำขอ

คำขอจากเซิร์ฟเวอร์ของคุณลงลายเซ็นแบบเดียวกับคำขออื่นของ Pusher HTTP API ด้วยคีย์และซีเคร็ตของแอป: query string มี auth_key, auth_timestamp, auth_version=1.0, body_md5 (เมื่อมีเนื้อหา) และ auth_signature ซึ่งคือ HMAC-SHA256 ของ METHOD\nPATH\nQUERY โดยเรียงพารามิเตอร์ตามชื่อ โค้ดลงลายเซ็นของไลบรารีเซิร์ฟเวอร์ Pusher ใดก็ใช้ได้ นี่คือทั้งหมดใน Node.js:

import crypto from 'node:crypto';

const { PUSHER_APP_ID: id, PUSHER_APP_KEY: key, PUSHER_APP_SECRET: secret } = process.env;

export async function chat(method, path, body) {
  const fullPath = `/apps/${id}/chat${path}`;
  const json = body === undefined ? '' : JSON.stringify(body);
  const params = { auth_key: key, auth_timestamp: Math.floor(Date.now() / 1000), auth_version: '1.0' };
  if (json) params.body_md5 = crypto.createHash('md5').update(json).digest('hex');
  const query = Object.keys(params).sort().map((k) => `${k}=${params[k]}`).join('&');
  const signature = crypto.createHmac('sha256', secret).update(`${method}\n${fullPath}\n${query}`).digest('hex');
  const res = await fetch(`https://ws.hibira.io${fullPath}?${query}&auth_signature=${signature}`, {
    method, body: json || undefined, headers: { 'Content-Type': 'application/json' },
  });
  if (!res.ok) throw new Error(`${res.status} ${(await res.json()).error}`);
  return res.json();
}

await chat('PUT', '/conversations/order-1042', { name: 'Order #1042', members: ['ann', 'support-bob'] });
await chat('POST', '/conversations/order-1042/messages', { user_id: 'ann', name: 'Ann', text: 'Where is my parcel?' });

พารามิเตอร์ของ GET (เช่น after หรือ limit) ก็เป็นส่วนหนึ่งของ query ที่ลงลายเซ็นด้วย

บทสนทนาและสมาชิก

บทสนทนา:

{"id": "order-1042", "name": "Order #1042", "metadata": {"kind": "support"},
 "members": [{"user_id": "ann", "read_seq": 3}, {"user_id": "support-bob", "read_seq": 1, "role": "agent"}],
 "last_seq": 3, "created_at": "...", "updated_at": "..."}

บทบาทและโน้ตภายใน ข้อความที่มี visible_to (สูงสุด 5 บทบาท) จะถึงเฉพาะสมาชิกที่มีบทบาทนั้น คนอื่นจะไม่ได้รับ อ่านไม่ได้ และไม่นับเป็นยังไม่อ่าน Watchers คือช่อง private หรือ presence ที่ได้รับทุกอีเวนต์ของบทสนทนา ให้กล่องข้อความของทีมติดตามทุกบทสนทนาได้ด้วยการสมัครเดียว อนุญาตเฉพาะพนักงานของคุณเท่านั้น

ข้อความ

ข้อความ:

{"id": "...", "seq": 3, "sender": "ann", "name": "Ann", "kind": "text",
 "text": "hi", "metadata": {"reply_to": 2}, "reactions": {"👍": ["support-bob"]}, "created_at": "..."}

ข้อความที่แก้ไขจะคง seq เดิมและมี edited_at ข้อความที่ลบจะคงตำแหน่งไว้พร้อม deleted_at และไม่มีข้อความ แก้ไขหรือกดอีโมจิไม่ได้อีก (409) การอ่านแบบ after คืนเฉพาะข้อความใหม่กว่า ไคลเอนต์ที่กลับมาจึงอ่านข้อความที่แสดงอยู่ซ้ำ (last=n) เพื่อรับการแก้ไข การลบ และอีโมจิ การค้นหาจับคู่ส่วนใดก็ได้ของคำ ไม่สนตัวพิมพ์เล็กใหญ่และอักขระเต็มความกว้าง จึงใช้ได้กับภาษาจีน ญี่ปุ่น และเกาหลี ข้อความระบบบอกว่าเกิดอะไรขึ้น (เข้าร่วม โอนต่อ ปิด) มีเพียงเซิร์ฟเวอร์ของคุณที่ส่งได้ ไม่มีการพุชและไม่นับเป็นยังไม่อ่าน

สถานะอ่านแล้วและจำนวนที่ยังไม่อ่าน

ตำแหน่งที่สมาชิกอ่านถึงจะเดินหน้าเท่านั้นและไม่เกิน last_seq ผู้ส่งข้อความถือว่าอ่านแล้ว unread ในรายการบทสนทนาของผู้ใช้นับข้อความหลัง read_seq ที่ไม่ใช่ข้อความระบบ สมาชิกทุกคนได้รับ chat.read เมื่อ read_seq ของใครเดินหน้า

เบราว์เซอร์และแอป: โทเคนผู้ใช้

ไคลเอนต์เรียก Chat API เองได้ที่ /apps/APP_ID/chat/me พร้อม Authorization: Bearer <user token> โดยไม่ต้องมีพร็อกซีบนเซิร์ฟเวอร์ของคุณ โทเคนคือ JWT ที่ลงลายเซ็นด้วยซีเคร็ตของแอป (HS256, {sub, exp}, นานสุด 30 วัน) เซิร์ฟเวอร์ของคุณสร้างได้ด้วยไลบรารี JWT ใดก็ได้หรือด้วย POST /tokens:

เมื่อมีโทเคน ไคลเอนต์แสดงรายการบทสนทนาของตน (GET /me/conversations) อ่าน ค้นหา ส่ง แก้ไขและลบข้อความของตัวเอง กดอีโมจิ ทำเครื่องหมายอ่านแล้ว และส่งสถานะกำลังพิมพ์ได้ ผู้ใช้คือ sub ของโทเคนเสมอ ไคลเอนต์สร้างบทสนทนา เปลี่ยนสมาชิก ตั้งค่าพุช ปิดเสียง หรือแบนไม่ได้ สิ่งเหล่านั้นอยู่ที่เซิร์ฟเวอร์ของคุณ ผู้ใช้แต่ละคนเขียนได้สูงสุด 2 ครั้งต่อวินาที และสูงสุด 10 ครั้งแบบต่อเนื่อง โทเคนที่มี conversation_id และ join เหมาะกับผู้เยี่ยมชมนิรนามของแชตซัพพอร์ต: เซิร์ฟเวอร์ของคุณสร้างบทสนทนา ตรวจสอบผู้เยี่ยมชม แล้วออกโทเคนอายุสั้นให้ ID ที่สร้างขึ้นเอง

ไฟล์แนบ

  1. เซิร์ฟเวอร์ของคุณขออัปโหลด: POST /conversations/{id}/attachments พร้อม user_id, name, content_type และ size (สูงสุด 25 MB) คำตอบมี attachment และ upload (url, method, headers)
  2. ไคลเอนต์อัปโหลดไฟล์ตรงไปที่ upload.url ภายใน 15 นาที ด้วยเฮดเดอร์เหล่านั้นทุกตัว
  3. เซิร์ฟเวอร์ของคุณส่งข้อความพร้อม attachments: id, name และ content_type จากขั้นที่ 1 (สูงสุด 10 ไฟล์ต่อข้อความ และ text เว้นว่างได้)

ไฟล์แนบทุกไฟล์ที่อ่านจาก API หรืออีเวนต์มี url ที่ดาวน์โหลดได้ภายในหนึ่งชั่วโมง ไฟล์ที่อัปโหลดแต่ไม่ได้ส่งภายในหนึ่งวันจะถูกลบ และการลบข้อความหรือบทสนทนาจะลบไฟล์ของมันด้วย

พุชถึงสมาชิกที่ออฟไลน์

ข้อความใหม่จะถูกพุชผ่าน Hibira Push ของแอปไปยังสมาชิกที่ไม่ได้เชื่อมต่อ (push: "offline" ค่าเริ่มต้น) ไปยังสมาชิกทุกคนยกเว้นผู้ส่ง ("always") หรือไม่พุชเลย ("never") หัวเรื่องคือชื่อผู้ส่งและชื่อบทสนทนา (หรือ push_title) เนื้อหาคือ 180 ตัวอักษรแรกของข้อความ และ push_url จะเปิดเมื่อแตะ อุปกรณ์ลงทะเบียนด้วย SDK พุชที่เข้ากันได้กับ Beams ด้วย ID ผู้ใช้เดียวกัน push ในคำตอบบอกว่าพุชถึงสมาชิกกี่คน หรือทำไมไม่มีการพุช

การกลั่นกรอง

ตัวกรองคำตรวจทุกข้อความใหม่หรือที่แก้ไข จับคู่ได้แม้อยู่กลางคำ ไม่สนตัวพิมพ์และอักขระเต็มความกว้าง จึงจับภาษาจีนและญี่ปุ่นได้ด้วย mask แทนส่วนที่ตรงด้วย * ส่วน reject ตอบ 422 และไม่เก็บอะไร ผู้ใช้ที่ถูกแบนได้ 403 เมื่อส่ง แก้ไข กดอีโมจิ และพิมพ์ในทุกบทสนทนาของแอป สมาชิกที่ถูกปิดเสียงได้ 403 เมื่อส่งและพิมพ์ในบทสนทนานั้นแต่ยังอ่านได้

อีเวนต์และเว็บฮุก

อีเวนต์ถูกส่งไปที่ #server-to-user-<user_id> ของสมาชิกแต่ละคนที่เกี่ยวข้อง และไปที่ watchers ของบทสนทนา แต่ละอีเวนต์นับเป็นหนึ่งข้อความในโควตารายวัน

const pusher = new Pusher('APP_KEY', { cluster: 'hkg', wsHost: 'ws.hibira.io', userAuthentication: { endpoint: '/pusher/user-auth' } });
pusher.signin();
pusher.user.bind('chat.message', ({ conversation_id, message }) => showMessage(conversation_id, message));

เซิร์ฟเวอร์ของคุณยังได้รับเว็บฮุก chat_message สำหรับทุกข้อความใหม่: channel คือ ID บทสนทนา user_id คือผู้ส่ง และ data คือ JSON {"conversation_id", "message"} เพิ่ม chat_message ในอีเวนต์ของเว็บฮุกหนึ่งของแอปเพื่อรับ

ขีดจำกัด

การเขียนใช้ขีดจำกัดอัตรา HTTP API ของแอปร่วมกัน (เกินแล้วได้ 429)

ผู้ใช้งานรายเดือนและระยะเวลาเก็บ

ผู้ใช้นับเป็นผู้ใช้งานในเดือนนั้น (UTC) เมื่อส่งข้อความหรือทำเครื่องหมายอ่านแล้ว นับครั้งเดียวทุกแอปของบัญชี ทุกบัญชีมี 500 คนต่อเดือน แพ็กเสริม Chat เพิ่มเป็น 1,000, 5,000, 20,000 หรือ 60,000 คน (แพ็กเกจ) เมื่อเดือนนั้นเต็ม ผู้ใช้ที่ยังไม่ถูกนับจะได้ 429 เมื่อส่งและอ่านจนถึงเดือนถัดไป ผู้ใช้ที่ถูกนับแล้วใช้ต่อได้ GET /usage ตอบ {month, active_users, limit}

ข้อความแก้ไขได้เต็มที่ภายใน 30 วัน หลังจากนั้น บัญชีที่มีแพ็กเกจแบบชำระเงินหรือแพ็กเสริม Chat จะเก็บไว้ในคลังที่ API ยังคืนให้ (อ่านอย่างเดียว) ส่วนแพ็กเกจ Free ที่ไม่มีแพ็กเสริมจะถูกลบ

ใช้งานจาก AI agent

MCP เซิร์ฟเวอร์ของ Hibira มีเครื่องมือ Chat API ให้ AI agent สำหรับเขียนโค้ดตั้งค่าและทดสอบแชตแทนคุณได้: create_conversation, send_message, list_conversations และ list_messages เครื่องมือเหล่านี้ทำงานกับแอปของคุณเองด้วยการตรวจสอบเดียวกับคำขอที่ลงลายเซ็น และต้องให้บัญชีเปิดใช้ Chat API แล้ว ปลั๊กอินสำหรับ agent ของ Claude Code, Codex, Cursor และอื่น ๆ มีสกิลที่เชื่อม Chat API เข้ากับโปรเจกต์ตามขั้นตอนนี้ หากต้องการหน้าสนทนาสำเร็จรูปสำหรับ React หรือ JavaScript ล้วน ดู @hibira-io/chat-ui