Vai al contenuto
Sursa Developers

Sincronizzare il tuo sistema con una fonte personalizzata

Una fonte personalizzata collega un sistema che non ha un connettore integrato: la tua wiki, il tuo strumento di ticketing, un database, un’esportazione da qualsiasi parte. Il tuo codice invia i documenti a Sursa e Sursa li trasforma in schede nella raccolta e nelle cartelle per cui la fonte è configurata, con la stessa ricerca, le stesse risposte, la stessa verifica e gli stessi permessi delle schede di qualsiasi altra fonte.

A differenza della scrittura diretta delle schede, una fonte personalizzata tiene traccia di ciò che hai inviato. Alla fine di una sincronizzazione completa, Sursa archivia ogni documento che non hai inviato, così le eliminazioni nel tuo sistema arrivano in Sursa senza lavoro aggiuntivo.

Configurare la fonte

Un amministratore crea la fonte in Sursa in Sources → New source → Custom source (fonti, nuova fonte, fonte personalizzata) e sceglie:

  • la raccolta e, facoltativamente, una cartella per le sue schede;
  • la modalità delle cartelle: tutte le schede nella cartella scelta, oppure sottocartelle che riproducono il path di ogni documento;
  • i permessi: i permessi della raccolta, oppure “come nella fonte”, dove ogni documento elenca chi può vederlo.

La pagina della fonte ne mostra l’ID; gli esempi usano 42.

Scegliere una chiave

ChiaveInizia conPuò
Chiave della fontekbsrc_Scrivere documenti in questa sola fonte. Nient’altro: non può leggere né cercare. Creala nella pagina della fonte, in API keys (chiavi API della fonte).
Chiave dell’organizzazione con l’ambito import:writekb_Scrivere in qualsiasi fonte personalizzata dell’organizzazione e leggerne lo stato. Per creare una fonte e le sue chiavi serve l’ambito admin.

La chiave della fonte è la scelta più sicura per una singola integrazione, soprattutto se funziona su una piattaforma di terzi. Una chiave dell’organizzazione con import:write è adatta a un servizio che alimenta più fonti.

Entrambe le chiavi si inviano allo stesso modo, e ogni endpoint di invio si trova in /v1/push/sources/{source_id}. Controlla la chiave e lo stato della fonte con GET /v1/push/sources/{source_id}:

curl https://api.sursa.com/v1/push/sources/42 \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY"
{"source_id": 42, "name": "Helpdesk articles", "documents": 1840, "open_sync": null}

Il documento

CampoObbligatorioDescrizione
external_idsìIl tuo ID stabile del documento, fino a 512 caratteri. Inviare di nuovo lo stesso ID sostituisce il documento.
titlesìTitolo della scheda, fino a 500 caratteri. Per un file, per impostazione predefinita il nome del file.
contentsì, a meno che non ci sia un fileFino a 5 MB.
content_typenohtml (predefinito), markdown o text. Dall’HTML vengono rimossi script, stili, moduli e oggetti incorporati.
urlnoLink al documento nel tuo sistema, mostrato sulla scheda.
pathnoCartelle, come array (["Support", "Billing"]) o come stringa ("Support/Billing"), fino a 10 livelli.
permissionsno{"everyone": true}, oppure {"emails": [...], "groups": [...]}. Si usa quando i permessi della fonte sono “come nella fonte”.
tagsnoFino a 50 tag, aggiunti ai tag della fonte.
author_emailnoSe è un utente dell’organizzazione, diventa il responsabile della scheda.
updated_atnoQuando il documento è cambiato nel tuo sistema (RFC 3339).
metadatanoLe tue coppie chiave-valore sulla scheda. Vedi Metadati.
categorynoCategoria della scheda: la chiave di una categoria dell’organizzazione.
verifiers, verify_interval_daysnoChi verifica la scheda (utenti per e-mail e gruppi) e con quale frequenza, in giorni.
upload_idnoIl file del documento da un caricamento in parti, al posto di content.
attachmentsnoFino a 20 altri file del documento, come elenco di upload_id. Ognuno diventa una scheda a sé della fonte.

Invece di content, un singolo documento può portare un file fino a 100 MB in una richiesta multipart/form-data: il file nella parte file, i campi precedenti in JSON nella parte document. I caricamenti in parti per upload_id e attachments si creano con una chiave dell’organizzazione che ha l’ambito import:write e la finalità import_attachment; una chiave della fonte non può crearli.

Due modi di inviare

Gli aggiornamenti diretti sono adatti ai sistemi che ti segnalano ogni modifica, come un webhook del tuo helpdesk o un passaggio in Zapier. Invia un documento quando viene creato o modificato ed eliminalo quando viene rimosso:

RichiestaCosa fa
POST /v1/push/sources/{source_id}/documentsCrea o sostituisce un documento.
POST /v1/push/sources/{source_id}/documents/batchCrea o sostituisce molti documenti in una volta.
DELETE /v1/push/sources/{source_id}/documents/{external_id}Rimuove un documento. Codifica l’ID per URL.

