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

    อ้างอิง

    Pagination & Common Types

    หน้านี้อธิบาย Pattern ที่ใช้ร่วมกันในทุก Endpoint ของ Partner API


    Pagination Object

    ทุก List Endpoint คืน pagination object พร้อมกับ data array

    {
      "data": [ ],
      "pagination": {
        "next_cursor": "eyJjIjoiMjAyNi0wNi0xNFQxMjozOTozNi4wNTZaIiwiaSI6ImUxMWM5Mjk4In0",
        "has_more": true,
        "limit": 50
      }
    }
    
    FieldTypeDescription
    next_cursorstring | nullCursor สำหรับดึงหน้าถัดไป — null เมื่อ has_more เป็น false
    has_morebooleantrue หากยังมีข้อมูลในหน้าถัดไป
    limitnumberจำนวนรายการต่อหน้าที่ใช้จริง

    Cursor Pagination

    วิธีใช้ Cursor

    1. เรียก Request แรกโดยไม่ต้องส่ง cursor
    2. ตรวจสอบ pagination.has_more
    3. หาก has_more เป็น true ส่ง pagination.next_cursor เป็น query parameter cursor ใน Request ถัดไป
    4. ทำซ้ำจนกว่า has_more เป็น false

    Important

    ค่า Cursor เป็น Opaque Value — ไม่ควรอ่าน แก้ไข หรือสร้างเอง

    โครงสร้างภายในอาจเปลี่ยนแปลงได้โดยไม่แจ้งล่วงหน้า ควรส่งค่าที่ได้รับจาก API กลับมาตรง ๆ เท่านั้น

    TypeScript Example

    async function fetchAll<T>(url: string, token: string): Promise<T[]> {
      const results: T[] = [];
      let cursor: string | null = null;
    
      do {
        const params = new URLSearchParams({ limit: '200' });
        if (cursor) params.set('cursor', cursor);
    
        const res = await fetch(`${url}?${params}`, {
          headers: { Authorization: `Bearer ${token}` },
        });
    
        if (!res.ok) {
          const body = await res.json();
          throw new Error(body.message || body.error);
        }
    
        const { data, pagination } = await res.json();
        results.push(...data);
        cursor = pagination.has_more ? pagination.next_cursor : null;
      } while (cursor);
    
      return results;
    }
    

    Branch Filtering

    Endpoint ที่รองรับ branch_id สามารถส่งหลายค่าได้

    GET /api/partner/v1/sales?branch_id=<uuid1>&branch_id=<uuid2>
    

    ผลลัพธ์จะเป็น Intersection ระหว่างสาขาที่ส่งมากับสาขาที่ Token อนุญาต (allowed_branch_ids)

    สถานการณ์ผลลัพธ์
    Token ไม่จำกัดสาขา (allowed_branch_ids: null) + ส่ง branch_idใช้ branch_id ที่ส่งมาโดยตรง
    Token จำกัดสาขา + ส่ง branch_id ที่อนุญาตได้ข้อมูลสาขานั้น
    Token จำกัดสาขา + ส่ง branch_id ที่ไม่อนุญาตไม่คืนข้อมูลสาขานั้น (ไม่ error)
    ไม่ส่ง branch_idคืนข้อมูลทุกสาขาที่ Token อนุญาต

    Date Filtering

    Endpoint ที่รองรับ from / to รับค่าในรูปแบบ YYYY-MM-DD

    GET /api/partner/v1/sales?from=2026-06-01&to=2026-06-15
    

    กรองตาม field วันที่หลักของแต่ละ Endpoint:

    EndpointField ที่ใช้กรอง
    /salesorder_date
    /inventory/movementscreated_at
    /purchase-ordersorder_date

    Decimal Strings

    ฟิลด์ตัวเงินและจำนวนทุกตัวส่งกลับเป็น String ไม่ใช่ number

    {
      "total_amount": "12510.40",
      "tax_amount": "818.40",
      "quantity": "1"
    }
    

    เหตุผล: ป้องกันปัญหา Floating Point precision loss ที่เกิดใน JavaScript และภาษาอื่น ๆ เมื่อจัดการตัวเลขทศนิยม

    Partner ควรใช้ Library เช่น decimal.js หรือ BigDecimal เมื่อต้องคำนวณทางการเงิน