ข้ามไปยังเนื้อหา
Sursa Developers

นำเข้าเอกสาร

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

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

คุณต้องมีคีย์ API ที่มีขอบเขตสิทธิ์ cards:write และบทบาทที่เขียนลงในคอลเลกชันปลายทางได้ (editor หรือ admin) ตัวอย่างใช้ฟังก์ชันช่วยจาก เริ่มต้นอย่างรวดเร็ว

เลือกเอนด์พอยต์ที่เหมาะสม

สิ่งที่คุณมีสิ่งที่ใช้
รายการที่มี ID คงที่ในระบบของคุณPUT /v1/cards-by-external-id/{external_id} สร้างหรือแทนที่ด้วย ID ของคุณ
ข้อความที่จะเพิ่มครั้งเดียว โดยไม่มี ID ของคุณเองPOST /v1/cards/text
ไฟล์ที่จะเพิ่มครั้งเดียวPOST /v1/cards
ไฟล์บีบอัด ZIP ที่มีไฟล์จำนวนมากPOST /v1/cards/archive
ไฟล์ที่ใหญ่เกินขีดจำกัดของคำขอเดียวการอัปโหลดเป็นส่วน แล้วตามด้วยเอนด์พอยต์ใดก็ได้ข้างต้น
เนื้อหาใหม่สำหรับการ์ดที่มีอยู่แล้วPUT /v1/cards/{card_id}/content

สำหรับสิ่งที่นำเข้ามากกว่าหนึ่งครั้ง ให้ใช้ external_id ซึ่งทำให้ทุกการนำเข้าทำซ้ำได้ การรันอีกครั้งจะอัปเดตการ์ดที่สร้างไว้แทนการเพิ่มสำเนา

สร้างหรือแทนที่การ์ดด้วย ID ของคุณ

PUT /v1/cards-by-external-id/{external_id} รับ ID ของรายการในระบบของคุณ หากไม่มีการ์ดที่มี external_id นี้ ระบบจะสร้างการ์ดใหม่ (201) หากมีการ์ดที่มีค่านี้อยู่แล้ว ระบบจะแทนที่เนื้อหาและรายละเอียดของการ์ดนั้น (200)

curl -X PUT https://api.sursa.com/v1/cards-by-external-id/kb-article-1042 \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "collection_id": 3,
    "folder_id": "0f8e2d7c-4b6a-4e1f-9c3d-2a5b8e7f1c40",
    "title": "Returning a damaged item",
    "content_type": "html",
    "body": "<h2>Damaged items</h2><p>Send a photo within 7 days and we ship a replacement.</p>",
    "tags": ["returns", "shipping"],
    "metadata": {"source": "helpdesk", "article_id": "1042"}
  }'

สิ่งที่เกิดขึ้นเมื่อส่งซ้ำ:

  • เนื้อหาไม่เปลี่ยน ไม่มีการสร้างเวอร์ชันใหม่ การตอบกลับเป็น 200 พร้อม "status": "skipped" และ "reason": "unchanged" การส่งคำขอซ้ำจึงปลอดภัยเสมอ แม้ไม่มี Idempotency-Key
  • เนื้อหาเปลี่ยน การ์ดได้เวอร์ชันใหม่และถูกทำดัชนีอีกครั้ง ชื่อ แท็ก ผู้รับผิดชอบ หมวดหมู่ และ metadata ของการ์ดจะใช้ค่าที่คุณส่งมา โดย metadata จะถูกแทนที่ทั้งชุด
  • คอลเลกชันและโฟลเดอร์ มีผลเฉพาะตอนสร้างการ์ด หากต้องการย้ายการ์ดภายหลัง ให้เปลี่ยนด้วย PATCH /v1/cards/{card_id}

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

รูปแบบข้อความ

content_typeเนื้อหาเป็น
markdown (ค่าเริ่มต้น)Markdown
htmlHTML ซึ่งจะถูกทำให้เหลือเพียงมาร์กอัปแบบง่าย ได้แก่ หัวข้อ ย่อหน้า รายการ ตาราง และลิงก์ http https และ mailto สคริปต์ สไตล์ เฟรม ฟอร์ม และรูปภาพจะถูกนำออกพร้อมเนื้อหาข้างใน
textข้อความธรรมดา ย่อหน้าคั่นด้วยบรรทัดว่าง

รอการ์ดหรือไม่รอ