Le modifiche diventano schede entro circa un minuto; più modifiche consecutive vengono elaborate insieme.

Le sincronizzazioni sono adatte alle esportazioni periodiche: invii tutto, o tutto ciò che è cambiato, e Sursa riconcilia. Il resto di questa guida riguarda le sincronizzazioni.

Eseguire una sincronizzazione completa

Una sincronizzazione ha tre passaggi: aprire, inviare, chiudere.

1. Aprire

POST /v1/push/sources/{source_id}/syncs apre una sincronizzazione e ne restituisce il numero:

curl -X POST https://api.sursa.com/v1/push/sources/42/syncs \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY" \
  -H "Idempotency-Key: sync-2026-10-24" \
  -H "Content-Type: application/json" \
  -d '{"type": "initial", "max_minutes": 180}'
{"sync_number": 7, "type": "initial", "status": "open", "opened_at": "2026-10-24T02:00:00Z",
 "expires_at": "2026-10-24T05:00:00Z", "pushed": 0, "removed": 0}
  • type è initial per la prima sincronizzazione della fonte e incremental dopo che una sincronizzazione si è completata. Una sincronizzazione incremental prima di una completata restituisce sources.push_initial_required.
  • Si può aprire una sola sincronizzazione alla volta: una seconda restituisce 409 sources.push_sync_open.
  • Una sincronizzazione resta aperta per max_minutes (60 per impostazione predefinita, fino a 1440). Poi scade: non viene archiviato nulla e il suo numero non è più accettato. Scegli un tempo ben più lungo di quello che richiede la tua esportazione.

2. Inviare i documenti

Invia i documenti in batch di massimo 500, con il numero della sincronizzazione. Il corpo di un batch può arrivare a 50 MiB; i file all’interno di un batch si passano come upload_id.

curl -X POST https://api.sursa.com/v1/push/sources/42/documents/batch \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY" \
  -H "Idempotency-Key: sync-7-batch-1" \
  -H "Content-Type: application/json" \
  -d '{
    "sync_number": 7,
    "documents": [
      {"external_id": "faq-shipping", "title": "Shipping", "content_type": "markdown",
       "content": "# Shipping\n\nWe ship worldwide within 5 days.", "path": ["Support"]},
      {"external_id": "faq-refunds", "title": "Refunds", "content_type": "html",
       "content": "<p>Refunds take 14 days.</p>", "path": ["Support", "Billing"],
       "permissions": {"groups": ["Support"]}, "metadata": {"article_id": "1042"}}
    ]
  }'

La risposta contiene un risultato per ogni documento, nell’ordine in cui li hai inviati:

{
  "results": [
    {"external_id": "faq-shipping", "result": "unchanged", "status": "indexed", "card_id": "8c1d…", "version": "5e0f…"},
    {"external_id": "faq-refunds", "result": "updated", "status": "pending", "card_id": "3f2c…", "version": "a91b…"}
  ]
}
CampoSignificato
resultCosa è successo ora al documento: created, updated, unchanged, deleted, not_found, error oppure skipped (in un batch atomico che non è stato applicato).
statusA che punto è il documento nel percorso verso una scheda: pending, processing (la scheda è scritta ed è in corso di indicizzazione), indexed, failed o removed.
card_idLa scheda del documento, quando esiste.
versionUn hash del contenuto e dei campi. Lo stesso documento inviato di nuovo ha la stessa versione ed è unchanged.
error, reasonPerché il documento non è riuscito. reason è un codice stabile: content_invalid, file_rejected, too_large, limit_reached, index_failed oppure batch_rejected (un altro documento di un batch atomico non è riuscito).

Per impostazione predefinita, ogni documento di un batch viene applicato da solo: un documento errato non blocca gli altri.

I documenti che non sono cambiati dall’ultima sincronizzazione non vanno inviati di nuovo. Confermali per ID con POST /v1/push/sources/{source_id}/syncs/{sync_number}/touch, fino a 1000 ID per richiesta, così la riconciliazione completa li mantiene:

curl -X POST https://api.sursa.com/v1/push/sources/42/syncs/7/touch \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_ids": ["faq-contact", "faq-hours"]}'

3. Chiudere

POST /v1/push/sources/{source_id}/syncs/{sync_number}/close termina la sincronizzazione:

curl -X POST https://api.sursa.com/v1/push/sources/42/syncs/7/close \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "complete"}'
statusEffetto
completeRiconciliazione completa. Ogni documento della fonte che in questa sincronizzazione non è stato né inviato né confermato viene archiviato. Usalo solo quando hai inviato tutto.
complete_incrementalApplica ciò che hai inviato e non archivia nulla.
failedNon archivia nulla e mantiene ciò che è già stato inviato. Aggiungi reason (per esempio API_ERROR) ed error_details per il registro.

