นำเข้าเอกสาร
คู่มือนี้แสดงวิธีนำเอกสารของคุณเข้า 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 |
html | HTML ซึ่งจะถูกทำให้เหลือเพียงมาร์กอัปแบบง่าย ได้แก่ หัวข้อ ย่อหน้า รายการ ตาราง และลิงก์ 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/… เป็นการนำเข้าปริมาณมากที่ง่ายที่สุด และหยุดแล้วรันใหม่ได้อย่างปลอดภัยทุกเมื่อ หากต้องการให้เร็วและไม่ชนขีดจำกัดอัตราการเรียก:
- ส่ง
"async": trueเพื่อให้แต่ละคำขอตอบกลับทันทีที่การ์ดเข้าคิว - รันคำขอพร้อมกันจำนวนหนึ่ง (4–8) และชะลอเมื่อเฮดเดอร์
RateLimitแสดงว่าเหลือคำขอน้อย ดู ขีดจำกัดอัตราการเรียกและโควตา - เมื่อได้
429ให้รอตามRetry-Afterเมื่อเกิดข้อผิดพลาดของเครือข่ายหรือ5xxให้ลองคำขอเดิมใหม่ การส่งซ้ำไม่ก่อปัญหา - บันทึก
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} รายงานผลลัพธ์
ค้นหาและนำการ์ดที่นำเข้าออก
- อ่านการ์ดด้วย ID ของคุณด้วย
GET /v1/cards-by-external-id/{external_id} - แสดงรายการการ์ดของการนำเข้าครั้งหนึ่งด้วยตัวกรองข้อมูลเมตา:
GET /v1/cards?metadata[source]=helpdeskดู ข้อมูลเมตา - ลบการ์ดด้วย
DELETE /v1/cards/{card_id}
ข้อผิดพลาดที่พบบ่อย
| รหัส | สาเหตุ | สิ่งที่ต้องทำ |
|---|---|---|
collections.not_found | คีย์มองไม่เห็นคอลเลกชันที่มี ID หรือชื่อนี้ | ตรวจ collection_id ด้วย GET /v1/collections |
collections.no_write_access | คีย์ไม่มีสิทธิ์เขียนลงในคอลเลกชันนี้ | ใช้คีย์ที่มีบทบาท editor และมีสิทธิ์เข้าถึงคอลเลกชันนั้น |
cards.external_id_taken | POST ด้วย external_id ที่การ์ดอื่นใช้อยู่แล้ว | ใช้ PUT /v1/cards-by-external-id/… เพื่อแทนที่การ์ดนั้น |
cards.managed_by_source | การ์ดเป็นของแหล่งข้อมูล | เปลี่ยนเอกสารในแหล่งข้อมูลนั้น |
files.type_mismatch | ชื่อ ประเภท และเนื้อหาของไฟล์ไม่สอดคล้องกัน | ส่งไฟล์ด้วยนามสกุลจริงของไฟล์ |
files.too_large | ไฟล์เกินขีดจำกัดการอัปโหลดหรือพื้นที่จัดเก็บขององค์กร | ใช้ การอัปโหลดเป็นส่วน หรือเพิ่มพื้นที่ว่างในพื้นที่จัดเก็บ |
limits.cards | องค์กรมีการ์ดถึงขีดจำกัดของแพ็กเกจแล้ว | ลบการ์ดที่ไม่ต้องใช้แล้ว หรือเปลี่ยนแพ็กเกจ |
api.metadata_invalid | metadata เกินขีดจำกัด | ดู ข้อมูลเมตา |