Importar documents
Aquesta guia mostra com posar els vostres documents a Sursa amb l’API d’entrades: uns quants documents des d’un script, o tots els documents d’un sistema amb un treball periòdic. Cada document es converteix en una entrada d’una col·lecció. La gent la troba a la cerca, l’assistent respon a partir del seu contingut, i té responsable, etiquetes, verificació i permisos com qualsevol altra entrada.
Si voleu que Sursa determini quins documents s’han eliminat al vostre sistema, o si envieu documents des d’una plataforma d’integració, feu servir una font personalitzada. Està pensada per a sincronitzacions completes i incrementals. Aquesta guia tracta de l’escriptura directa en una col·lecció.
Necessiteu una clau d’API amb l’àmbit cards:write i un rol que pugui escriure a la col·lecció de destinació
(editor o admin). Els exemples fan servir la funció auxiliar de l’Inici ràpid.
Triar el punt final adequat
| Teniu | Feu servir |
|---|---|
| Un element amb un ID estable al vostre sistema | PUT /v1/cards-by-external-id/{external_id}: crear o substituir pel vostre ID. |
| Un text per afegir una sola vegada, sense ID propi | POST /v1/cards/text |
| Un fitxer per afegir una sola vegada | POST /v1/cards |
| Un arxiu comprimit ZIP amb molts fitxers | POST /v1/cards/archive |
| Un fitxer més gran que el límit d’una sola sol·licitud | Una pujada per parts i després qualsevol dels punts finals anteriors. |
| Contingut nou per a una entrada que ja teniu | PUT /v1/cards/{card_id}/content |
Per a qualsevol cosa que importeu més d’una vegada, feu servir external_id. Fa que cada importació es pugui repetir:
si la torneu a executar, actualitza les entrades que va crear en lloc d’afegir-ne còpies.
Crear o substituir una entrada pel vostre ID
PUT /v1/cards-by-external-id/{external_id} rep l’ID de l’element al vostre sistema. Si cap entrada no té aquest
external_id, en crea una (201). Si una entrada el té, en substitueix el contingut i les dades (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"}
}'Què passa en una repetició:
- El contingut no ha canviat: no es crea cap versió nova. La resposta és
200amb"status": "skipped"i"reason": "unchanged". Repetir la sol·licitud no comporta mai cap risc, fins i tot senseIdempotency-Key. - El contingut ha canviat: l’entrada rep una versió nova i es torna a indexar. El títol, les etiquetes, el
responsable, la categoria i
metadataprenen els valors que heu enviat;metadatase substitueix sencer. - La col·lecció i la carpeta només s’apliquen quan es crea l’entrada. Per moure una entrada més endavant,
canvieu-la amb
PATCH /v1/cards/{card_id}.
Una versió nova retira la verificació de l’entrada, com qualsevol canvi de contingut: un verificador l’ha de tornar a confirmar.
Formats de text
content_type | El cos és |
|---|---|
markdown (per defecte) | Markdown. |
html | HTML. Es redueix a un marcatge senzill: títols, paràgrafs, llistes, taules i enllaços http, https i mailto. Els scripts, els estils, els marcs, els formularis i les imatges s’eliminen amb el seu contingut. |
text | Text pla. Els paràgrafs se separen amb línies en blanc. |
Esperar l’entrada o no
Per defecte, la sol·licitud retorna quan l’entrada ja es pot trobar, amb "status": "ready" i l’entrada a card.
Això triga des d’una fracció de segon, per a un text curt, fins a un minut o més, per a un fitxer llarg.
Per a les importacions massives, envieu "async": true. La resposta arriba immediatament amb "status": "queued" i
el treball d’indexació a job (amb el seu job_id). Comproveu el treball amb
GET /v1/jobs/{job_id}, o seguiu tots els treballs a
GET /v1/jobs/stream. Un treball acaba amb status igual a done, error o canceled.
curl https://api.sursa.com/v1/jobs/48213 \
-H "Authorization: Bearer $SURSA_API_KEY"Pujar un fitxer
Els fitxers van en una sol·licitud multipart/form-data, al camp file. Sursa llegeix PDF, Word, Excel, PowerPoint,
fulls de càlcul d’OpenDocument, CSV, Markdown, HTML, AsciiDoc, correu electrònic (.eml), text pla i els formats
d’imatge habituals. Comprova que el nom, el tipus declarat i el contingut del fitxer concordin, i rebutja una
discrepància amb 415.
Per crear o substituir una entrada de fitxer pel vostre ID, envieu el fitxer al mateix
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"}'En un formulari, tags és una cadena separada per comes i metadata és un objecte JSON escrit com a cadena. Una
entrada nova sense title rep el nom del fitxer com a títol.
Per afegir un fitxer una sola vegada, sense ID propi, feu servir POST /v1/cards amb
el mateix formulari i una Idempotency-Key. Si pugeu un fitxer que la col·lecció ja té, es retorna
"status": "skipped" amb "duplicate": true i el card_id existent, tret que passeu un external_id.
La mida d’un fitxer la limita la instal·lació (200 MB per defecte). Per a fitxers més grans, o per a xarxes poc fiables, pugeu primer el fitxer per parts.
Substituir el contingut d’una entrada
Quan ja teniu l’ID de Sursa d’una entrada, PUT /v1/cards/{card_id}/content
en substitueix el text o el fitxer i conserva tota la resta: el responsable, les etiquetes, els verificadors,
l’interval de verificació i una categoria definida a mà.
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."}'- Si torneu a enviar el mateix contingut, es retorna
"status": "skipped"amb"reason": "unchanged". - Una entrada que s’està indexant en aquest moment retorna
409amb el codicards.indexing_in_progress. Torneu-ho a provar d’aquí a uns segons. - Una entrada que prové d’una font, com ara un connector o una font personalitzada, només es canvia a la seva font:
cards.managed_by_source. - La clau ha de poder veure tota l’entrada; una entrada visible només en part retorna
cards.content_whole_access.
Importar molts documents
Un bucle sobre els vostres elements amb PUT /v1/cards-by-external-id/… és la importació massiva més senzilla, i la
podeu aturar i tornar a executar en qualsevol moment sense risc. Per fer-la ràpida i respectuosa amb el límit de
freqüència:
- Envieu
"async": true, perquè cada sol·licitud retorni tan bon punt l’entrada és a la cua. - Executeu unes quantes sol·licituds en paral·lel (de 4 a 8) i aneu més a poc a poc quan la capçalera
RateLimitmostri que en queden poques. Vegeu Límits de freqüència i quotes. - Amb un
429, espereu el temps deRetry-After; amb un error de xarxa o un5xx, reintenteu la mateixa sol·licitud. Les repeticions no fan cap mal. - Anoteu l’
external_idde cada element que acabi en error i reintenteu-los al final.
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;
}Per a un arxiu comprimit ZIP de fitxers, POST /v1/cards/archive converteix
en una entrada cada fitxer compatible que conté, amb una sola sol·licitud. Respon immediatament amb la previsió
(quins fitxers es converteixen en entrades i quins s’ometen, i per què) i un treball;
GET /v1/archives/{job_id} informa del resultat.
Trobar i eliminar les entrades importades
- Llegiu una entrada pel vostre ID amb
GET /v1/cards-by-external-id/{external_id}. - Enumereu les entrades d’una importació amb un filtre de metadades:
GET /v1/cards?metadata[source]=helpdesk. Vegeu Metadades. - Elimineu una entrada amb
DELETE /v1/cards/{card_id}.
Errors habituals
| Codi | Causa | Què cal fer |
|---|---|---|
collections.not_found | La clau no veu cap col·lecció amb aquest ID o aquest nom. | Comproveu collection_id amb GET /v1/collections. |
collections.no_write_access | La clau no pot escriure en aquesta col·lecció. | Feu servir una clau amb el rol editor i accés a la col·lecció. |
cards.external_id_taken | POST amb un external_id que ja té una altra entrada. | Feu servir PUT /v1/cards-by-external-id/… per substituir-la. |
cards.managed_by_source | L’entrada pertany a una font. | Canvieu el document a la seva font. |
files.type_mismatch | El nom, el tipus i el contingut del fitxer no concorden. | Envieu el fitxer amb la seva extensió real. |
files.too_large | El fitxer supera el límit de pujada o l’emmagatzematge de l’organització. | Feu servir una pujada per parts o allibereu espai d’emmagatzematge. |
limits.cards | L’organització ha arribat al límit d’entrades del seu pla. | Elimineu les entrades que ja no calguin o canvieu de pla. |
api.metadata_invalid | metadata supera un límit. | Vegeu Metadades. |