Chiudi con failed ogni volta che la tua esportazione si ferma a metà: un complete dopo un’esportazione parziale archivierebbe ogni documento a cui non sei arrivato. Ripetere la stessa chiusura restituisce lo stesso risultato.

Dopo la chiusura, Sursa trasforma i documenti in schede entro circa un minuto. La pagina della fonte mostra ogni sincronizzazione con il numero di documenti inviati e archiviati, e GET /v1/push/sources/{source_id}/syncs/{sync_number} restituisce gli stessi contatori.

Sincronizzazioni incrementali

Tra una sincronizzazione completa e l’altra, invia solo ciò che è cambiato:

  1. Apri con "type": "incremental".
  2. Invia i documenti modificati e metti gli ID di quelli rimossi in deletes (più avanti).
  3. Chiudi con complete_incremental.

Esegui di tanto in tanto una sincronizzazione completa, per esempio ogni settimana, per recuperare ciò che un’esecuzione incrementale ha perso.

Eliminare documenti in un batch

Un batch può rimuovere documenti insieme a quelli che scrive. Elenca i loro ID in deletes:

{
  "sync_number": 8,
  "documents": [{"external_id": "faq-shipping", "title": "Shipping", "content": "…"}],
  "deletes": ["faq-old-returns", "faq-fax"]
}

Ogni ID eliminato riceve una propria voce in results, con result deleted, oppure not_found se la fonte non ha quel documento. Eliminare di nuovo lo stesso ID non ha conseguenze.

Batch atomici

Alcune modifiche hanno senso solo insieme, per esempio un documento e quello che lo sostituisce. Invia "atomic": true e il batch viene applicato per intero o per niente: se un documento qualsiasi non supera i controlli, non viene applicato nulla del batch e la risposta è 422 con il codice sources.push_batch_rejected e il risultato di ogni documento in error.details.results: i documenti che non sono riusciti hanno error, gli altri skipped.

{"sync_number": 8, "atomic": true, "documents": […], "deletes": ["faq-old-returns"]}

Senza atomic, un batch viene applicato documento per documento. Usa i batch atomici per le modifiche correlate e i batch normali per i caricamenti massivi, dove un documento errato non deve bloccare il resto.

Controllare il risultato di ogni documento

La risposta del batch ti dice come è stato scritto ogni documento. La trasformazione in scheda avviene dopo, quindi status può essere ancora pending. Per trovare i documenti di una sincronizzazione che non sono diventati schede:

curl "https://api.sursa.com/v1/push/sources/42/syncs/7/documents?status=failed" \
  -H "Authorization: Bearer $SURSA_SOURCE_KEY"

Ogni voce ha external_id, title, status, card_id, version e reason, e l’elenco si pagina con cursor. status accetta anche pending, processing, indexed e removed.

Puoi anche ricevere una notifica invece di chiedere: gli eventi import.sync_completed (una sincronizzazione è chiusa ed elaborata, con i suoi totali) e import.document_failed (un documento non è diventato una scheda, con il suo reason) arrivano via webhook e nel feed degli eventi.

Nuovi tentativi

  • Invia una Idempotency-Key con ogni POST. Un batch ripetuto con la stessa chiave restituisce il primo risultato.
  • Anche senza la chiave, un documento con lo stesso external_id non diventa mai una seconda scheda: è unchanged o updated.
  • Se il processo si ferma a metà di una sincronizzazione, aprine una nuova dopo che quella vecchia è scaduta, oppure chiudi la vecchia con failed se ne hai ancora il numero, ed esegui di nuovo la sincronizzazione.

Limiti

LimiteValore
Contenuto di un documento5 MB
File in una richiesta con un solo documento100 MB
Documenti per batch500
Corpo della richiesta di un batch50 MiB
ID per richiesta touch1000
Documenti per fonteDipende dal piano: da 100.000
Sincronizzazione aperta60 minuti per impostazione predefinita, fino a 24 ore

Un documento oltre il limite di documenti della fonte non riesce con il motivo limit_reached in un batch; una richiesta con un solo documento risponde 409 con il codice sources.push_too_many_documents. I limiti di frequenza si applicano come a qualsiasi altra richiesta; vedi Limiti di frequenza e quote.

Errori comuni

RispostaCausaCosa fare
401 sources.push_key_invalidLa chiave è errata, revocata o appartiene a un’altra fonte.Controlla la chiave e l’ID della fonte nel percorso.
400 sources.push_document_invalidManca un campo obbligatorio o è superato un limite.Correggi il documento; in un batch normale non riesce solo quel documento.
409 sources.push_sync_openUn’altra sincronizzazione è ancora aperta.Chiudila oppure attendi che scada.
409 sources.push_sync_closedLa sincronizzazione è chiusa o scaduta.Apri una nuova sincronizzazione; per le esportazioni lunghe aumenta max_minutes.
403 sources.feature_disabledLe fonti non fanno parte del piano dell’organizzazione.Contatta l’amministratore.
429Troppe richieste.Attendi il tempo di Retry-After; invia batch più grandi e meno numerosi.