Zum Inhalt springen
Sursa Developers

Ihr System mit einer benutzerdefinierten Quelle synchronisieren

Eine benutzerdefinierte Quelle bindet ein System an, für das es keinen eingebauten Connector gibt: Ihr Wiki, Ihr Ticketsystem, eine Datenbank, einen Export von irgendwoher. Ihr Code sendet Dokumente an Sursa, und Sursa macht daraus Karten in der Sammlung und den Ordnern, für die die Quelle eingerichtet ist – mit derselben Suche, denselben Antworten, derselben Prüfung und denselben Berechtigungen wie bei Karten aus jeder anderen Quelle.

Anders als beim direkten Schreiben von Karten merkt sich eine benutzerdefinierte Quelle, was Sie gesendet haben. Am Ende einer vollständigen Synchronisierung archiviert Sursa jedes Dokument, das Sie nicht gesendet haben. So kommen Löschungen in Ihrem System ohne Zusatzaufwand bei Sursa an.

Quelle einrichten

Die Quelle legen Administratorinnen und Administratoren in Sursa unter Sources → New source → Custom source an und wählen dabei:

  • die Sammlung und optional einen Ordner für ihre Karten;
  • den Ordnermodus: alle Karten im gewählten Ordner oder Unterordner, die den path jedes Dokuments abbilden;
  • die Berechtigungen: die Berechtigungen der Sammlung oder „wie in der Quelle“, wobei jedes Dokument angibt, wer es sehen darf.

Die Seite der Quelle zeigt ihre ID; die Beispiele verwenden 42.

Schlüssel wählen

SchlüsselBeginnt mitDarf
Quellschlüsselkbsrc_Dokumente in genau diese Quelle schreiben. Sonst nichts: Er kann weder lesen noch suchen. Erstellen Sie ihn auf der Seite der Quelle unter API keys.
Schlüssel der Organisation mit dem Scope import:writekb_In jede benutzerdefinierte Quelle der Organisation schreiben und ihren Zustand lesen. Das Anlegen einer Quelle und ihrer Schlüssel erfordert den Scope admin.

Der Quellschlüssel ist die sicherste Wahl für eine einzelne Integration, besonders für eine, die auf einer Plattform eines Drittanbieters läuft. Ein Schlüssel der Organisation mit import:write eignet sich für einen Dienst, der mehrere Quellen befüllt.

Beide Schlüssel werden auf dieselbe Weise gesendet, und jeder Push-Endpunkt liegt unter /v1/push/sources/{source_id}. Prüfen Sie den Schlüssel und den Zustand der Quelle mit 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}

Das Dokument

FeldPflichtBeschreibung
external_idjaIhre stabile ID des Dokuments, bis zu 512 Zeichen. Wird dieselbe ID erneut gesendet, wird das Dokument ersetzt.
titlejaTitel der Karte, bis zu 500 Zeichen. Bei einer Datei standardmäßig der Dateiname.
contentja, außer bei einer DateiBis zu 5 MB.
content_typeneinhtml (Standard), markdown oder text. HTML wird von Skripten, Styles, Formularen und eingebetteten Objekten bereinigt.
urlneinLink auf das Dokument in Ihrem System, wird auf der Karte angezeigt.
pathneinOrdner als Array (["Support", "Billing"]) oder als Zeichenkette ("Support/Billing"), bis zu 10 Ebenen.
permissionsnein{"everyone": true} oder {"emails": [...], "groups": [...]}. Wird verwendet, wenn die Berechtigungen der Quelle auf „wie in der Quelle“ stehen.
tagsneinBis zu 50 Tags, zusätzlich zu den Tags der Quelle.
author_emailneinIst dies ein Benutzer der Organisation, wird diese Person für die Karte verantwortlich.
updated_atneinWann sich das Dokument in Ihrem System geändert hat (RFC 3339).
metadataneinIhre Schlüssel-Wert-Paare an der Karte. Siehe Metadaten.
categoryneinKategorie der Karte: der Schlüssel einer Kategorie der Organisation.
verifiers, verify_interval_daysneinWer die Karte prüft (Benutzer per E-Mail und Gruppen) und wie oft, in Tagen.
upload_idneinDie Datei des Dokuments aus einem Upload in Teilen, statt content.
attachmentsneinBis zu 20 weitere Dateien des Dokuments als Liste von upload_id. Jede davon wird zu einer eigenen Karte der Quelle.

Statt content kann ein einzelnes Dokument in einer Anfrage mit multipart/form-data eine Datei von bis zu 100 MB mitbringen: die Datei im Teil file, die obigen Felder als JSON im Teil document. Uploads in Teilen für upload_id und attachments werden mit einem Schlüssel der Organisation erstellt, der den Scope import:write hat, und mit dem Zweck import_attachment; ein Quellschlüssel kann sie nicht erstellen.

Zwei Arten zu senden

