Mengimpor dokumen
Panduan ini menunjukkan cara memasukkan dokumen Anda ke Sursa dengan API kartu: beberapa dokumen dari sebuah skrip, atau setiap dokumen dari suatu sistem melalui job rutin. Setiap dokumen menjadi kartu di sebuah koleksi. Orang menemukannya di pencarian, asisten menjawab berdasarkan kartu itu, dan kartu itu memiliki penanggung jawab, tag, verifikasi, dan izin seperti kartu lainnya.
Jika Anda ingin Sursa mengetahui dokumen mana yang dihapus di sistem Anda, atau Anda mengirim dokumen dari platform integrasi, pakai sumber kustom. Sumber kustom dibuat untuk sinkronisasi penuh dan inkremental. Panduan ini membahas penulisan langsung ke sebuah koleksi.
Anda membutuhkan kunci API dengan cakupan cards:write dan peran yang dapat menulis ke koleksi tujuan (editor atau
admin). Contoh-contoh memakai fungsi bantu dari Mulai cepat.
Memilih endpoint yang tepat
| Yang Anda miliki | Pakai |
|---|---|
| Catatan dengan ID stabil di sistem Anda | PUT /v1/cards-by-external-id/{external_id}: buat atau ganti menurut ID Anda. |
| Teks untuk ditambahkan sekali, tanpa ID milik Anda | POST /v1/cards/text |
| File untuk ditambahkan sekali | POST /v1/cards |
| Arsip ZIP berisi banyak file | POST /v1/cards/archive |
| File yang lebih besar dari batas satu permintaan | Unggahan per bagian, lalu salah satu endpoint di atas. |
| Konten baru untuk kartu yang sudah Anda miliki | PUT /v1/cards/{card_id}/content |
Untuk apa pun yang Anda impor lebih dari sekali, pakai external_id. Dengan ini setiap impor dapat diulang:
menjalankannya lagi akan memperbarui kartu yang telah dibuatnya, alih-alih menambahkan salinan.
Membuat atau mengganti kartu menurut ID Anda
PUT /v1/cards-by-external-id/{external_id} menerima ID catatan di sistem Anda. Jika tidak ada kartu dengan
external_id ini, endpoint ini membuat kartu (201). Jika ada kartu dengan ID itu, endpoint ini mengganti konten dan
detail kartu (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"}
}'Yang terjadi saat diulang:
- Konten tidak berubah: tidak ada versi baru yang dibuat. Responsnya
200dengan"status": "skipped"dan"reason": "unchanged". Mengulang permintaan selalu aman, bahkan tanpaIdempotency-Key. - Konten berubah: kartu mendapat versi baru dan diindeks ulang. Judul, tag, penanggung jawab, kategori, dan
metadatakartu mengambil nilai yang Anda kirim;metadatadiganti secara utuh. - Koleksi dan folder hanya berlaku saat kartu dibuat. Untuk memindahkan kartu nanti, ubah kartu dengan
PATCH /v1/cards/{card_id}.
Versi baru menghapus verifikasi kartu, seperti setiap perubahan konten: verifikator mengonfirmasinya lagi.
Format teks
content_type | Isinya berupa |
|---|---|
markdown (default) | Markdown. |
html | HTML. Dibersihkan menjadi markup sederhana: judul, paragraf, daftar, tabel, serta tautan http, https, dan mailto. Skrip, gaya, frame, formulir, dan gambar dihapus beserta isinya. |
text | Teks biasa. Paragraf dipisahkan oleh baris kosong. |
Menunggu kartu, atau tidak
Secara default, permintaan kembali setelah kartu siap ditemukan, dengan "status": "ready" dan kartu di card. Hal
itu memakan waktu dari sepersekian detik untuk teks pendek hingga satu menit atau lebih untuk file panjang.
Untuk impor massal, kirim "async": true. Respons datang seketika dengan "status": "queued" dan job pengindeksan
di job (dengan job_id-nya). Periksa job dengan GET /v1/jobs/{job_id}, atau ikuti
semua job di GET /v1/jobs/stream. Job berakhir dengan status done, error, atau canceled.
curl https://api.sursa.com/v1/jobs/48213 \
-H "Authorization: Bearer $SURSA_API_KEY"Mengunggah file
File dikirim dalam permintaan multipart/form-data, di field file. Sursa membaca PDF, Word, Excel, PowerPoint,
spreadsheet OpenDocument, CSV, Markdown, HTML, AsciiDoc, email (.eml), teks biasa, dan format gambar yang umum.
Sursa memeriksa bahwa nama file, jenis yang dinyatakan, dan isinya sesuai, dan menolak ketidaksesuaian dengan 415.
Untuk membuat atau mengganti kartu file menurut ID Anda, kirim file ke PUT /v1/cards-by-external-id/{external_id}
yang sama:
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"}'Dalam formulir, tags adalah string yang dipisahkan koma dan metadata adalah objek JSON yang ditulis sebagai
string. Kartu baru tanpa title mendapat nama file sebagai judulnya.
Untuk menambahkan file sekali, tanpa ID milik Anda, pakai POST /v1/cards dengan
formulir yang sama dan Idempotency-Key. Mengunggah file yang sudah ada di koleksi mengembalikan
"status": "skipped" dengan "duplicate": true dan card_id yang sudah ada, kecuali jika Anda memberikan
external_id.
Ukuran satu file dibatasi oleh instalasi (secara default 200 MB). Untuk file yang lebih besar, atau untuk jaringan yang tidak andal, unggah file per bagian terlebih dahulu.
Mengganti konten kartu
Jika Anda sudah memiliki ID Sursa sebuah kartu,
PUT /v1/cards/{card_id}/content mengganti teks atau file-nya dan
mempertahankan semua hal lainnya: penanggung jawab, tag, verifikator, interval verifikasi, dan kategori yang
ditetapkan secara manual.
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."}'- Konten yang sama lagi mengembalikan
"status": "skipped"dengan"reason": "unchanged". - Kartu yang sedang diindeks saat ini mengembalikan
409dengan kodecards.indexing_in_progress. Coba lagi dalam beberapa detik. - Kartu yang berasal dari sebuah sumber, seperti konektor atau sumber kustom, hanya diubah di sumbernya:
cards.managed_by_source. - Kunci harus boleh melihat seluruh kartu; kartu yang hanya terlihat sebagian mengembalikan
cards.content_whole_access.
Mengimpor banyak dokumen
Loop atas catatan Anda dengan PUT /v1/cards-by-external-id/… adalah impor massal yang paling sederhana, dan aman
untuk dihentikan lalu dijalankan lagi kapan saja. Agar cepat dan ramah terhadap batas laju:
- Kirim
"async": true, agar setiap permintaan kembali segera setelah kartu masuk antrean. - Jalankan beberapa permintaan secara paralel (4 hingga 8), dan perlambat saat header
RateLimitmenunjukkan sisa permintaan tinggal sedikit. Lihat Batas laju dan kuota. - Pada
429, tunggu selamaRetry-After; pada error jaringan atau5xx, coba ulang permintaan yang sama. Pengulangan tidak berbahaya. - Catat
external_idsetiap catatan yang berakhir dengan error, dan coba ulang catatan itu di akhir.
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;
}Untuk arsip ZIP berisi file, POST /v1/cards/archive mengubah setiap file
yang didukung di dalamnya menjadi kartu dengan satu permintaan. Endpoint ini langsung menjawab dengan rencana (file
mana yang menjadi kartu dan mana yang dilewati, serta alasannya) dan sebuah job;
GET /v1/archives/{job_id} melaporkan hasilnya.
Menemukan dan menghapus kartu yang diimpor
- Baca kartu menurut ID Anda dengan
GET /v1/cards-by-external-id/{external_id}. - Tampilkan daftar kartu dari satu impor dengan penyaring metadata:
GET /v1/cards?metadata[source]=helpdesk. Lihat Metadata. - Hapus kartu dengan
DELETE /v1/cards/{card_id}.
Error yang umum
| Kode | Penyebab | Yang perlu dilakukan |
|---|---|---|
collections.not_found | Tidak ada koleksi dengan ID atau nama ini yang terlihat oleh kunci. | Periksa collection_id dengan GET /v1/collections. |
collections.no_write_access | Kunci tidak boleh menulis ke koleksi ini. | Pakai kunci dengan peran editor dan akses ke koleksi itu. |
cards.external_id_taken | POST dengan external_id yang sudah dimiliki kartu lain. | Pakai PUT /v1/cards-by-external-id/… untuk menggantinya. |
cards.managed_by_source | Kartu milik sebuah sumber. | Ubah dokumen di sumbernya. |
files.type_mismatch | Nama, jenis, dan isi file tidak sesuai. | Kirim file dengan ekstensinya yang sebenarnya. |
files.too_large | File melebihi batas unggahan atau penyimpanan organisasi. | Pakai unggahan per bagian, atau kosongkan sebagian penyimpanan. |
limits.cards | Organisasi telah mencapai batas kartu paketnya. | Hapus kartu yang tidak lagi diperlukan, atau ubah paketnya. |
api.metadata_invalid | metadata melanggar batas. | Lihat Metadata. |