โดยค่าเริ่มต้น คำขอจะตอบกลับเมื่อการ์ดพร้อมให้ค้นพบแล้ว พร้อม "status": "ready" และการ์ดใน card ซึ่งใช้เวลาตั้งแต่เสี้ยววินาทีสำหรับข้อความสั้น ไปจนถึงหนึ่งนาทีหรือมากกว่าสำหรับไฟล์ยาว

สำหรับการนำเข้าปริมาณมาก ให้ส่ง "async": true การตอบกลับจะมาทันทีพร้อม "status": "queued" และงานทำดัชนีใน job (พร้อม job_id) ตรวจสอบงานด้วย GET /v1/jobs/{job_id} หรือติดตามงานทั้งหมดใน GET /v1/jobs/stream งานจะจบด้วย status เป็น done error หรือ canceled

curl https://api.sursa.com/v1/jobs/48213 \
  -H "Authorization: Bearer $SURSA_API_KEY"

อัปโหลดไฟล์

ไฟล์ส่งในคำขอ multipart/form-data ในฟิลด์ file Sursa อ่านไฟล์ PDF Word Excel PowerPoint สเปรดชีต OpenDocument CSV Markdown HTML AsciiDoc อีเมล (.eml) ข้อความธรรมดา และรูปแบบรูปภาพทั่วไป Sursa ตรวจว่าชื่อไฟล์ ประเภทที่ระบุ และเนื้อหาของไฟล์สอดคล้องกัน และปฏิเสธไฟล์ที่ไม่สอดคล้องด้วย 415

หากต้องการสร้างหรือแทนที่การ์ดไฟล์ด้วย ID ของคุณ ให้ส่งไฟล์ไปยัง PUT /v1/cards-by-external-id/{external_id} เดียวกัน:

curl -X PUT https://api.sursa.com/v1/cards-by-external-id/handbook-2026 \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -F "file=@employee-handbook.pdf" \
  -F "collection_id=3" \
  -F "tags=hr,policies" \
  -F 'metadata={"owner_team":"people"}'

ในฟอร์ม tags เป็นสตริงที่คั่นด้วยจุลภาค และ metadata เป็นออบเจ็กต์ JSON ที่เขียนเป็นสตริง การ์ดใหม่ที่ไม่มี title จะใช้ชื่อไฟล์เป็นชื่อการ์ด

หากต้องการเพิ่มไฟล์ครั้งเดียวโดยไม่มี ID ของคุณเอง ให้ใช้ POST /v1/cards ด้วยฟอร์มเดียวกันและ Idempotency-Key การอัปโหลดไฟล์ที่คอลเลกชันมีอยู่แล้วจะได้ "status": "skipped" พร้อม "duplicate": true และ card_id ของการ์ดที่มีอยู่ เว้นแต่คุณจะส่ง external_id

ขนาดของไฟล์หนึ่งไฟล์ถูกจำกัดโดยระบบที่ติดตั้ง (ค่าเริ่มต้น 200 MB) สำหรับไฟล์ที่ใหญ่กว่านั้น หรือเครือข่ายที่ไม่เสถียร ให้อัปโหลดไฟล์ เป็นส่วน ก่อน

แทนที่เนื้อหาของการ์ด

เมื่อคุณมี ID ของการ์ดใน Sursa อยู่แล้ว PUT /v1/cards/{card_id}/content จะแทนที่ข้อความหรือไฟล์ของการ์ดและคงสิ่งอื่นไว้ทั้งหมด ได้แก่ ผู้รับผิดชอบ แท็ก ผู้ตรวจสอบ รอบการตรวจสอบ และหมวดหมู่ที่ตั้งด้วยมือ

curl -X PUT https://api.sursa.com/v1/cards/3f2c9a7e-5b1d-4c8e-9f0a-1b2c3d4e5f60/content \
  -H "Authorization: Bearer $SURSA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content_type": "markdown", "body": "# Refund policy\n\nRefunds are processed within 10 days."}'
  • เนื้อหาเดิมซ้ำอีกครั้งจะได้ "status": "skipped" พร้อม "reason": "unchanged"
  • การ์ดที่กำลังทำดัชนีอยู่จะได้การตอบกลับ 409 พร้อมรหัส cards.indexing_in_progress ให้ลองใหม่ในอีกไม่กี่วินาที
  • การ์ดที่มาจากแหล่งข้อมูล เช่น คอนเนกเตอร์หรือแหล่งข้อมูลแบบกำหนดเอง เปลี่ยนแปลงได้เฉพาะในแหล่งข้อมูลนั้น: cards.managed_by_source
  • คีย์ต้องมีสิทธิ์มองเห็นการ์ดทั้งใบ การ์ดที่มองเห็นได้เพียงบางส่วนจะได้ cards.content_whole_access