Direkte Aktualisierungen eignen sich für Systeme, die Sie über jede Änderung informieren, etwa ein Webhook aus Ihrem Helpdesk oder ein Schritt in Zapier. Senden Sie ein Dokument, wenn es erstellt oder geändert wird, und löschen Sie es, wenn es entfernt wird:

AnfrageBewirkt
POST /v1/push/sources/{source_id}/documentsErstellt oder ersetzt ein Dokument.
POST /v1/push/sources/{source_id}/documents/batchErstellt oder ersetzt viele Dokumente auf einmal.
DELETE /v1/push/sources/{source_id}/documents/{external_id}Entfernt ein Dokument. Kodieren Sie die ID für die URL.

Änderungen werden innerhalb von etwa einer Minute zu Karten; mehrere aufeinanderfolgende Änderungen werden gemeinsam verarbeitet.

Synchronisierungen eignen sich für regelmäßige Exporte: Sie senden alles oder alles Geänderte, und Sursa gleicht ab. Der Rest dieser Anleitung behandelt Synchronisierungen.

Vollständige Synchronisierung ausführen

Eine Synchronisierung hat drei Schritte: öffnen, senden, schließen.

1. Öffnen

POST /v1/push/sources/{source_id}/syncs öffnet eine Synchronisierung und gibt ihre Nummer zurück:

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 ist initial für die erste Synchronisierung der Quelle und incremental, sobald eine Synchronisierung abgeschlossen ist. Eine incremental-Synchronisierung vor der ersten abgeschlossenen ergibt sources.push_initial_required.
  • Es kann immer nur eine Synchronisierung offen sein: Eine zweite ergibt 409 sources.push_sync_open.
  • Eine Synchronisierung bleibt max_minutes lang offen (standardmäßig 60, bis zu 1440). Danach läuft sie ab: Nichts wird archiviert, und ihre Nummer wird nicht mehr akzeptiert. Wählen Sie eine Zeit, die deutlich länger ist, als Ihr Export dauert.

2. Dokumente senden

Senden Sie die Dokumente in Batches von bis zu 500 zusammen mit der Synchronisierungsnummer. Der Body eines Batches umfasst bis zu 50 MiB; Dateien innerhalb eines Batches werden als upload_id übergeben.

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"}}
    ]
  }'

Die Antwort enthält für jedes Dokument ein Ergebnis, in der Reihenfolge, in der Sie sie gesendet haben:

{
  "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…"}
  ]
}
FeldBedeutung
resultWas jetzt mit dem Dokument geschehen ist: created, updated, unchanged, deleted, not_found, error oder skipped (in einem atomaren Batch, der nicht angewendet wurde).
statusWo sich das Dokument auf dem Weg zur Karte befindet: pending, processing (die Karte ist geschrieben und wird indexiert), indexed, failed oder removed.
card_idDie Karte des Dokuments, sobald sie existiert.
versionEin Hash des Inhalts und der Felder. Dasselbe Dokument, erneut gesendet, hat dieselbe Version und ist unchanged.
error, reasonWarum das Dokument fehlgeschlagen ist. reason ist ein stabiler Code: content_invalid, file_rejected, too_large, limit_reached, index_failed oder batch_rejected (ein anderes Dokument eines atomaren Batches ist fehlgeschlagen).

Standardmäßig wird jedes Dokument eines Batches für sich angewendet: Ein fehlerhaftes Dokument hält die anderen nicht auf.

Dokumente, die sich seit der letzten Synchronisierung nicht geändert haben, müssen Sie nicht erneut senden. Bestätigen Sie sie über ihre ID mit POST /v1/push/sources/{source_id}/syncs/{sync_number}/touch, bis zu 1000 IDs pro Anfrage, damit der vollständige Abgleich sie behält:

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. Schließen

POST /v1/push/sources/{source_id}/syncs/{sync_number}/close beendet die Synchronisierung:

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"}'
statusWirkung
completeVollständiger Abgleich. Jedes Dokument der Quelle, das in dieser Synchronisierung weder gesendet noch bestätigt wurde, wird archiviert. Verwenden Sie dies nur, wenn Sie alles gesendet haben.
complete_incrementalÜbernimmt, was Sie gesendet haben, und archiviert nichts.
failedArchiviert nichts und behält, was bereits gesendet wurde. Fügen Sie reason (zum Beispiel API_ERROR) und error_details für das Protokoll hinzu.

Schließen Sie mit failed, wann immer Ihr Export auf halbem Weg abbricht: Ein complete nach einem unvollständigen Export würde jedes Dokument archivieren, zu dem Sie nicht mehr gekommen sind. Dasselbe Schließen erneut auszuführen ergibt dasselbe Ergebnis.

Nach dem Schließen macht Sursa innerhalb von etwa einer Minute Karten aus den Dokumenten. Die Seite der Quelle zeigt jede Synchronisierung mit der Anzahl der gesendeten und archivierten Dokumente, und GET /v1/push/sources/{source_id}/syncs/{sync_number} gibt dieselben Zähler zurück.

Inkrementelle Synchronisierungen

