Синхронізуйте свою систему через власне джерело
Власне джерело підключає систему, для якої немає вбудованого конектора: вашу wiki, систему заявок, базу даних, експорт звідки завгодно. Ваш код надсилає документи до Sursa, а Sursa перетворює їх на картки в колекції та папках, на які налаштовано джерело, — з тими самими пошуком, відповідями, верифікацією та дозволами, що й у карток із будь-якого іншого джерела.
На відміну від прямого запису карток, власне джерело відстежує, що ви вже надіслали. Наприкінці повної синхронізації Sursa архівує кожен документ, якого ви не надіслали, тож видалення у вашій системі доходять до Sursa без додаткової роботи.
Налаштуйте джерело
Адміністратор створює джерело в Sursa в розділі Sources → New source → Custom source (джерела → нове джерело → власне джерело) і вибирає:
- колекцію і, за потреби, папку для його карток;
- режим папок: усі картки у вибраній папці або вкладені папки, що відтворюють
pathкожного документа; - дозволи: дозволи колекції або «як у джерелі», коли кожен документ перелічує, хто може його бачити.
Сторінка джерела показує його ID; у прикладах це 42.
Виберіть ключ
| Ключ | Починається з | Що може |
|---|---|---|
| Ключ джерела | kbsrc_ | Записувати документи в це одне джерело. І нічого більше: він не може читати чи шукати. Створіть його на сторінці джерела в розділі API keys (ключі API джерела). |
Ключ організації з областю доступу import:write | kb_ | Записувати в будь-яке власне джерело організації та читати його стан. Для створення джерела та його ключів потрібна область доступу admin. |
Ключ джерела — найбезпечніший вибір для окремої інтеграції, особливо такої, що працює на сторонній платформі. Ключ
організації з import:write підходить для сервісу, який наповнює кілька джерел.
Обидва ключі надсилають однаково, а всі push-операції розміщено в /v1/push/sources/{source_id}. Перевірте ключ і
стан джерела через 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}
Документ
| Поле | Обов’язкове | Опис |
|---|---|---|
external_id | так | Ваш стабільний ідентифікатор документа, до 512 символів. Повторне надсилання з тим самим ідентифікатором замінює документ. |
title | так | Заголовок картки, до 500 символів. Для файлу типово — назва файлу. |
content | так, якщо немає файлу | До 5 МБ. |
content_type | ні | html (типово), markdown або text. З HTML вилучаються скрипти, стилі, форми й вбудовані об’єкти. |
url | ні | Посилання на документ у вашій системі, показане на картці. |
path | ні | Папки — масивом (["Support", "Billing"]) або рядком ("Support/Billing"), до 10 рівнів. |
permissions | ні | {"everyone": true} або {"emails": [...], "groups": [...]}. Використовується, коли дозволи джерела — «як у джерелі». |
tags | ні | До 50 тегів, що додаються до тегів джерела. |
author_email | ні | Якщо це користувач організації, він стає відповідальним за картку. |
updated_at | ні | Коли документ змінився у вашій системі (RFC 3339). |
metadata | ні | Ваші пари «ключ — значення» в картці. Див. Метадані. |
category | ні | Категорія картки: ключ однієї з категорій організації. |
verifiers, verify_interval_days | ні | Хто верифікує картку (користувачі за електронною поштою та групи) і як часто, у днях. |
upload_id | ні | Файл документа із завантаження частинами, замість content. |
attachments | ні | До 20 додаткових файлів документа — список upload_id. Кожен файл стає окремою карткою джерела. |
Замість content окремий документ може містити файл до 100 МБ у запиті multipart/form-data: файл — у частині
file, поля, наведені вище, — у форматі JSON у частині document. Завантаження частинами для upload_id і
attachments створюють ключем організації з областю доступу import:write і метою import_attachment; ключ джерела
створити їх не може.
Два способи надсилання
Прямі оновлення підходять для систем, які повідомляють про кожну зміну, як-от вебхук від вашої служби підтримки або крок у Zapier. Надсилайте документ, коли його створено чи змінено, і видаляйте, коли його прибрано:
| Запит | Що робить |
|---|---|
POST /v1/push/sources/{source_id}/documents | Створює або замінює один документ. |
POST /v1/push/sources/{source_id}/documents/batch | Створює або замінює багато документів одразу. |
DELETE /v1/push/sources/{source_id}/documents/{external_id} | Видаляє один документ. Закодуйте ідентифікатор для URL. |
Зміни стають картками приблизно за хвилину; кілька змін поспіль обробляються разом.
Синхронізації підходять для регулярних експортів: ви надсилаєте все або все, що змінилося, а Sursa звіряє. Решта цього посібника — про синхронізації.
Запустіть повну синхронізацію
Синхронізація має три кроки: відкрити, надіслати, закрити.
1. Відкрийте
POST /v1/push/sources/{source_id}/syncs відкриває синхронізацію й повертає її
номер:
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для першої синхронізації джерела таincrementalпісля того, як якась синхронізація завершилася. Синхронізаціяincrementalдо першої завершеної повертаєsources.push_initial_required.- Одночасно може бути відкрита лише одна синхронізація: друга повертає
409sources.push_sync_open. - Синхронізація лишається відкритою
max_minutesхвилин (типово 60, щонайбільше 1440). Після цього строк її дії спливає: нічого не архівується, а її номер більше не приймається. Вибирайте час із добрим запасом понад тривалість вашого експорту.
2. Надішліть документи
Надсилайте документи пакетами до 500 разом із номером синхронізації. Тіло пакета — до 50 МіБ; файли всередині
пакета передаються як 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"}}
]
}'Відповідь містить результат для кожного документа в тому порядку, в якому ви їх надіслали:
{
"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…"}
]
}
| Поле | Значення |
|---|---|
result | Що зараз сталося з документом: created, updated, unchanged, deleted, not_found, error або skipped (в атомарному пакеті, який не застосовано). |
status | На якому етапі шляху до картки перебуває документ: pending, processing (картку записано, і вона індексується), indexed, failed або removed. |
card_id | Картка документа, щойно вона з’явиться. |
version | Хеш вмісту й полів. Той самий документ, надісланий повторно, має ту саму версію й отримує unchanged. |
error, reason | Чому документ не вдалося обробити. reason — стабільний код: content_invalid, file_rejected, too_large, limit_reached, index_failed або batch_rejected (інший документ атомарного пакета не пройшов перевірки). |
Типово кожен документ пакета застосовується окремо: один хибний документ не зупиняє інших.
Документи, що не змінилися з останньої синхронізації, не треба надсилати знову. Підтвердьте їх за ідентифікатором
через POST /v1/push/sources/{source_id}/syncs/{sync_number}/touch, до
1000 ідентифікаторів на запит, щоб повна звірка їх зберегла:
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. Закрийте
POST /v1/push/sources/{source_id}/syncs/{sync_number}/close завершує
синхронізацію:
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 | Дія |
|---|---|
complete | Повна звірка. Кожен документ джерела, який у цій синхронізації не надіслали й не підтвердили, архівується. Використовуйте цей статус, лише коли надіслали все. |
complete_incremental | Застосовує надіслане й нічого не архівує. |
failed | Нічого не архівує й зберігає вже надіслане. Додайте reason (наприклад, API_ERROR) та error_details для журналу. |
Закривайте зі статусом failed щоразу, коли ваш експорт зупиняється на півдорозі: complete після часткового
експорту архівував би кожен документ, до якого ви не дійшли. Повторне таке саме закриття повертає той самий
результат.
Після закриття Sursa перетворює документи на картки приблизно за хвилину. Сторінка джерела показує кожну
синхронізацію з кількістю надісланих та архівованих документів, а
GET /v1/push/sources/{source_id}/syncs/{sync_number} повертає ті самі
лічильники.
Інкрементні синхронізації
Між повними синхронізаціями надсилайте лише те, що змінилося:
- Відкрийте синхронізацію з
"type": "incremental". - Надішліть змінені документи, а ідентифікатори видалених додайте в
deletes(див. нижче). - Закрийте зі статусом
complete_incremental.
Час від часу, наприклад щотижня, запускайте повну синхронізацію, щоб підхопити все, що пропустив інкрементний запуск.
Видаляйте документи в пакеті
Пакет може видаляти документи разом із тими, які він записує. Перелічіть їхні ідентифікатори в deletes:
{
"sync_number": 8,
"documents": [{"external_id": "faq-shipping", "title": "Shipping", "content": "…"}],
"deletes": ["faq-old-returns", "faq-fax"]
}
Кожен видалений ідентифікатор отримує власний запис у results із result, що дорівнює deleted, або not_found,
якщо в джерелі немає такого документа. Повторне видалення того самого ідентифікатора нічим не шкодить.
Атомарні пакети
Деякі зміни мають сенс лише разом, наприклад документ і той, що його замінює. Надішліть "atomic": true, і пакет
буде застосовано повністю або не застосовано зовсім: якщо будь-який документ не пройде перевірки, з пакета не
застосовується нічого, а відповідь — 422 з кодом sources.push_batch_rejected і результатом кожного документа
в error.details.results: документи, що не пройшли перевірки, мають error, решта — skipped.
{"sync_number": 8, "atomic": true, "documents": […], "deletes": ["faq-old-returns"]}
Без atomic пакет застосовується документ за документом. Використовуйте атомарні пакети для пов’язаних змін, а
звичайні — для масових завантажень, де один хибний документ не має затримувати решту.
Перевірте результат кожного документа
Відповідь на пакет повідомляє, як було записано кожен документ. Перетворення на картку відбувається пізніше, тож
status може ще бути pending. Щоб знайти документи синхронізації, які не стали картками:
curl "https://api.sursa.com/v1/push/sources/42/syncs/7/documents?status=failed" \
-H "Authorization: Bearer $SURSA_SOURCE_KEY"Кожен запис має external_id, title, status, card_id, version і reason, а список розбито на сторінки
через cursor. status також приймає pending, processing, indexed і removed.
Можна не запитувати, а отримувати сповіщення: події import.sync_completed (синхронізацію закрито й оброблено, з
підсумками) та import.document_failed (документ не став карткою, з його reason) надходять через
вебхук і в стрічці подій.
Повтори
- Надсилайте
Idempotency-Keyз кожнимPOST. Повторний пакет із тим самим ключем повертає перший результат. - Навіть без ключа документ із тим самим
external_idніколи не стане другою карткою: він отримаєunchangedабоupdated. - Якщо процес зупинився посеред синхронізації, відкрийте нову після того, як строк дії старої спливе, або закрийте
стару зі статусом
failed, якщо ще маєте її номер, і запустіть синхронізацію знову.
Ліміти
| Ліміт | Значення |
|---|---|
| Вміст одного документа | 5 МБ |
| Файл у запиті з одним документом | 100 МБ |
| Документів у пакеті | 500 |
| Тіло запиту з пакетом | 50 МіБ |
Ідентифікаторів у запиті touch | 1000 |
| Документів у джерелі | Залежить від тарифу: від 100 000 |
| Відкрита синхронізація | Типово 60 хвилин, щонайбільше 24 години |
Документ понад ліміт документів джерела завершується в пакеті помилкою з причиною limit_reached; на запит з одним
документом API відповідає 409 з кодом sources.push_too_many_documents.
Ліміти частоти діють так само, як для будь-якого іншого запиту; див. Ліміти частоти та квоти.
Поширені помилки
| Відповідь | Причина | Що робити |
|---|---|---|
401 sources.push_key_invalid | Ключ неправильний, відкликаний або належить іншому джерелу. | Перевірте ключ та ID джерела в шляху. |
400 sources.push_document_invalid | Бракує обов’язкового поля або перевищено ліміт. | Виправте документ; у звичайному пакеті помилкою завершується лише цей документ. |
409 sources.push_sync_open | Інша синхронізація ще відкрита. | Закрийте її або дочекайтеся, поки сплине строк її дії. |
409 sources.push_sync_closed | Синхронізацію закрито, або строк її дії сплив. | Відкрийте нову синхронізацію; для довгих експортів збільште max_minutes. |
403 sources.feature_disabled | Джерела не входять до тарифу організації. | Зверніться до адміністратора. |
429 | Забагато запитів. | Зачекайте Retry-After; надсилайте менше пакетів більшого розміру. |