Nhập tài liệu
Hướng dẫn này trình bày cách đưa tài liệu của bạn vào Sursa bằng API thẻ: vài tài liệu từ một script, hoặc mọi tài liệu của một hệ thống qua một tác vụ chạy định kỳ. Mỗi tài liệu trở thành một thẻ trong một bộ sưu tập. Mọi người tìm thấy nó khi tìm kiếm, trợ lý trả lời dựa trên nó, và nó có người phụ trách, nhãn, kiểm chứng và quyền như mọi thẻ khác.
Nếu bạn muốn Sursa tự xác định tài liệu nào đã bị xóa trong hệ thống của bạn, hoặc bạn đẩy tài liệu từ một nền tảng tích hợp, hãy dùng nguồn tùy chỉnh. Nó được xây dựng cho đồng bộ toàn bộ và đồng bộ gia tăng. Hướng dẫn này trình bày việc ghi trực tiếp vào một bộ sưu tập.
Bạn cần một khóa API có phạm vi quyền cards:write và vai trò được ghi vào bộ sưu tập đích (editor hoặc admin).
Các ví dụ dùng hàm hỗ trợ từ Bắt đầu nhanh.
Chọn endpoint phù hợp
| Bạn có | Hãy dùng |
|---|---|
| Một bản ghi có ID ổn định trong hệ thống của bạn | PUT /v1/cards-by-external-id/{external_id}: tạo hoặc thay thế theo ID của bạn. |
| Văn bản cần thêm một lần, không có ID riêng | POST /v1/cards/text |
| Một tệp cần thêm một lần | POST /v1/cards |
| Một tệp nén ZIP chứa nhiều tệp | POST /v1/cards/archive |
| Một tệp lớn hơn giới hạn của một yêu cầu | Tải lên theo từng phần, rồi dùng bất kỳ endpoint nào ở trên. |
| Nội dung mới cho một thẻ đã có | PUT /v1/cards/{card_id}/content |
Với bất cứ thứ gì bạn nhập nhiều lần, hãy dùng external_id. Nó làm cho mọi lượt nhập có thể lặp lại: chạy lại sẽ
cập nhật các thẻ đã tạo thay vì thêm bản sao.
Tạo hoặc thay thế thẻ theo ID của bạn
PUT /v1/cards-by-external-id/{external_id} nhận ID của bản ghi trong hệ thống của bạn. Nếu chưa có thẻ nào có
external_id này, endpoint tạo một thẻ (201). Nếu đã có, nó thay thế nội dung và thông tin chi tiết của thẻ (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"}
}'Điều gì xảy ra khi lặp lại:
- Nội dung không thay đổi: không có phiên bản mới nào được tạo. Phản hồi là
200với"status": "skipped"và"reason": "unchanged". Lặp lại yêu cầu luôn an toàn, ngay cả khi không cóIdempotency-Key. - Nội dung đã thay đổi: thẻ có phiên bản mới và được lập chỉ mục lại. Tiêu đề, nhãn, người phụ trách, danh mục và
metadatacủa thẻ nhận các giá trị bạn gửi;metadatađược thay thế toàn bộ. - Bộ sưu tập và thư mục chỉ áp dụng khi thẻ được tạo. Để chuyển thẻ sau này, hãy thay đổi nó bằng
PATCH /v1/cards/{card_id}.
Phiên bản mới gỡ bỏ trạng thái kiểm chứng của thẻ, giống như mọi thay đổi nội dung: người kiểm chứng xác nhận lại thẻ.
Định dạng văn bản
content_type | Phần thân là |
|---|---|
markdown (mặc định) | Markdown. |
html | HTML. Nó được làm sạch thành đánh dấu đơn giản: tiêu đề, đoạn văn, danh sách, bảng và liên kết http, https và mailto. Script, style, frame, biểu mẫu và hình ảnh bị loại bỏ cùng với nội dung của chúng. |
text | Văn bản thuần. Các đoạn văn được phân tách bằng dòng trống. |
Chờ thẻ hoặc không
Theo mặc định, yêu cầu trả về khi thẻ đã sẵn sàng để được tìm thấy, với "status": "ready" và thẻ trong card. Việc
đó mất từ một phần nhỏ của giây với văn bản ngắn tới một phút hoặc hơn với tệp dài.
Với lượt nhập hàng loạt, hãy gửi "async": true. Phản hồi tới ngay với "status": "queued" và tác vụ lập chỉ mục
trong job (kèm job_id). Kiểm tra tác vụ bằng GET /v1/jobs/{job_id}, hoặc theo dõi
mọi tác vụ trong GET /v1/jobs/stream. Tác vụ kết thúc với status là done,
error hoặc canceled.
curl https://api.sursa.com/v1/jobs/48213 \
-H "Authorization: Bearer $SURSA_API_KEY"Tải tệp lên
Tệp được gửi trong yêu cầu multipart/form-data, ở trường file. Sursa đọc được PDF, Word, Excel, PowerPoint, bảng
tính OpenDocument, CSV, Markdown, HTML, AsciiDoc, email (.eml), văn bản thuần và các định dạng hình ảnh phổ biến.
Sursa kiểm tra rằng tên tệp, loại được khai báo và nội dung tệp khớp nhau, và từ chối trường hợp không khớp với 415.
Để tạo hoặc thay thế thẻ tệp theo ID của bạn, hãy gửi tệp tới cùng endpoint 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"}'Trong biểu mẫu, tags là chuỗi phân tách bằng dấu phẩy và metadata là đối tượng JSON được viết dưới dạng chuỗi. Thẻ
mới không có title lấy tên tệp làm tiêu đề.
Để thêm một tệp một lần, không có ID riêng, hãy dùng POST /v1/cards với cùng biểu
mẫu và một Idempotency-Key. Tải lên một tệp mà bộ sưu tập đã có trả về "status": "skipped" với "duplicate": true
và card_id của thẻ hiện có, trừ khi bạn truyền external_id.
Kích thước của một tệp bị giới hạn theo bản cài đặt (mặc định 200 MB). Với tệp lớn hơn, hoặc với mạng không ổn định, trước tiên hãy tải tệp lên theo từng phần.
Thay thế nội dung của thẻ
Khi bạn đã có ID Sursa của thẻ, PUT /v1/cards/{card_id}/content thay thế
văn bản hoặc tệp của thẻ và giữ nguyên mọi thứ khác: người phụ trách, nhãn, người kiểm chứng, chu kỳ kiểm chứng và
danh mục được đặt thủ công.
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."}'- Gửi lại cùng nội dung trả về
"status": "skipped"với"reason": "unchanged". - Thẻ đang được lập chỉ mục ngay lúc đó trả về
409với mãcards.indexing_in_progress. Hãy thử lại sau vài giây. - Thẻ đến từ một nguồn, chẳng hạn trình kết nối hoặc nguồn tùy chỉnh, chỉ được thay đổi trong nguồn của nó:
cards.managed_by_source. - Khóa phải được phép xem toàn bộ thẻ; thẻ chỉ hiển thị một phần trả về
cards.content_whole_access.
Nhập nhiều tài liệu
Một vòng lặp qua các bản ghi của bạn với PUT /v1/cards-by-external-id/… là cách nhập hàng loạt đơn giản nhất, và có
thể dừng rồi chạy lại an toàn ở bất kỳ thời điểm nào. Để nhập nhanh và không vượt giới hạn tốc độ:
- Gửi
"async": true, để mỗi yêu cầu trả về ngay khi thẻ được đưa vào hàng đợi. - Chạy song song một vài yêu cầu (từ 4 đến 8), và giảm tốc khi header
RateLimitcho thấy còn ít yêu cầu. Xem Giới hạn tốc độ và hạn mức. - Khi gặp
429, hãy chờ hếtRetry-After; khi có lỗi mạng hoặc5xx, hãy thử lại cùng yêu cầu. Lặp lại không gây hại. - Ghi lại
external_idcủa từng bản ghi kết thúc bằng lỗi, và thử lại chúng ở cuối.
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;
}Với tệp nén ZIP chứa nhiều tệp, POST /v1/cards/archive biến mỗi tệp được hỗ
trợ bên trong thành một thẻ chỉ với một yêu cầu. Endpoint trả lời ngay với kế hoạch (tệp nào trở thành thẻ, tệp nào bị
bỏ qua và vì sao) và một tác vụ; GET /v1/archives/{job_id} báo cáo kết quả.
Tìm và xóa thẻ đã nhập
- Đọc thẻ theo ID của bạn bằng
GET /v1/cards-by-external-id/{external_id}. - Liệt kê các thẻ của một lượt nhập bằng bộ lọc siêu dữ liệu:
GET /v1/cards?metadata[source]=helpdesk. Xem Siêu dữ liệu. - Xóa thẻ bằng
DELETE /v1/cards/{card_id}.
Lỗi thường gặp
| Mã | Nguyên nhân | Cách xử lý |
|---|---|---|
collections.not_found | Khóa không nhìn thấy bộ sưu tập nào có ID hoặc tên này. | Kiểm tra collection_id bằng GET /v1/collections. |
collections.no_write_access | Khóa không được ghi vào bộ sưu tập này. | Dùng khóa có vai trò editor và quyền truy cập bộ sưu tập. |
cards.external_id_taken | POST với external_id mà một thẻ khác đã có. | Dùng PUT /v1/cards-by-external-id/… để thay thế thẻ đó. |
cards.managed_by_source | Thẻ thuộc về một nguồn. | Thay đổi tài liệu trong nguồn của nó. |
files.type_mismatch | Tên, loại và nội dung tệp không khớp nhau. | Gửi tệp với phần mở rộng thật của nó. |
files.too_large | Tệp vượt giới hạn tải lên hoặc dung lượng lưu trữ của tổ chức. | Dùng tải lên theo từng phần, hoặc giải phóng dung lượng lưu trữ. |
limits.cards | Tổ chức đã chạm giới hạn số thẻ của gói. | Xóa những thẻ không còn cần, hoặc đổi gói. |
api.metadata_invalid | metadata vượt một giới hạn. | Xem Siêu dữ liệu. |