Senden Sie zwischen vollständigen Synchronisierungen nur, was sich geändert hat:

  1. Öffnen Sie mit "type": "incremental".
  2. Senden Sie die geänderten Dokumente und tragen Sie die IDs entfernter Dokumente in deletes ein (siehe unten).
  3. Schließen Sie mit complete_incremental.

Führen Sie von Zeit zu Zeit eine vollständige Synchronisierung aus, zum Beispiel wöchentlich, um alles zu erfassen, was ein inkrementeller Lauf verpasst hat.

Dokumente in einem Batch löschen

Ein Batch kann zusammen mit den Dokumenten, die er schreibt, auch Dokumente entfernen. Führen Sie deren IDs in deletes auf:

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

Jede gelöschte ID erhält einen eigenen Eintrag in results, mit result gleich deleted oder not_found, wenn die Quelle kein solches Dokument hat. Dieselbe ID erneut zu löschen schadet nicht.

Atomare Batches

Manche Änderungen ergeben nur zusammen einen Sinn, zum Beispiel ein Dokument und das Dokument, das es ersetzt. Senden Sie "atomic": true, dann wird der Batch ganz oder gar nicht angewendet: Besteht ein Dokument seine Prüfungen nicht, wird nichts aus dem Batch übernommen, und die Antwort ist 422 mit dem Code sources.push_batch_rejected und dem Ergebnis jedes Dokuments in error.details.results: Die fehlgeschlagenen Dokumente haben error, die anderen skipped.

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

Ohne atomic wird ein Batch Dokument für Dokument angewendet. Verwenden Sie atomare Batches für zusammengehörige Änderungen und normale Batches für Massenladungen, bei denen ein fehlerhaftes Dokument den Rest nicht aufhalten soll.

Ergebnis jedes Dokuments prüfen

Die Antwort auf einen Batch sagt Ihnen, wie jedes Dokument geschrieben wurde. Die Umwandlung in eine Karte geschieht danach, daher kann status noch pending sein. So finden Sie die Dokumente einer Synchronisierung, die nicht zu Karten geworden sind:

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

Jeder Eintrag hat external_id, title, status, card_id, version und reason, und die Liste wird mit cursor paginiert. status akzeptiert auch pending, processing, indexed und removed.

Sie können sich auch benachrichtigen lassen, statt nachzufragen: Die Ereignisse import.sync_completed (eine Synchronisierung ist geschlossen und verarbeitet, mit ihren Summen) und import.document_failed (ein Dokument ist nicht zur Karte geworden, mit seinem reason) kommen per Webhook und im Ereignis-Feed an.

Wiederholungen

  • Senden Sie bei jedem POST einen Idempotency-Key. Ein wiederholter Batch mit demselben Schlüssel gibt das erste Ergebnis zurück.
  • Auch ohne den Schlüssel wird ein Dokument mit derselben external_id nie zu einer zweiten Karte: Es ist unchanged oder updated.
  • Bricht der Prozess mitten in einer Synchronisierung ab, öffnen Sie eine neue, nachdem die alte abgelaufen ist, oder schließen Sie die alte mit failed, wenn Sie ihre Nummer noch haben, und führen Sie die Synchronisierung erneut aus.

Limits

LimitWert
Inhalt eines Dokuments5 MB
Datei in einer Anfrage mit einem einzelnen Dokument100 MB
Dokumente pro Batch500
Body einer Batch-Anfrage50 MiB
IDs pro touch-Anfrage1000
Dokumente pro QuelleAbhängig vom Tarif: ab 100.000
Offene SynchronisierungStandardmäßig 60 Minuten, bis zu 24 Stunden

Ein Dokument über dem Dokumentenlimit der Quelle schlägt in einem Batch mit dem Grund limit_reached fehl; eine Anfrage mit einem einzelnen Dokument ergibt 409 mit dem Code sources.push_too_many_documents. Ratenlimits gelten wie für jede andere Anfrage; siehe Ratenlimits und Kontingente.

Häufige Fehler

AntwortUrsacheWas zu tun ist
401 sources.push_key_invalidDer Schlüssel ist falsch, widerrufen oder gehört zu einer anderen Quelle.Prüfen Sie den Schlüssel und die Quell-ID im Pfad.
400 sources.push_document_invalidEin Pflichtfeld fehlt oder ein Limit ist überschritten.Korrigieren Sie das Dokument; in einem normalen Batch schlägt nur dieses Dokument fehl.
409 sources.push_sync_openEine andere Synchronisierung ist noch offen.Schließen Sie sie oder warten Sie, bis sie abläuft.
409 sources.push_sync_closedDie Synchronisierung ist geschlossen oder abgelaufen.Öffnen Sie eine neue Synchronisierung; erhöhen Sie max_minutes für lange Exporte.
403 sources.feature_disabledQuellen sind nicht Teil des Tarifs der Organisation.Wenden Sie sich an die Administration.
429Zu viele Anfragen.Warten Sie die Zeit aus Retry-After ab; senden Sie weniger, dafür größere Batches.