Перейти до вмісту
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} приймає ідентифікатор запису у вашій системі. Якщо жодна картка не має цього 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 МБ). Більші файли, а також файли в ненадійних мережах спершу завантажуйте частинами.

Замініть вміст картки

Коли ви вже маєте ідентифікатор картки в 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Ключ не бачить жодної колекції з таким ідентифікатором чи назвою.Перевірте 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 порушує ліміт.Див. Метадані.