สำหรับนักพัฒนา

คู่มือ Public API (สำหรับนักพัฒนา)

สร้างเมื่อ: อัปเดตเมื่อ:

Public API ช่วยให้ระบบ EC ระบบหลักขององค์กร หรือ RPA เพิ่มเรคคอร์ดในแอป kintone ที่ติดตั้ง PRING สร้างเอกสารด้วยเทมเพลต PRING ของแอปนั้น และรับไฟล์กลับมาได้ทั้งหมดผ่าน HTTPS ใช้ได้ในแผน Pro ให้ออก API key ของ PRING ที่แท็บ "API" ของหน้าตั้งค่า ลงทะเบียน API token ของ kintone ทีละแอป แล้วส่ง key ใน header Authorization: Bearer

Public API ใช้ได้ในแผน Pro

ภาพรวมและสิ่งที่ต้องมี

Public API ของ PRING คือ API ผ่าน HTTPS ที่ให้ระบบภายนอกใช้การส่งออกเอกสารของ PRING ได้โดยไม่ต้องเปิดหน้าจอ kintone การใช้งานหลักมี 3 แบบ

  • เพิ่มเรคคอร์ดในแอป kintone จากระบบภายนอก แล้วสร้างเอกสาร (PDF, Excel, Word) ต่อได้ทันที
  • สร้างเอกสารจากเรคคอร์ดที่มีอยู่แล้วใน kintone
  • รับไฟล์ของเอกสารที่สร้างแล้ว

ก่อนเริ่มใช้ ตรวจสอบว่ามีครบทั้ง 3 ข้อต่อไปนี้

  1. มีสัญญาแผน Pro ตรวจสอบแผนได้ที่แท็บ “แผนและราคา” ของหน้าตั้งค่า (แผนและราคา)
  2. แอป kintone ที่เรียกติดตั้ง PRING แล้ว และลงทะเบียนเทมเพลตที่จะใช้ไว้แล้ว เอกสารสร้างด้วยเทมเพลต PRING ของแอปนั้น (ลงทะเบียนเทมเพลต)
  3. ลงทะเบียน API token ของ kintone ทีละแอปที่แท็บ “API” (ในหมวด “อัตโนมัติและการเชื่อมต่อ”) ของหน้าตั้งค่าแล้ว สร้าง token ได้ที่ “API Token” ในการตั้งค่าแอปของ kintone วางใน “API โทเค็น kintone ของแอปนี้” ในแท็บ “API” แล้วกด “บันทึกโทเค็น” จะแสดง “ลงทะเบียนแล้ว (วันที่)” หากต้องการลบ กด “ลบโทเค็น” เมื่อแสดง “กดอีกครั้งเพื่อลบ” ให้กดอีกครั้ง ให้สิทธิ์เพียง 3 อย่าง คือ “เพิ่มเรคคอร์ด” “แก้ไขเรคคอร์ด” และ “ดูเรคคอร์ด” PRING เก็บ token แบบเข้ารหัส และใช้เฉพาะตอนเพิ่มและดึงเรคคอร์ดเท่านั้น

URL หลักของ API คือ https://api.pring.tech/api/v1/ request และ response เป็น JSON (UTF-8) ยกเว้นไฟล์เอกสารที่รับเป็น binary

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

Public API ตรวจสอบผู้เรียกด้วย API key ของ PRING ซึ่งเป็นคนละอย่างกับ API token ของ kintone (ข้อ 3 ของสิ่งที่ต้องมี) PRING ใช้ token ของ kintone เพื่อเรียก kintone ส่วนระบบของคุณใช้ API key ของ PRING เพื่อเรียก PRING

ออก API key

  1. ใน kintone เปิดการตั้งค่าปลั๊กอินของแอปที่ติดตั้ง PRING
  2. เลือก “อัตโนมัติและการเชื่อมต่อ” ในแถวบน แล้วเปิดแท็บ “API” สำหรับแผนอื่นที่ไม่ใช่ Pro จะแสดงเพียง “API สาธารณะใช้ได้ในแผน Pro” และ “เปิดแผนและราคา” และออก key ไม่ได้
  3. ที่ “คีย์ API” กด “ออกคีย์” แล้วกรอก “ชื่อ” ที่บอกการใช้งาน (เช่น “เชื่อมต่อ EC ใช้งานจริง”)
  4. ที่ “ขอบเขต” เลือกสิ่งที่จะใช้ (ดูตารางด้านล่าง) เลือกเฉพาะที่จำเป็น
  5. หากใช้สำหรับพัฒนาและทดสอบ ให้เลือก “เป็นคีย์ทดสอบ (prk_test_)”
  6. หากต้องการ ให้กรอก “IP ที่อนุญาต” บรรทัดละหนึ่ง IP address หรือ CIDR (ไม่บังคับ สูงสุด 20 รายการ ดู “จำกัด IP address” ด้านล่าง)
  7. กด “ออกคีย์” key จะแสดง เพียงครั้งเดียว กด “คัดลอก” แล้วเก็บตาม “การเก็บ key” ด้านล่าง จากนั้นกด “ปิด” เมื่อปิดแล้วจะแสดงอีกไม่ได้