นำเข้าเอกสารจำนวนมาก

ลูปที่วนผ่านรายการของคุณด้วย PUT /v1/cards-by-external-id/… เป็นการนำเข้าปริมาณมากที่ง่ายที่สุด และหยุดแล้วรันใหม่ได้อย่างปลอดภัยทุกเมื่อ หากต้องการให้เร็วและไม่ชนขีดจำกัดอัตราการเรียก:

  1. ส่ง "async": true เพื่อให้แต่ละคำขอตอบกลับทันทีที่การ์ดเข้าคิว
  2. รันคำขอพร้อมกันจำนวนหนึ่ง (4–8) และชะลอเมื่อเฮดเดอร์ RateLimit แสดงว่าเหลือคำขอน้อย ดู ขีดจำกัดอัตราการเรียกและโควตา
  3. เมื่อได้ 429 ให้รอตาม Retry-After เมื่อเกิดข้อผิดพลาดของเครือข่ายหรือ 5xx ให้ลองคำขอเดิมใหม่ การส่งซ้ำไม่ก่อปัญหา
  4. บันทึก external_id ของแต่ละรายการที่จบด้วยข้อผิดพลาด แล้วลองรายการเหล่านั้นใหม่ในตอนท้าย
import { api } from "./sursa.mjs";

async function importAll(records, concurrency = 6) {
  const failed = [];
  const queue = [...records];
  async function worker() {
    for (let record = queue.shift(); record; record = queue.shift()) {
      try {
        await api("PUT", `/v1/cards-by-external-id/${encodeURIComponent(record.id)}`, {
          collection_id: 3,
          title: record.title,
          content_type: "html",
          body: record.html,
          metadata: { source: "helpdesk" },
          async: true,
        });
      } catch (error) {
        failed.push({ id: record.id, error: String(error) });
      }
    }
  }
  await Promise.all(Array.from({ length: concurrency }, worker));
  return failed;
}

สำหรับไฟล์บีบอัด ZIP POST /v1/cards/archive เปลี่ยนไฟล์ที่รองรับแต่ละไฟล์ข้างในให้เป็นการ์ดด้วยคำขอเดียว เอนด์พอยต์นี้ตอบกลับทันทีพร้อมแผน (ไฟล์ใดจะเป็นการ์ด ไฟล์ใดจะถูกข้าม และเพราะอะไร) และงานประมวลผล ส่วน GET /v1/archives/{job_id} รายงานผลลัพธ์

ค้นหาและนำการ์ดที่นำเข้าออก

ข้อผิดพลาดที่พบบ่อย

รหัสสาเหตุสิ่งที่ต้องทำ
collections.not_foundคีย์มองไม่เห็นคอลเลกชันที่มี ID หรือชื่อนี้ตรวจ collection_id ด้วย GET /v1/collections
collections.no_write_accessคีย์ไม่มีสิทธิ์เขียนลงในคอลเลกชันนี้ใช้คีย์ที่มีบทบาท editor และมีสิทธิ์เข้าถึงคอลเลกชันนั้น
cards.external_id_takenPOST ด้วย external_id ที่การ์ดอื่นใช้อยู่แล้วใช้ PUT /v1/cards-by-external-id/… เพื่อแทนที่การ์ดนั้น
cards.managed_by_sourceการ์ดเป็นของแหล่งข้อมูลเปลี่ยนเอกสารในแหล่งข้อมูลนั้น
files.type_mismatchชื่อ ประเภท และเนื้อหาของไฟล์ไม่สอดคล้องกันส่งไฟล์ด้วยนามสกุลจริงของไฟล์
files.too_largeไฟล์เกินขีดจำกัดการอัปโหลดหรือพื้นที่จัดเก็บขององค์กรใช้ การอัปโหลดเป็นส่วน หรือเพิ่มพื้นที่ว่างในพื้นที่จัดเก็บ
limits.cardsองค์กรมีการ์ดถึงขีดจำกัดของแพ็กเกจแล้วลบการ์ดที่ไม่ต้องใช้แล้ว หรือเปลี่ยนแพ็กเกจ
api.metadata_invalidmetadata เกินขีดจำกัดดู ข้อมูลเมตา