Developer Docs

    เริ่มต้น

    Partner API — Auth

    Partner API — Sales

    Partner API — Products

    Partner API — Inventory

    Partner API — Purchasing

    Partner API — Customers

    Partner API — Reports

    Partner API — Webhooks

    อ้างอิง

    Payload & Signatures

    เมื่อ Event เกิดขึ้น MeeD จะส่ง HTTP POST ไปที่ endpoint_url ที่ตั้งค่าไว้ใน Webhook Subscription — รวมถึง /ping test event

    หน้านี้อธิบาย:

    • โครงสร้าง Payload ที่ได้รับ
    • วิธีตรวจสอบ Signature เพื่อยืนยันว่า Request มาจาก MeeD จริง
    • Retry Policy เมื่อ Endpoint ไม่ตอบสนอง

    Request Headers

    ทุก Webhook Delivery จะมี Headers เหล่านี้

    HeaderDescription
    Content-Typeapplication/json
    X-MeeD-EventEvent type เช่น sales.order.completed
    X-MeeD-Webhook-IdUUID ของ Webhook Subscription
    X-MeeD-Signaturesha256=<hmac_hex> — HMAC-SHA256 ของ Raw Request Body ที่ sign ด้วย signing_secret

    Event Payload

    Payload เป็น JSON Object ที่มีโครงสร้างเดียวกันทุก Event Type

    {
      "event_type": "sales.order.completed",
      "webhook_id": "a1b2c3d4-0000-0000-0000-000000000001",
      "business_id": "e3d716b9-eed5-4128-a709-83927a832060",
      "timestamp": "2026-06-16T10:30:00.000Z",
      "data": { }
    }
    
    FieldTypeDescription
    event_typestringประเภท Event เช่น sales.order.completed — ดูรายการทั้งหมดที่ Create Webhook
    webhook_idstring (UUID)UUID ของ Webhook Subscription ที่ trigger Event นี้
    business_idstring (UUID)UUID ของธุรกิจ
    timestampstring (ISO 8601)เวลาที่ Event เกิดขึ้น (UTC)
    dataobjectRecord ที่เกี่ยวข้องกับ Event — เช่น sales.order.completed จะมีข้อมูล SalesOrder ครบถ้วน

    Signature Verification

    ตรวจสอบ X-MeeD-Signature ก่อนประมวลผล Payload ทุกครั้ง เพื่อยืนยันว่า Request มาจาก MeeD จริงและ Payload ไม่ถูกแก้ไขระหว่างทาง

    วิธีการตรวจสอบ

    1. นำ Raw Request Body (ก่อน Parse JSON) มา Hash ด้วย HMAC-SHA256 โดยใช้ signing_secret เป็น Key
    2. เติม prefix sha256= ด้านหน้า
    3. เปรียบเทียบกับค่าใน X-MeeD-Signature header โดยใช้ Constant-time Comparison

    Important

    ต้องใช้ crypto.timingSafeEqual — ไม่ใช่ === — เพื่อป้องกัน Timing Attack

    signing_secret ได้รับเพียงครั้งเดียวตอนสร้าง Webhook — หากทำหาย ต้องสร้าง Webhook ใหม่

    TypeScript Example

    import crypto from 'crypto';
    
    function verifySignature(
      rawBody: string,
      signingSecret: string,
      signatureHeader: string
    ): boolean {
      const expected =
        'sha256=' +
        crypto.createHmac('sha256', signingSecret).update(rawBody).digest('hex');
    
      return crypto.timingSafeEqual(
        Buffer.from(expected),
        Buffer.from(signatureHeader)
      );
    }
    

    Express Integration Example

    import express from 'express';
    import crypto from 'crypto';
    
    const app = express();
    
    app.post(
      '/webhooks/meed',
      express.raw({ type: 'application/json' }), // ต้องใช้ raw() ไม่ใช่ json()
      (req, res) => {
        const signature = req.headers['x-meed-signature'] as string;
    
        if (!verifySignature(req.body.toString(), process.env.WEBHOOK_SIGNING_SECRET!, signature)) {
          return res.status(401).send('Invalid signature');
        }
    
        const event = JSON.parse(req.body.toString());
        const { event_type, data } = event;
    
        switch (event_type) {
          case 'sales.order.completed':
            // handle completed order
            break;
          case 'inventory.stock.low':
            // handle low stock alert
            break;
        }
    
        res.status(200).send('ok');
      }
    );
    

    Important

    ต้องใช้ express.raw() ไม่ใช่ express.json()

    หาก Parse JSON ก่อน Body จะถูก Serialize ใหม่ทำให้ Hash ไม่ตรงและ Signature Verification ล้มเหลวทุกครั้ง


    Retry Policy

    เมื่อ Endpoint ไม่ตอบกลับ 2xx MeeD จะ Retry ตาม Exponential Backoff โดยอัตโนมัติ

    Attemptหลังจาก
    1ทันที (First delivery)
    25 นาที
    330 นาที
    42 ชั่วโมง
    512 ชั่วโมง

    หลัง Attempt ที่ 5 สถานะ Delivery จะเปลี่ยนเป็น DEAD — ตรวจสอบประวัติได้ที่ List Deliveries

    แนวทางรับมือ Retry

    • ออกแบบ Endpoint ให้รองรับ Idempotent — Event เดียวกันอาจถูกส่งซ้ำ ควรตรวจสอบ webhook_id + timestamp หรือ data.id ก่อนประมวลผล
    • ตอบกลับ 200 ทันทีแม้ยังประมวลผลไม่เสร็จ แล้วทำงานหนักใน Background
    • Timeout ของ MeeD อยู่ที่ 30 วินาที — หาก Endpoint ไม่ตอบภายในเวลานี้จะถือว่า Delivery ล้มเหลว