key ที่ออกแล้วจะแสดงในตาราง “คีย์ API” พร้อมชื่อ (key แสดงเพียง prk_live_… และ 4 ตัวท้าย) ประเภท ขอบเขต IP ที่อนุญาต วันที่ออก วันที่ใช้ล่าสุด และสถานะ มี key ที่ใช้งานได้พร้อมกันได้สูงสุด 20 ตัว ออก key ได้หลายตัว หากแยก key ตามระบบที่เชื่อมต่อ การเพิกถอน key ตัวหนึ่งจะไม่ทำให้การเชื่อมต่ออื่นหยุด

รูปแบบของ key

ประเภท ขึ้นต้นด้วย ใช้ที่ไหน
ใช้งานจริง prk_live_ การเชื่อมต่อจริง
ทดสอบ prk_test_ สภาพแวดล้อมพัฒนาและทดสอบ

key เป็นสตริงบรรทัดเดียว ขึ้นต้นด้วย prk_live_ หรือ prk_test_ ตามด้วยเลขฐานสิบหก 64 หลัก ตัวขึ้นต้นบอกได้ว่าเป็น key ใช้งานจริงหรือทดสอบ ให้ตรวจสอบเมื่อไล่ดู log หรือทบทวนรายการ secret

วิธีส่ง key

ส่ง key ใน header Authorization ของทุก request ต่อจาก Bearer

GET /api/v1/apps HTTP/1.1
Host: api.pring.tech
Authorization: Bearer prk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • อย่าใส่ key ใน query ของ URL (เช่น ?key=) ระบบไม่รับ URL จะถูกบันทึกใน access log และประวัติเบราว์เซอร์
  • รับเฉพาะ HTTPS ไม่รับ HTTP

Scope

key แต่ละตัวมีการทำงานที่ใช้ได้ (scope) หากเรียกการทำงานที่ key ไม่มี scope จะได้ 403

Scope ทำอะไรได้ API ที่ใช้
records:write เพิ่ม อัปเดต และดึงเรคคอร์ดในแอป kintone POST PUT GET /api/v1/apps/{appID}/records…
render สร้างเอกสาร และตรวจสอบสถานะของ job แบบ asynchronous …/records/{recordID}/render, ?render=, GET /api/v1/jobs/{jobID}
files:read รับไฟล์ที่สร้างแล้ว GET /api/v1/files/{fileID}

รายการแอปและเทมเพลต (GET /api/v1/apps) เรียกได้ด้วย key ทุก scope การเชื่อมต่อที่เพิ่มเรคคอร์ดแล้วรับ PDF ต้องใช้ครบทั้ง 3 scope การเชื่อมต่อที่สร้างเอกสารอย่างเดียวโดยไม่เพิ่มเรคคอร์ด ใช้แค่ render และ files:read

ความต่างระหว่าง 401 กับ 403 และวิธีแก้

Response ความหมาย สาเหตุที่พบบ่อย วิธีแก้
401 Unauthorized ระบุไม่ได้ว่าใครเป็นผู้เรียก ไม่มี header Authorization ไม่มี Bearer คัดลอก key ผิด (มีช่องว่างหรือขึ้นบรรทัดใหม่ข้างหน้าหรือข้างหลัง) key ถูกเพิกถอนแล้ว ตรวจสอบรูปแบบ header และคัดลอก key ใหม่ หาก key ถูกเพิกถอนแล้ว ให้ออก key ใหม่
403 Forbidden รู้ว่าใครเรียก แต่ไม่อนุญาตให้ทำการนั้น scope ไม่พอ ใช้แผนอื่นที่ไม่ใช่ Pro เรียกจาก IP address ที่ไม่ได้อนุญาต แอปนั้นยังไม่ได้ลงทะเบียน API token ของ kintone detail ใน response บอกเหตุผล ให้ออก key ที่เพิ่ม scope แล้ว ตรวจสอบแผน เพิ่ม IP ที่อนุญาต หรือลงทะเบียน token ที่แท็บ “API”

จำไว้ว่า 401 คือปัญหาที่ตัว key ส่วน 403 คือ key ถูกต้องแต่มีปัญหาเรื่องสิทธิ์หรือการตั้งค่า การลองใหม่ด้วย key เดิมเมื่อได้ 401 จะไม่ช่วยให้หาย

