Přejít na obsah
Sursa Developers

Import dokumentů

Tento návod ukazuje, jak pomocí API karet vložit dokumenty do Sursy: několik dokumentů ze skriptu, nebo všechny dokumenty určitého systému pravidelnou úlohou. Z každého dokumentu se stane karta v kolekci. Lidé ji najdou při vyhledávání, asistent z ní odpovídá a má vlastníka, štítky, ověření a oprávnění jako každá jiná karta.

Pokud chcete, aby Sursa sama zjistila, které dokumenty byly ve vašem systému smazány, nebo pokud dokumenty odesíláte z integrační platformy, použijte místo toho vlastní zdroj. Je určený pro úplné a přírůstkové synchronizace. Tento návod popisuje přímý zápis do kolekce.

Potřebujete klíč API s rozsahem cards:write a roli, která smí zapisovat do cílové kolekce (editor nebo admin). Ukázky používají pomocnou funkci z Rychlého startu.

Výběr správné operace

MátePoužijte
Záznam se stabilním identifikátorem ve vašem systémuPUT /v1/cards-by-external-id/{external_id}: vytvoření nebo nahrazení podle vašeho identifikátoru.
Text, který přidáte jednou, bez vlastního identifikátoruPOST /v1/cards/text
Soubor, který přidáte jednouPOST /v1/cards
Archiv ZIP s mnoha souboryPOST /v1/cards/archive
Soubor větší než limit jednoho požadavkuNahrávání po částech a pak kteroukoli z operací výše.
Nový obsah pro kartu, kterou už mátePUT /v1/cards/{card_id}/content

Pro vše, co importujete víc než jednou, používejte external_id. Díky němu je každý import opakovatelný: další spuštění aktualizuje karty, které vytvořilo, místo aby přidávalo kopie.

Vytvoření nebo nahrazení karty podle vašeho identifikátoru

PUT /v1/cards-by-external-id/{external_id} přijímá identifikátor záznamu ve vašem systému. Pokud žádná karta toto external_id nemá, vytvoří novou (201). Pokud ho některá karta má, nahradí její obsah a údaje (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"}
  }'

Co se stane při opakování:

  • Obsah se nezměnil: nová verze nevznikne. Odpověď je 200 s "status": "skipped" a "reason": "unchanged". Opakovat požadavek je vždy bezpečné, i bez Idempotency-Key.
  • Obsah se změnil: karta dostane novou verzi a znovu se indexuje. Její název, štítky, vlastník, kategorie a metadata převezmou odeslané hodnoty; metadata se nahradí jako celek.
  • Kolekce a složka se uplatní jen při vytvoření karty. Chcete-li kartu později přesunout, změňte ji pomocí PATCH /v1/cards/{card_id}.

Nová verze odebere kartě ověření, stejně jako každá změna obsahu: ověřovatel ji potvrdí znovu.

Formáty textu

content_typeTělo je
markdown (výchozí)Markdown.
htmlHTML. Vyčistí se na jednoduché značky: nadpisy, odstavce, seznamy, tabulky a odkazy http, https a mailto. Skripty, styly, rámy, formuláře a obrázky se odstraní i se svým obsahem.
textProstý text. Odstavce se oddělují prázdnými řádky.

Čekat na kartu, nebo nečekat

Ve výchozím nastavení se požadavek vrátí, jakmile je karta připravená k nalezení, s "status": "ready" a kartou v card. To trvá od zlomku sekundy u krátkého textu po minutu i déle u dlouhého souboru.

U hromadných importů odešlete "async": true. Odpověď přijde okamžitě s "status": "queued" a úlohou indexování v job (s jejím job_id). Úlohu kontrolujte pomocí GET /v1/jobs/{job_id}, nebo sledujte všechny úlohy v GET /v1/jobs/stream. Úloha skončí se status done, error nebo canceled.

curl https://api.sursa.com/v1/jobs/48213 \
  -H "Authorization: Bearer $SURSA_API_KEY"

Nahrání souboru

