Synchronizuj swój system przez własne źródło
Własne źródło łączy system, który nie ma wbudowanego konektora: Twoją wiki, system zgłoszeń, bazę danych, eksport z dowolnego miejsca. Twój kod wysyła dokumenty do Sursy, a Sursa zamienia je w karty w kolekcji i folderach, dla których skonfigurowano źródło, z takim samym wyszukiwaniem, odpowiedziami, weryfikacją i uprawnieniami jak w przypadku kart z każdego innego źródła.
W odróżnieniu od bezpośredniego zapisu kart własne źródło śledzi, co zostało wysłane. Na koniec pełnej synchronizacji Sursa archiwizuje każdy dokument, którego nie wysłano, więc usunięcia w Twoim systemie docierają do Sursy bez dodatkowej pracy.
Skonfiguruj źródło
Administrator tworzy źródło w Sursie w sekcji Sources → New source → Custom source (źródła → nowe źródło → własne źródło) i wybiera:
- kolekcję i opcjonalnie folder dla kart źródła;
- tryb folderów: wszystkie karty w wybranym folderze albo podfoldery odwzorowujące
pathkażdego dokumentu; - uprawnienia: uprawnienia kolekcji albo „jak w źródle”, gdzie każdy dokument wymienia, kto może go widzieć.
Strona źródła pokazuje jego ID; przykłady używają 42.
Wybierz klucz
| Klucz | Zaczyna się od | Może |
|---|---|---|
| Klucz źródła | kbsrc_ | Zapisywać dokumenty w tym jednym źródle. Nic więcej: nie może odczytywać ani wyszukiwać. Utwórz go na stronie źródła w sekcji API keys. |
Klucz organizacji z zakresem import:write | kb_ | Zapisywać dane w dowolnym własnym źródle organizacji i odczytywać jego stan. Utworzenie źródła i jego kluczy wymaga zakresu admin. |
Klucz źródła to najbezpieczniejszy wybór dla pojedynczej integracji, zwłaszcza działającej na platformie zewnętrznej.
Klucz organizacji z import:write pasuje do usługi, która zasila kilka źródeł.
Oba klucze wysyła się w ten sam sposób, a wszystkie operacje push znajdują się pod /v1/push/sources/{source_id}.
Sprawdź klucz i stan źródła za pomocą 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}
Dokument
| Pole | Wymagane | Opis |
|---|---|---|
external_id | tak | Twój stały identyfikator dokumentu, do 512 znaków. Ponowne wysłanie tego samego identyfikatora zastępuje dokument. |
title | tak | Tytuł karty, do 500 znaków. W przypadku pliku domyślnie nazwa pliku. |
content | tak, chyba że jest plik | Do 5 MB. |
content_type | nie | html (domyślnie), markdown lub text. Z HTML usuwane są skrypty, style, formularze i osadzone obiekty. |
url | nie | Link do dokumentu w Twoim systemie, wyświetlany na karcie. |
path | nie | Foldery jako tablica (["Support", "Billing"]) lub ciąg znaków ("Support/Billing"), do 10 poziomów. |
permissions | nie | {"everyone": true} lub {"emails": [...], "groups": [...]}. Używane, gdy uprawnienia źródła są ustawione na „jak w źródle”. |
tags | nie | Do 50 tagów, dodawanych do tagów źródła. |
author_email | nie | Jeśli to użytkownik organizacji, staje się właścicielem karty. |
updated_at | nie | Kiedy dokument zmienił się w Twoim systemie (RFC 3339). |
metadata | nie | Twoje pary klucz–wartość w karcie. Zob. Metadane. |
category | nie | Kategoria karty: klucz jednej z kategorii organizacji. |
verifiers, verify_interval_days | nie | Kto weryfikuje kartę (użytkownicy według adresu e-mail i grupy) i jak często, w dniach. |
upload_id | nie | Plik dokumentu z przesyłania w częściach, zamiast content. |
attachments | nie | Do 20 dodatkowych plików dokumentu jako lista upload_id. Każdy z nich staje się osobną kartą źródła. |
Zamiast content pojedynczy dokument może zawierać plik do 100 MB w żądaniu multipart/form-data: plik w części
file, a powyższe pola jako JSON w części document. Przesyłania w częściach dla upload_id i attachments
tworzy się kluczem organizacji, który ma zakres import:write, z przeznaczeniem import_attachment; klucz źródła
nie może ich tworzyć.
Dwa sposoby wysyłania
Bezpośrednie aktualizacje pasują do systemów, które informują o każdej zmianie, np. webhook z Twojego systemu pomocy technicznej lub krok w Zapier. Wysyłaj dokument, gdy zostanie utworzony lub zmieniony, i usuwaj go, gdy zniknie z Twojego systemu:
| Żądanie | Działanie |
|---|---|
POST /v1/push/sources/{source_id}/documents | Tworzy lub zastępuje jeden dokument. |
POST /v1/push/sources/{source_id}/documents/batch | Tworzy lub zastępuje wiele dokumentów naraz. |
DELETE /v1/push/sources/{source_id}/documents/{external_id} | Usuwa jeden dokument. Zakoduj identyfikator do postaci URL. |
Zmiany stają się kartami w ciągu około minuty; kilka kolejnych zmian jest przetwarzanych razem.
Synchronizacje pasują do regularnych eksportów: wysyłasz wszystko lub wszystko, co się zmieniło, a Sursa uzgadnia stan. Dalsza część przewodnika dotyczy synchronizacji.
Uruchom pełną synchronizację
Synchronizacja ma trzy kroki: otwarcie, wysyłanie, zamknięcie.
1. Otwórz
POST /v1/push/sources/{source_id}/syncs otwiera synchronizację i zwraca jej
numer:
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}
typema wartośćinitialprzy pierwszej synchronizacji źródła iincrementalpo zakończeniu którejkolwiek synchronizacji. Synchronizacjaincrementalprzed pierwszą zakończoną zwracasources.push_initial_required.- Naraz może być otwarta tylko jedna synchronizacja: druga zwraca
409sources.push_sync_open. - Synchronizacja pozostaje otwarta przez
max_minutes(domyślnie 60, maksymalnie 1440). Potem wygasa: nic nie jest archiwizowane, a jej numer przestaje być akceptowany. Wybierz czas wyraźnie dłuższy niż czas trwania eksportu.
2. Wyślij dokumenty
Wysyłaj dokumenty w pakietach do 500 z numerem synchronizacji. Treść pakietu może mieć do 50 MiB; pliki
w pakiecie przekazuje się jako 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"}}
]
}'Odpowiedź zawiera wynik dla każdego dokumentu, w kolejności wysłania:
{
"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…"}
]
}
| Pole | Znaczenie |
|---|---|
result | Co teraz stało się z dokumentem: created, updated, unchanged, deleted, not_found, error lub skipped (w pakiecie atomowym, który nie został zastosowany). |
status | Na jakim etapie drogi do karty jest dokument: pending, processing (karta jest zapisana i trwa jej indeksowanie), indexed, failed lub removed. |
card_id | Karta dokumentu, gdy już istnieje. |
version | Skrót (hash) treści i pól. Ten sam dokument wysłany ponownie ma tę samą wersję i wynik unchanged. |
error, reason | Dlaczego dokument nie został przetworzony. reason to stały kod: content_invalid, file_rejected, too_large, limit_reached, index_failed lub batch_rejected (inny dokument pakietu atomowego nie przeszedł kontroli). |
Domyślnie każdy dokument pakietu jest stosowany osobno: jeden błędny dokument nie zatrzymuje pozostałych.
Dokumentów, które nie zmieniły się od ostatniej synchronizacji, nie trzeba wysyłać ponownie. Potwierdź je według
identyfikatora za pomocą POST /v1/push/sources/{source_id}/syncs/{sync_number}/touch,
do 1000 identyfikatorów na żądanie, aby pełne uzgadnianie je zachowało:
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. Zamknij
POST /v1/push/sources/{source_id}/syncs/{sync_number}/close kończy
synchronizację:
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 | Skutek |
|---|---|
complete | Pełne uzgadnianie. Każdy dokument źródła, który w tej synchronizacji nie został ani wysłany, ani potwierdzony, jest archiwizowany. Używaj tego statusu tylko wtedy, gdy wysłano wszystko. |
complete_incremental | Stosuje to, co wysłano, i niczego nie archiwizuje. |
failed | Niczego nie archiwizuje i zachowuje to, co już wysłano. Dodaj reason (np. API_ERROR) i error_details do dziennika. |
Zamykaj z failed zawsze, gdy eksport zatrzyma się w połowie: complete po częściowym eksporcie zarchiwizowałoby
każdy dokument, do którego eksport nie dotarł. Powtórzenie tego samego zamknięcia zwraca ten sam wynik.
Po zamknięciu Sursa w ciągu około minuty zamienia dokumenty w karty. Strona źródła pokazuje każdą synchronizację
z liczbą wysłanych i zarchiwizowanych dokumentów, a GET /v1/push/sources/{source_id}/syncs/{sync_number}
zwraca te same liczniki.
Synchronizacje przyrostowe
Między pełnymi synchronizacjami wysyłaj tylko to, co się zmieniło:
- Otwórz synchronizację z
"type": "incremental". - Wyślij zmienione dokumenty, a identyfikatory usuniętych umieść w
deletes(poniżej). - Zamknij synchronizację z
complete_incremental.
Od czasu do czasu, np. co tydzień, uruchamiaj pełną synchronizację, aby wyłapać wszystko, co pominęło uruchomienie przyrostowe.
Usuwaj dokumenty w pakiecie
Pakiet może usuwać dokumenty razem z tymi, które zapisuje. Wymień ich identyfikatory w deletes:
{
"sync_number": 8,
"documents": [{"external_id": "faq-shipping", "title": "Shipping", "content": "…"}],
"deletes": ["faq-old-returns", "faq-fax"]
}
Każdy usunięty identyfikator otrzymuje własny wpis w results, z result równym deleted lub not_found, jeśli
źródło nie ma takiego dokumentu. Ponowne usunięcie tego samego identyfikatora jest nieszkodliwe.
Pakiety atomowe
Niektóre zmiany mają sens tylko razem, np. dokument i ten, który go zastępuje. Wyślij "atomic": true, a pakiet
zostanie zastosowany w całości albo wcale: jeśli którykolwiek dokument nie przejdzie kontroli, nic z pakietu nie
zostanie zastosowane, a odpowiedź to 422 z kodem sources.push_batch_rejected i wynikiem każdego dokumentu
w error.details.results: dokumenty, które nie przeszły kontroli, mają error, a pozostałe skipped.
{"sync_number": 8, "atomic": true, "documents": […], "deletes": ["faq-old-returns"]}
Bez atomic pakiet jest stosowany dokument po dokumencie. Używaj pakietów atomowych do powiązanych zmian, a zwykłych
pakietów do ładowań masowych, w których jeden błędny dokument nie powinien wstrzymywać reszty.
Sprawdź wynik każdego dokumentu
Odpowiedź pakietu informuje, jak każdy dokument został zapisany. Zamiana w kartę następuje później, więc status
może jeszcze mieć wartość pending. Aby znaleźć dokumenty synchronizacji, które nie stały się kartami:
curl "https://api.sursa.com/v1/push/sources/42/syncs/7/documents?status=failed" \
-H "Authorization: Bearer $SURSA_SOURCE_KEY"Każdy wpis ma external_id, title, status, card_id, version i reason, a lista jest stronicowana za pomocą
cursor. status przyjmuje też pending, processing, indexed i removed.
Możesz też otrzymywać powiadomienia, zamiast pytać: zdarzenia import.sync_completed (synchronizacja została zamknięta
i przetworzona, z jej sumami) i import.document_failed (dokument nie stał się kartą, z jego reason) przychodzą
przez webhook i w kanale zdarzeń.
Ponowienia
- Wysyłaj
Idempotency-Keyz każdym żądaniemPOST. Powtórzony pakiet z tym samym kluczem zwraca pierwszy wynik. - Nawet bez klucza dokument z tym samym
external_idnigdy nie stanie się drugą kartą: ma wynikunchangedlubupdated. - Jeśli proces zatrzyma się w trakcie synchronizacji, otwórz nową po wygaśnięciu starej albo zamknij starą z
failed, jeśli nadal znasz jej numer, i uruchom synchronizację ponownie.
Limity
| Limit | Wartość |
|---|---|
| Treść jednego dokumentu | 5 MB |
| Plik w żądaniu z jednym dokumentem | 100 MB |
| Dokumenty w pakiecie | 500 |
| Treść żądania z pakietem | 50 MiB |
Identyfikatory w żądaniu touch | 1000 |
| Dokumenty w źródle | Zależnie od planu: od 100 000 |
| Otwarta synchronizacja | Domyślnie 60 minut, maksymalnie 24 godziny |
Dokument przekraczający limit dokumentów źródła kończy się w pakiecie błędem z przyczyną limit_reached; na żądanie
z pojedynczym dokumentem API odpowiada 409 z kodem
sources.push_too_many_documents. Limity częstotliwości obowiązują tak
samo jak przy każdym innym żądaniu; zob. Limity częstotliwości i przydziały.
Typowe błędy
| Odpowiedź | Przyczyna | Co zrobić |
|---|---|---|
401 sources.push_key_invalid | Klucz jest błędny, unieważniony lub należy do innego źródła. | Sprawdź klucz i ID źródła w ścieżce. |
400 sources.push_document_invalid | Brakuje wymaganego pola lub przekroczono limit. | Popraw dokument; w zwykłym pakiecie błędem kończy się tylko ten dokument. |
409 sources.push_sync_open | Inna synchronizacja jest wciąż otwarta. | Zamknij ją lub poczekaj, aż wygaśnie. |
409 sources.push_sync_closed | Synchronizacja jest zamknięta lub wygasła. | Otwórz nową synchronizację; przy długich eksportach zwiększ max_minutes. |
403 sources.feature_disabled | Źródła nie są częścią planu organizacji. | Skontaktuj się z administratorem. |
429 | Zbyt wiele żądań. | Odczekaj czas z Retry-After; wysyłaj mniej pakietów, ale większych. |