การเก็บ key

  • ปฏิบัติกับ key เหมือนรหัสผ่าน อย่าเขียนไว้ในซอร์สโค้ด Git repository แชต หรืออีเมล
  • เก็บไว้ในระบบจัดการ secret ของระบบที่เชื่อมต่อ (cloud secret manager, CI secret, environment variable ฯลฯ) และให้โปรแกรมอ่านจากที่นั่น
  • อย่าพิมพ์ key หรือ header Authorization ลงใน log ของแอป บันทึกข้อผิดพลาด หรือเครื่องมือ monitoring หากต้องบันทึก ให้บันทึกแค่ตัวขึ้นต้น prk_live_ กับตัวอักษรท้ายไม่กี่ตัว
  • เมื่อเปลี่ยนผู้รับผิดชอบ หรือเลิกการเชื่อมต่อ ให้เพิกถอน key นั้น

เพิกถอนและออกใหม่

  • เพิกถอน: ในตาราง “คีย์ API” ของแท็บ “API” กด “เพิกถอน” ของ key นั้น เมื่อแสดง “กดอีกครั้งเพื่อเพิกถอน” ให้กดอีกครั้ง สถานะจะเป็น “เพิกถอนแล้ว” key ที่ถูกเพิกถอนจะได้ 401 ตั้งแต่ตอนนั้น และย้อนกลับไม่ได้
  • ออกใหม่ (เปลี่ยน key): หากต้องการเปลี่ยนโดยไม่ให้การเชื่อมต่อหยุด ให้ทำตามลำดับ ① ออก key ใหม่ ② เปลี่ยน secret ในระบบที่เชื่อมต่อเป็น key ใหม่ ③ ตรวจสอบว่าใช้งานได้ด้วย key ใหม่ ④ เพิกถอน key เก่า ใช้ key หลายตัวพร้อมกันได้ การเชื่อมต่อจึงไม่หยุดจนถึงขั้น ③
  • เมื่อสงสัยว่า key อาจรั่ว: เพิกถอนทันทีโดยไม่ต้องลังเล จากนั้นออก key ใหม่และเปลี่ยนไปใช้

จำกัด IP address (ไม่บังคับ)

กำหนด IP address หรือ CIDR ที่อนุญาตให้เรียกด้วย key ได้สูงสุด 20 รายการ หากไม่กำหนดจะแสดง “ไม่จำกัด” เมื่อกำหนดแล้ว การเรียกจาก address อื่นจะได้ 403 สำหรับการเชื่อมต่อแบบ server-to-server ที่เรียกจาก IP address คงที่ การกำหนดไว้ช่วยลดความเสียหายหาก key รั่ว

ตัวอย่างการใช้งาน

ตัวอย่างอ่าน key จาก environment variable PRING_API_KEY ให้เปลี่ยนหมายเลขแอป 19 เทมเพลต tpl_invoice และ field code ของ kintone (เช่น customer_name) ให้ตรงกับแอปของคุณ ตรวจสอบหมายเลขแอปและ ID ของเทมเพลตได้จากรายการในข้อ e) ด้านล่าง

ส่งค่าของเรคคอร์ดในรูปแบบเดียวกับ kintone REST API ({"field_code": {"value": ค่า}})

ตัวอย่างที่พร้อมรัน

ตัวอย่างเหล่านี้ทำครบทั้งขั้นตอน คือ เพิ่มเรคคอร์ด สร้าง PDF แล้วดาวน์โหลด

ตัวอย่างอ่าน environment variable ต่อไปนี้

ตัวแปร ความหมาย ค่าเริ่มต้น
PRING_API_KEY API key ของ PRING (จำเป็น) ไม่มี
PRING_API_BASE URL หลักของ API https://api.pring.tech
PRING_APP หมายเลขแอป 19
PRING_TEMPLATE ID ของเทมเพลต tpl_invoice
PRING_OUT ชื่อไฟล์ที่บันทึก invoice.pdf

a) เพิ่มเรคคอร์ดและสร้าง PDF ในครั้งเดียว

เติม ?render=<ID เทมเพลต>&format=pdf ให้กับ POST /api/v1/apps/{appID}/records ระบบจะสร้างเอกสารต่อจากการเพิ่มเรคคอร์ดทันที เลือกรูปแบบได้จาก pdf xlsx docx (รูปแบบที่เทมเพลตรองรับ) scope ที่ต้องใช้คือ records:write และ render

curl

curl -sS -X POST "https://api.pring.tech/api/v1/apps/19/records?render=tpl_invoice&format=pdf" \
  -H "Authorization: Bearer $PRING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "record": {
      "customer_name": { "value": "Sample Trading Co." },
      "invoice_date": { "value": "2026-10-31" },
      "items": { "value": [
        { "value": { "item_name": { "value": "Item A" }, "qty": { "value": "2" }, "unit_price": { "value": "10000" } } }
      ] }
    }
  }'