Soubory se posílají v požadavku multipart/form-data v poli file. Sursa načte PDF, Word, Excel, PowerPoint, tabulky OpenDocument, CSV, Markdown, HTML, AsciiDoc, e-maily (.eml), prostý text a běžné formáty obrázků. Kontroluje, že se název souboru, deklarovaný typ a obsah shodují, a nesoulad odmítne s 415.

Chcete-li vytvořit nebo nahradit kartu se souborem podle vlastního identifikátoru, odešlete soubor na stejnou operaci 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"}'

Ve formuláři je tags řetězec oddělený čárkami a metadata objekt JSON zapsaný jako řetězec. Nová karta bez title dostane jako název jméno souboru.

Chcete-li soubor přidat jednou, bez vlastního identifikátoru, použijte POST /v1/cards se stejným formulářem a s Idempotency-Key. Nahrání souboru, který kolekce už obsahuje, vrátí "status": "skipped" s "duplicate": true a card_id existující karty, pokud nepředáte external_id.

Velikost jednoho souboru omezuje instalace (výchozí je 200 MB). Větší soubory nebo soubory odesílané přes nespolehlivou síť nejdřív nahrajte po částech.

Nahrazení obsahu karty

Pokud už ID karty v Surse máte, PUT /v1/cards/{card_id}/content nahradí její text nebo soubor a vše ostatní ponechá: vlastníka, štítky, ověřovatele, interval ověřování a ručně nastavenou kategorii.

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."}'
  • Opětovně odeslaný stejný obsah vrátí "status": "skipped" s "reason": "unchanged".
  • Karta, která se právě indexuje, vrátí 409 s kódem cards.indexing_in_progress. Zopakujte požadavek za několik sekund.
  • Karta, která pochází ze zdroje, například z konektoru nebo vlastního zdroje, se mění jen ve svém zdroji: cards.managed_by_source.
  • Klíč musí smět vidět celou kartu; částečně viditelná karta vrátí cards.content_whole_access.

Import mnoha dokumentů

Smyčka přes vaše záznamy s PUT /v1/cards-by-external-id/… je nejjednodušší hromadný import a lze ji kdykoli zastavit a spustit znovu. Aby byla rychlá a šetrná k limitu četnosti:

  1. Odesílejte "async": true, aby se každý požadavek vrátil, jakmile se karta zařadí do fronty.
  2. Spouštějte několik požadavků paralelně (4 až 8) a zpomalte, když hlavička RateLimit ukazuje, že zbývá málo požadavků. Viz Limity četnosti a kvóty.
  3. Při 429 počkejte podle Retry-After; při chybě sítě nebo 5xx zopakujte stejný požadavek. Opakování nic nepokazí.
  4. Zaznamenejte external_id každého záznamu, který skončí chybou, a ty na konci zopakujte.
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;
}

U archivu ZIP se soubory vytvoří POST /v1/cards/archive jedním požadavkem kartu z každého podporovaného souboru uvnitř. Odpoví okamžitě plánem (které soubory se stanou kartami, které se přeskočí a proč) a úlohou; výsledek hlásí GET /v1/archives/{job_id}.

Vyhledání a odstranění importovaných karet

Časté chyby

KódPříčinaCo dělat
collections.not_foundKlíč nevidí žádnou kolekci s tímto ID nebo názvem.Zkontrolujte collection_id pomocí GET /v1/collections.
collections.no_write_accessKlíč nesmí do této kolekce zapisovat.Použijte klíč s rolí editor a přístupem ke kolekci.
cards.external_id_takenPOST s external_id, které už má jiná karta.K nahrazení použijte PUT /v1/cards-by-external-id/….
cards.managed_by_sourceKarta patří zdroji.Změňte dokument v jeho zdroji.
files.type_mismatchNázev, typ a obsah souboru si neodpovídají.Odešlete soubor s jeho skutečnou příponou.
files.too_largeSoubor přesahuje limit nahrávání nebo úložiště organizace.Použijte nahrávání po částech, nebo uvolněte úložiště.
limits.cardsOrganizace dosáhla limitu karet svého tarifu.Smažte karty, které už nejsou potřeba, nebo změňte tarif.
api.metadata_invalidmetadata porušuje limit.Viz Metadata.