Към съдържанието
Sursa Developers

Импорт на документи

Това ръководство показва как да поставите документите си в Sursa с API за карти: няколко документа от скрипт или всички документи на дадена система чрез редовно задание. Всеки документ става карта в колекция. Хората я намират при търсене, асистентът отговаря въз основа на нея и тя има отговорник, етикети, проверка и права като всяка друга карта.

Ако искате Sursa сама да установява кои документи са изтрити във вашата система или изпращате документи от платформа за интеграции, използвайте вместо това собствен източник. Той е създаден за пълни и инкрементални синхронизации. Това ръководство описва директния запис в колекция.

Нужен ви е API ключ с обхвата cards:write и роля, която може да записва в целевата колекция (editor или admin). Примерите използват помощната функция от Бърз старт.

Изберете подходящата операция

ИматеИзползвайте
Запис със стабилен идентификатор във вашата системаPUT /v1/cards-by-external-id/{external_id}: създаване или замяна по вашия идентификатор.
Текст, който добавяте веднъж, без собствен идентификаторPOST /v1/cards/text
Файл, който добавяте веднъжPOST /v1/cards
ZIP архив с много файловеPOST /v1/cards/archive
Файл, по-голям от лимита за една заявкаКачване на части, а след това някоя от операциите по-горе.
Ново съдържание за карта, която вече иматеPUT /v1/cards/{card_id}/content

За всичко, което импортирате повече от веднъж, използвайте external_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), обикновен текст и разпространените формати на изображения. Тя проверява дали името на файла, обявеният тип и съдържанието му си съответстват и отхвърля несъответствие с 415.

За да създадете или замените карта с файл по вашия идентификатор, изпратете файла до същата 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 получава за заглавие името на файла.

За да добавите файл веднъж, без собствен идентификатор, използвайте POST /v1/cards със същия формуляр и Idempotency-Key. Качването на файл, който колекцията вече има, връща "status": "skipped" с "duplicate": true и съществуващия card_id, освен ако не подадете external_id.

Размерът на един файл се ограничава от инсталацията (по подразбиране 200 MB). За по-големи файлове или за ненадеждни мрежи първо качете файла на части.

Замяна на съдържанието на карта

Когато вече имате идентификатора на картата в 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 нарушава лимит.Вж. Метаданни.