Node.js (fetch)

const res = await fetch("https://api.pring.tech/api/v1/apps/19/records?render=tpl_invoice&format=pdf", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PRING_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    record: {
      customer_name: { value: "Sample Trading Co." },
      invoice_date: { value: "2026-10-31" },
    },
  }),
});
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).detail}`);
const { id, file } = await res.json();
console.log("record", id, "file", file.id);

Python (requests)

import os, requests

res = requests.post(
    "https://api.pring.tech/api/v1/apps/19/records",
    params={"render": "tpl_invoice", "format": "pdf"},
    headers={"Authorization": f"Bearer {os.environ['PRING_API_KEY']}"},
    json={"record": {"customer_name": {"value": "Sample Trading Co."}, "invoice_date": {"value": "2026-10-31"}}},
    timeout=60,
)
res.raise_for_status()
body = res.json()
print("record", body["id"], "file", body["file"]["id"])

ตัวอย่าง response (201 Created)

{
  "id": "105",
  "revision": "1",
  "file": {
    "id": "fil_01HXY...",
    "url": "https://api.pring.tech/api/v1/files/fil_01HXY...",
    "expires_at": "2026-10-31T09:15:00Z"
  }
}

id คือหมายเลขเรคคอร์ดของ kintone รับไฟล์ด้วยวิธีในข้อ c) หากไม่เติม ?render= ระบบจะเพิ่มเรคคอร์ดอย่างเดียว และส่งกลับเฉพาะ id กับ revision อัปเดตเรคคอร์ดด้วย PUT /api/v1/apps/{appID}/records/{recordID} และดึงเรคคอร์ดด้วย GET /api/v1/apps/{appID}/records/{recordID} ตอนอัปเดต ส่ง revision ไปด้วยได้ kintone จะตรวจสอบค่านี้ หากเรคคอร์ดถูกเปลี่ยนไปแล้วในระหว่างนั้น จะได้ 409

เพิ่มหลายเรคคอร์ดพร้อมกัน

ใส่ array ใน records แทน record เพื่อเพิ่มได้ไม่เกิน 100 เรคคอร์ดในครั้งเดียว ตั้งแต่ 101 รายการขึ้นไปจะได้ 413

{
  "records": [
    { "customer_name": { "value": "Sample Trading Co." }, "invoice_date": { "value": "2026-10-31" } },
    { "customer_name": { "value": "Example Industries" }, "invoice_date": { "value": "2026-10-31" } }
  ]
}

หากไม่เติม ?render= จะได้ 201 พร้อมหมายเลขเรคคอร์ดและ revision ตามลำดับที่ส่ง

{
  "ids": ["105", "106"],
  "revisions": ["1", "1"]
}

หากส่ง records พร้อม ?render= ระบบจะสร้างเอกสารแบบ asynchronous และส่ง 202 พร้อม job_id กลับมา (ดูข้อ d)

b) สร้างเอกสารจากเรคคอร์ดที่มีอยู่

ส่งเทมเพลต (template) และรูปแบบ (format ไม่บังคับ) ไปที่ POST /api/v1/apps/{appID}/records/{recordID}/render หากใส่ field code ของฟิลด์ไฟล์แนบของ kintone ใน attach_to_field ระบบจะบันทึกไฟล์ลงในฟิลด์ไฟล์แนบของเรคคอร์ดนั้นด้วย scope ที่ต้องใช้คือ render

curl

curl -sS -X POST "https://api.pring.tech/api/v1/apps/19/records/105/render" \
  -H "Authorization: Bearer $PRING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "template": "tpl_invoice", "format": "pdf", "attach_to_field": "invoice_pdf" }'

Node.js (fetch)

const res = await fetch("https://api.pring.tech/api/v1/apps/19/records/105/render", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.PRING_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ template: "tpl_invoice", format: "pdf", attach_to_field: "invoice_pdf" }),
});
const { file, attached_to, warnings } = await res.json();

Python (requests)

res = requests.post(
    "https://api.pring.tech/api/v1/apps/19/records/105/render",
    headers={"Authorization": f"Bearer {os.environ['PRING_API_KEY']}"},
    json={"template": "tpl_invoice", "format": "pdf", "attach_to_field": "invoice_pdf"},
    timeout=60,
)
file = res.json()["file"]

ตัวอย่าง response (201 Created)

{
  "file": {
    "id": "fil_01HXY...",
    "url": "https://api.pring.tech/api/v1/files/fil_01HXY...",
    "expires_at": "2026-10-31T09:15:00Z"
  },
  "attached_to": "invoice_pdf",
  "warnings": []
}

file มีรูปแบบเดียวกับข้อ a) เมื่อส่ง attach_to_field ค่า attached_to จะเป็น field code ของฟิลด์ไฟล์แนบที่บันทึกไฟล์ไว้ API นี้ส่งผลลัพธ์กลับด้วย 201 ทันที และไม่ส่ง 202

บันทึกไฟล์แนบจาก API ลงใน File Log

หากต้องการให้ไฟล์ที่ API บันทึกลงในฟิลด์ไฟล์แนบถูกบันทึกในแอป File Log ด้วย ให้ลงทะเบียน “API โทเค็นของบันทึกไฟล์” ในแท็บ “API”

  1. ในแอป File Log สร้าง token ที่ “การตั้งค่าแอป > API Token” ให้สิทธิ์เฉพาะ “เพิ่มเรคคอร์ด” เท่านั้น
  2. วางใน “API โทเค็นของบันทึกไฟล์” ในแท็บ “API” แล้วกด “บันทึกโทเค็นบันทึกไฟล์”

ระหว่างที่ยังไม่ได้ลงทะเบียน แท็บ “API” จะแสดง “ยังไม่ได้ลงทะเบียนโทเค็น File Log (ไฟล์แนบจาก API จะไม่ถูกบันทึก)” หากยังไม่มีแอป File Log ให้สร้างที่แท็บบันทึกตรวจสอบก่อน

หากส่ง attach_to_field โดยยังไม่ได้ลงทะเบียน token นี้ ไฟล์จะถูกบันทึกลงในฟิลด์ไฟล์แนบ แต่ warnings จะมี "audit_not_recorded" ในกรณีนี้ แอป File Log จะไม่มีแถวของไฟล์นั้น

c) รับไฟล์

เรียก GET /api/v1/files/{fileID} ระบบจะ redirect ด้วย 302 ไปยังลิงก์ที่ใช้ได้ครั้งเดียว (/api/v1/files/{fileID}/content?t=…) ให้รับไฟล์จากลิงก์นั้น ลิงก์นี้ไม่ต้องใช้ header Authorization scope ที่ต้องใช้คือ files:read

  • ลิงก์ที่ใช้ได้ครั้งเดียวหมดอายุใน 15 นาที ไฟล์ที่สร้างก็ถูกลบหลังสร้าง 15 นาทีเช่นกัน
  • ลิงก์ที่ใช้ไปแล้วหรือหมดอายุแล้วจะได้ 410 หากต้องการดาวน์โหลดอีกครั้ง ให้เรียก GET /api/v1/files/{fileID} ใหม่ ก่อนไฟล์ถูกลบ
  • เอกสารที่ต้องการเก็บไว้ ให้บันทึกลงใน kintone ด้วย attach_to_field ในข้อ b)

curl (-L ตาม redirect ไปจนถึงปลายทาง)

curl -sS -L -o invoice.pdf "https://api.pring.tech/api/v1/files/fil_01HXY..." \
  -H "Authorization: Bearer $PRING_API_KEY"

Node.js (fetch) (fetch ตาม redirect ให้อัตโนมัติ)

import { writeFile } from "node:fs/promises";

const res = await fetch(`https://api.pring.tech/api/v1/files/${file.id}`, {
  headers: { Authorization: `Bearer ${process.env.PRING_API_KEY}` },
});
if (!res.ok) throw new Error(`${res.status}`);
await writeFile("invoice.pdf", Buffer.from(await res.arrayBuffer()));

