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
pathdi 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
| Chiave | Inizia con | Può |
|---|---|---|
| Chiave della fonte | kbsrc_ | 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:write | kb_ | 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
| Campo | Obbligatorio | Descrizione |
|---|---|---|
external_id | sì | Il tuo ID stabile del documento, fino a 512 caratteri. Inviare di nuovo lo stesso ID sostituisce il documento. |
title | sì | Titolo della scheda, fino a 500 caratteri. Per un file, per impostazione predefinita il nome del file. |
content | sì, a meno che non ci sia un file | Fino a 5 MB. |
content_type | no | html (predefinito), markdown o text. Dall’HTML vengono rimossi script, stili, moduli e oggetti incorporati. |
url | no | Link al documento nel tuo sistema, mostrato sulla scheda. |
path | no | Cartelle, come array (["Support", "Billing"]) o come stringa ("Support/Billing"), fino a 10 livelli. |
permissions | no | {"everyone": true}, oppure {"emails": [...], "groups": [...]}. Si usa quando i permessi della fonte sono “come nella fonte”. |
tags | no | Fino a 50 tag, aggiunti ai tag della fonte. |
author_email | no | Se è un utente dell’organizzazione, diventa il responsabile della scheda. |
updated_at | no | Quando il documento è cambiato nel tuo sistema (RFC 3339). |
metadata | no | Le tue coppie chiave-valore sulla scheda. Vedi Metadati. |
category | no | Categoria della scheda: la chiave di una categoria dell’organizzazione. |
verifiers, verify_interval_days | no | Chi verifica la scheda (utenti per e-mail e gruppi) e con quale frequenza, in giorni. |
upload_id | no | Il file del documento da un caricamento in parti, al posto di content. |
attachments | no | Fino 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:
| Richiesta | Cosa fa |
|---|---|
POST /v1/push/sources/{source_id}/documents | Crea o sostituisce un documento. |
POST /v1/push/sources/{source_id}/documents/batch | Crea 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èinitialper la prima sincronizzazione della fonte eincrementaldopo che una sincronizzazione si è completata. Una sincronizzazioneincrementalprima di una completata restituiscesources.push_initial_required.- Si può aprire una sola sincronizzazione alla volta: una seconda restituisce
409sources.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…"}
]
}
| Campo | Significato |
|---|---|
result | Cosa è successo ora al documento: created, updated, unchanged, deleted, not_found, error oppure skipped (in un batch atomico che non è stato applicato). |
status | A che punto è il documento nel percorso verso una scheda: pending, processing (la scheda è scritta ed è in corso di indicizzazione), indexed, failed o removed. |
card_id | La scheda del documento, quando esiste. |
version | Un hash del contenuto e dei campi. Lo stesso documento inviato di nuovo ha la stessa versione ed è unchanged. |
error, reason | Perché 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"}'status | Effetto |
|---|---|
complete | Riconciliazione completa. Ogni documento della fonte che in questa sincronizzazione non è stato né inviato né confermato viene archiviato. Usalo solo quando hai inviato tutto. |
complete_incremental | Applica ciò che hai inviato e non archivia nulla. |
failed | Non 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:
- Apri con
"type": "incremental". - Invia i documenti modificati e metti gli ID di quelli rimossi in
deletes(più avanti). - 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-Keycon ogniPOST. Un batch ripetuto con la stessa chiave restituisce il primo risultato. - Anche senza la chiave, un documento con lo stesso
external_idnon diventa mai una seconda scheda: èunchangedoupdated. - Se il processo si ferma a metà di una sincronizzazione, aprine una nuova dopo che quella vecchia è scaduta, oppure
chiudi la vecchia con
failedse ne hai ancora il numero, ed esegui di nuovo la sincronizzazione.
Limiti
| Limite | Valore |
|---|---|
| Contenuto di un documento | 5 MB |
| File in una richiesta con un solo documento | 100 MB |
| Documenti per batch | 500 |
| Corpo della richiesta di un batch | 50 MiB |
ID per richiesta touch | 1000 |
| Documenti per fonte | Dipende dal piano: da 100.000 |
| Sincronizzazione aperta | 60 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
| Risposta | Causa | Cosa fare |
|---|---|---|
401 sources.push_key_invalid | La chiave è errata, revocata o appartiene a un’altra fonte. | Controlla la chiave e l’ID della fonte nel percorso. |
400 sources.push_document_invalid | Manca un campo obbligatorio o è superato un limite. | Correggi il documento; in un batch normale non riesce solo quel documento. |
409 sources.push_sync_open | Un’altra sincronizzazione è ancora aperta. | Chiudila oppure attendi che scada. |
409 sources.push_sync_closed | La sincronizzazione è chiusa o scaduta. | Apri una nuova sincronizzazione; per le esportazioni lunghe aumenta max_minutes. |
403 sources.feature_disabled | Le fonti non fanno parte del piano dell’organizzazione. | Contatta l’amministratore. |
429 | Troppe richieste. | Attendi il tempo di Retry-After; invia batch più grandi e meno numerosi. |