Langsung ke konten
Sursa Developers

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 milikiPakai
Catatan dengan ID stabil di sistem AndaPUT /v1/cards-by-external-id/{external_id}: buat atau ganti menurut ID Anda.
Teks untuk ditambahkan sekali, tanpa ID milik AndaPOST /v1/cards/text
File untuk ditambahkan sekaliPOST /v1/cards
Arsip ZIP berisi banyak filePOST /v1/cards/archive
File yang lebih besar dari batas satu permintaanUnggahan per bagian, lalu salah satu endpoint di atas.
Konten baru untuk kartu yang sudah Anda milikiPUT /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 200 dengan "status": "skipped" dan "reason": "unchanged". Mengulang permintaan selalu aman, bahkan tanpa Idempotency-Key.
  • Konten berubah: kartu mendapat versi baru dan diindeks ulang. Judul, tag, penanggung jawab, kategori, dan metadata kartu mengambil nilai yang Anda kirim; metadata diganti 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_typeIsinya berupa
markdown (default)Markdown.
htmlHTML. Dibersihkan menjadi markup sederhana: judul, paragraf, daftar, tabel, serta tautan http, https, dan mailto. Skrip, gaya, frame, formulir, dan gambar dihapus beserta isinya.
textTeks 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 409 dengan kode cards.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:

  1. Kirim "async": true, agar setiap permintaan kembali segera setelah kartu masuk antrean.
  2. Jalankan beberapa permintaan secara paralel (4 hingga 8), dan perlambat saat header RateLimit menunjukkan sisa permintaan tinggal sedikit. Lihat Batas laju dan kuota.
  3. Pada 429, tunggu selama Retry-After; pada error jaringan atau 5xx, coba ulang permintaan yang sama. Pengulangan tidak berbahaya.
  4. Catat external_id setiap 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

Error yang umum

KodePenyebabYang perlu dilakukan
collections.not_foundTidak ada koleksi dengan ID atau nama ini yang terlihat oleh kunci.Periksa collection_id dengan GET /v1/collections.
collections.no_write_accessKunci tidak boleh menulis ke koleksi ini.Pakai kunci dengan peran editor dan akses ke koleksi itu.
cards.external_id_takenPOST dengan external_id yang sudah dimiliki kartu lain.Pakai PUT /v1/cards-by-external-id/… untuk menggantinya.
cards.managed_by_sourceKartu milik sebuah sumber.Ubah dokumen di sumbernya.
files.type_mismatchNama, jenis, dan isi file tidak sesuai.Kirim file dengan ekstensinya yang sebenarnya.
files.too_largeFile melebihi batas unggahan atau penyimpanan organisasi.Pakai unggahan per bagian, atau kosongkan sebagian penyimpanan.
limits.cardsOrganisasi telah mencapai batas kartu paketnya.Hapus kartu yang tidak lagi diperlukan, atau ubah paketnya.
api.metadata_invalidmetadata melanggar batas.Lihat Metadata.