Python (requests) (requests ก็ตาม redirect ให้อัตโนมัติ)

res = requests.get(
    f"https://api.pring.tech/api/v1/files/{file['id']}",
    headers={"Authorization": f"Bearer {os.environ['PRING_API_KEY']}"},
    timeout=60,
)
res.raise_for_status()
open("invoice.pdf", "wb").write(res.content)

d) แบบ asynchronous: 202 และ job_id

เฉพาะเมื่อส่ง records พร้อม ?render= ระบบจะไม่ส่งเอกสารกลับทันที แต่ส่ง 202 Accepted และ job_id กลับมา ตอนนี้เรคคอร์ดถูกเพิ่มเสร็จแล้ว จึงได้ ids และ revisions กลับมาด้วย การเพิ่ม 1 เรคคอร์ด (ข้อ a) และการสร้างเอกสารจากเรคคอร์ดที่มีอยู่ (ข้อ b) จะไม่ได้ 202

{
  "job_id": "job_01HXY...",
  "status": "queued",
  "poll_url": "/api/v1/jobs/job_01HXY...",
  "ids": ["105", "106"],
  "revisions": ["1", "1"]
}

ให้เรียก GET /api/v1/jobs/{jobID} เว้นระยะเป็นช่วงๆ จนกว่า status จะเป็น done หรือ failed scope ที่ต้องใช้คือ render

status เปลี่ยนจาก queued (รอคิว) → running (กำลังประมวลผล) → done (เสร็จ) หรือ failed (ล้มเหลว) job มีรายการต่อไปนี้

  • total: จำนวนทั้งหมด done: จำนวนที่เสร็จแล้ว failed: จำนวนที่ล้มเหลว
  • detail: เหตุผล เมื่อ status เป็น failed
  • result_url: มีค่าเมื่อ job เป็น done เป็น signed URL ของไฟล์ ZIP 1 ไฟล์ที่รวมเอกสารทั้งหมด ใช้ได้ 24 ชั่วโมง
  • files: ZIP ไฟล์เดียวกัน ในรูปแบบ [{"url": …, "expires_at": …}]
  • expires_at: เวลาหมดอายุ

ตัวอย่าง job ที่เสร็จแล้ว

{
  "status": "done",
  "total": 2,
  "done": 2,
  "failed": 0,
  "result_url": "https://...",
  "files": [
    { "url": "https://...", "expires_at": "2026-11-01T09:00:00Z" }
  ],
  "expires_at": "2026-11-01T09:00:00Z"
}

curl

curl -sS "https://api.pring.tech/api/v1/jobs/job_01HXY..." -H "Authorization: Bearer $PRING_API_KEY"

Node.js (fetch)

async function waitJob(jobId) {
  for (let i = 0; i < 60; i++) {
    const res = await fetch(`https://api.pring.tech/api/v1/jobs/${jobId}`, {
      headers: { Authorization: `Bearer ${process.env.PRING_API_KEY}` },
    });
    const job = await res.json();
    if (job.status === "done") return job.result_url;
    if (job.status === "failed") throw new Error(job.detail ?? "job failed");
    await new Promise((r) => setTimeout(r, Math.min(2000 * 2 ** Math.floor(i / 5), 30000)));
  }
  throw new Error("timeout");
}

Python (requests)

import time

def wait_job(job_id):
    for i in range(60):
        job = requests.get(
            f"https://api.pring.tech/api/v1/jobs/{job_id}",
            headers={"Authorization": f"Bearer {os.environ['PRING_API_KEY']}"},
            timeout=30,
        ).json()
        if job["status"] == "done":
            return job["result_url"]
        if job["status"] == "failed":
            raise RuntimeError(job.get("detail", "job failed"))
        time.sleep(min(2 * 2 ** (i // 5), 30))
    raise TimeoutError(job_id)

เริ่ม polling ทุก 2 วินาที แล้วค่อยๆ เพิ่มระยะห่าง (ในตัวอย่างสูงสุด 30 วินาที) หากเรียกถี่ๆ ต่อเนื่อง จะติด rate limit (429)

e) รายการแอปและเทมเพลต

GET /api/v1/apps ส่งรายการแอปที่ติดตั้ง PRING และเทมเพลตของแต่ละแอปกลับมา ใช้ตรวจสอบหมายเลขแอปและ ID ของเทมเพลต

curl

curl -sS "https://api.pring.tech/api/v1/apps" -H "Authorization: Bearer $PRING_API_KEY"

Node.js (fetch)

const res = await fetch("https://api.pring.tech/api/v1/apps", {
  headers: { Authorization: `Bearer ${process.env.PRING_API_KEY}` },
});
const { apps } = await res.json();
for (const a of apps) console.log(a.app_id, a.name, a.templates.map((t) => t.id));

Python (requests)

apps = requests.get(
    "https://api.pring.tech/api/v1/apps",
    headers={"Authorization": f"Bearer {os.environ['PRING_API_KEY']}"},
    timeout=30,
).json()["apps"]
for a in apps:
    print(a["app_id"], a["name"], [t["id"] for t in a["templates"]])

ตัวอย่าง response

{
  "apps": [
    {
      "app_id": "19",
      "name": "Invoices",
      "api_token_registered": true,
      "templates": [
        { "id": "tpl_invoice", "name": "Invoice", "formats": ["pdf", "xlsx"] }
      ]
    }
  ]
}

แอปที่ api_token_registered เป็น false จะเพิ่มและดึงเรคคอร์ดไม่ได้ จนกว่าจะลงทะเบียน API token ของ kintone ที่แท็บ “API”

ข้อผิดพลาด

ข้อผิดพลาดส่งกลับเป็น JSON ในรูปแบบ RFC 7807 (Problem Details) (Content-Type: application/problem+json) detail บอกว่าต้องแก้อะไร

{
  "type": "https://pring.tech/th/help/developer/public-api#errors",
  "title": "Forbidden",
  "status": 403,
  "detail": "This API key does not have the render scope.",
  "instance": "/api/v1/apps/19/records/105/render"
}

เมื่อ kintone ไม่รับค่าของเรคคอร์ด body อาจมี errors ด้วย คือข้อความของ kintone แยกตาม field code ({"field_code": ["ข้อความ", ...]})

Status ความหมาย วิธีแก้
400 Bad Request รูปแบบ JSON ไม่ถูกต้อง ขาดรายการที่จำเป็น หรือระบุรูปแบบ (format) ผิด แก้รายการตาม detail แล้วส่งใหม่
401 Unauthorized ไม่มี key, key ไม่ถูกต้อง หรือถูกเพิกถอนแล้ว ดู “ความต่างระหว่าง 401 กับ 403 และวิธีแก้”
403 Forbidden scope, แผน, การจำกัด IP หรือยังไม่ได้ลงทะเบียน API token ของ kintone ดู “ความต่างระหว่าง 401 กับ 403 และวิธีแก้”
404 Not Found ไม่มีแอป เรคคอร์ด เทมเพลต ไฟล์ หรือ job นั้น (ไฟล์ถูกลบหลัง 15 นาที) ตรวจสอบหมายเลขและ ID จากรายการในข้อ e)
409 Conflict เรคคอร์ดถูกเปลี่ยนไปแล้ว (revision ที่ส่งกับ PUT ไม่ตรงกับเรคคอร์ดใน kintone) ดึงเรคคอร์ดใหม่ แล้วส่งพร้อม revision ล่าสุด
413 Payload Too Large records มีตั้งแต่ 101 รายการขึ้นไป แบ่งส่งครั้งละไม่เกิน 100 รายการ
422 Unprocessable Content kintone ไม่รับค่าของเรคคอร์ด (ฟิลด์ที่จำเป็นว่าง ค่าไม่อยู่ในตัวเลือก ฯลฯ) หรือเกินขีดจำกัดต่อ request ของแผน ดูฟิลด์ของ kintone และเหตุผลใน detail และ errors แล้วแก้ค่า หากเกินขีดจำกัด ให้แบ่งส่ง
429 Too Many Requests ติด rate limit หรือถึงเพดานจำนวนหน้าส่งออกของเดือนนี้แล้ว รอตามจำนวนวินาทีใน header Retry-After แล้วส่งใหม่ เพดานจำนวนหน้าแสดงใน detail (ขีดจำกัดการใช้งานและการนับหน้า)
502 Bad Gateway kintone ไม่ตอบกลับ เว้นระยะแล้วส่งใหม่
500, 503 ความล้มเหลวชั่วคราวฝั่ง PRING หรือ kintone เว้นระยะแล้วส่งใหม่ หากยังเกิดต่อเนื่อง ให้ติดต่อฝ่ายสนับสนุนพร้อม instance และเวลา

ลองใหม่ได้สำหรับ 429, 502 และ 5xx response ของ 429 มี header Retry-After (หน่วยวินาที) ให้รอตามนั้นก่อนลองใหม่ สำหรับ 400, 401, 403, 404, 409, 413 และ 422 การส่ง request เดิมซ้ำจะได้ผลเหมือนเดิม ก่อนลองเพิ่มเรคคอร์ด (POST …/records) ใหม่ ให้ตรวจสอบก่อนว่าครั้งก่อนเพิ่มสำเร็จไปแล้วหรือไม่ (เพื่อป้องกันเรคคอร์ดซ้ำ)

ขีดจำกัด

  • จำนวนเรคคอร์ดต่อ request: 1 request ต่อ 1 เรคคอร์ด หรือใส่ใน records ได้ไม่เกิน 100 รายการ ตั้งแต่ 101 รายการขึ้นไปจะได้ 413 หากเกินขีดจำกัดต่อ request ของแผนจะได้ 422
  • Rate limit: ไม่เกิน 100 request ต่อวินาทีต่อ API key และมีขีดจำกัดต่อสัญญา (tenant) ด้วย หากเกินจะได้ 429
  • จำนวนหน้า: จำนวนหน้าของเอกสารที่สร้างผ่าน API นับรวมในจำนวนหน้าที่รวมอยู่ในแผน Pro ต่อเดือน (100,000 หน้า) วิธีนับเหมือนการส่งออกจากหน้าจอ (ขีดจำกัดการใช้งานและการนับหน้า)
  • ระยะเวลาเก็บไฟล์: ไฟล์ที่สร้างถูกลบหลัง 15 นาที ZIP ของ job (result_url) ใช้ได้ 24 ชั่วโมง หากต้องการเก็บ ให้บันทึกลงใน kintone ด้วย attach_to_field
  • File Log: หากต้องการบันทึกไฟล์แนบจาก API ในแอป File Log ให้ลงทะเบียน “API โทเค็นของบันทึกไฟล์” ในแท็บ “API” (ดูข้อ b) หากยังไม่ได้ลงทะเบียน warnings จะมี audit_not_recorded
  • ค่าของเรคคอร์ด: ไม่เก็บบนเซิร์ฟเวอร์ของ PRING (อยู่ในหน่วยความจำระหว่างประมวลผลเท่านั้น)
  • การเรียกที่ดูเหมือนการใช้งานในทางที่ผิด เช่น จำนวนการเรียกเพิ่มขึ้นกะทันหัน อาจถูกหยุดชั่วคราว

คำถามที่พบบ่อย

ใช้ในแผน Lite หรือ Standard ได้ไหม?

ไม่ได้ Public API ใช้ได้ในแผน Pro (รวมถึง Enterprise และสัญญาผ่านตัวแทนจำหน่าย) ในแผน Lite, Standard และช่วงทดลองใช้ฟรี แท็บ "API" ของหน้าตั้งค่าจะแสดงว่าใช้ได้ในแผน Pro และออก key ไม่ได้

เอกสารที่สร้างผ่าน API นับเป็นจำนวนหน้าด้วยไหม?

นับ จำนวนหน้าของเอกสารที่สร้างผ่าน API นับรวมในจำนวนหน้าที่รวมอยู่ในแผน Pro ต่อเดือน (100,000 หน้า) ส่วนที่เกินจำนวนที่รวมอยู่จะถูกเพิ่มเป็นส่วนเสริม เหมือนการส่งออกจากหน้าจอ

ควรสร้าง API token ของ kintone ด้วยสิทธิ์อะไร?

ใช้เพียง 3 สิทธิ์ของแอปนั้น คือ "เพิ่มเรคคอร์ด" "แก้ไขเรคคอร์ด" และ "ดูเรคคอร์ด" อย่าให้สิทธิ์จัดการแอปหรือลบเรคคอร์ด PRING เก็บ token แบบเข้ารหัส และใช้เฉพาะตอนเพิ่มและดึงเรคคอร์ดเท่านั้น

ค่าของเรคคอร์ดถูกเก็บไว้บนเซิร์ฟเวอร์ของ PRING ไหม?

ไม่ ค่าของเรคคอร์ดอยู่ในหน่วยความจำระหว่างประมวลผลเท่านั้น แล้วถูกเพิ่มลงใน kintone ไฟล์ที่สร้างจะเก็บไว้ช่วงสั้นๆ เพื่อให้รับไฟล์ได้ และถูกลบหลัง 15 นาทีตามค่าเริ่มต้น หากต้องการเก็บไฟล์ ให้ส่ง attach_to_field เพื่อบันทึกลงในฟิลด์ไฟล์แนบของ kintone

API key หาย ดูอีกครั้งได้ไหม?

ไม่ได้ key แสดงเพียงครั้งเดียวตอนออก หากทำหาย ให้ออก key ใหม่ เปลี่ยนไปใช้ key ใหม่ แล้วเพิกถอน key เก่า

ส่งได้ครั้งละกี่เรคคอร์ด?

1 request ต่อ 1 เรคคอร์ด หรือใส่ใน records ได้ไม่เกิน 100 รายการ ตั้งแต่ 101 รายการขึ้นไปจะได้ 413 หากเกินขีดจำกัดต่อ request ของแผนจะได้ 422 หากมีมากกว่านั้น ให้แบ่งส่ง เมื่อส่ง records พร้อม ?render= ระบบรับแบบ asynchronous (202 และ job_id)

warnings ใน response มี audit_not_recorded หมายความว่าอะไร?

ไฟล์ถูกบันทึกลงในฟิลด์ไฟล์แนบของ kintone แล้ว แต่ยังไม่ได้ลงทะเบียน API โทเค็นของบันทึกไฟล์ แอป File Log จึงไม่มีแถวของไฟล์นั้น หากต้องการบันทึก ให้สร้าง token ที่มีเฉพาะสิทธิ์ "เพิ่มเรคคอร์ด" ที่ "การตั้งค่าแอป > API Token" ของแอป File Log วางใน "API โทเค็นของบันทึกไฟล์" ในแท็บ "API" แล้วกด "บันทึกโทเค็นบันทึกไฟล์"

key สำหรับทดสอบกับ key สำหรับใช้งานจริงต่างกันอย่างไร?

ขึ้นต้นต่างกันเป็น prk_test_ และ prk_live_ เพื่อให้แยกได้ ใช้ key ทดสอบในสภาพแวดล้อมพัฒนาและทดสอบ ใช้ key ใช้งานจริงกับการเชื่อมต่อจริง และอย่าใส่ปนกันในไฟล์ตั้งค่าเดียวกัน

เขียนและดูแลโดย: TechJapan LLC (ทีม PRING) (ผู้พัฒนาและผู้ให้บริการ) · ติดต่อ