Розділи документації API
Документація API/Запити/Синхронізація

Синхронізація

Три інструменти для двобічної синхронізації без дублів: ваш ключ запису (external_id), вибірка змін за updated_at і список видалених записів.

external_id: ваш ключ у записі Silium

Контакти, контрагенти, ліди, угоди, замовлення й рахунки мають поле external_id (рядок до 64 символів), тобто id запису у вашій системі: номер замовлення на сайті, код контрагента в 1С, id ліда з форми. Воно унікальне в межах сутності.

Створення з вашим ключем

POST /api/v1/order
{ "name": "Замовлення з сайту №1001", "external_id": "site-1001", "contact_id": 42, ... }

Пошук за ключем

GET /api/v1/order?filter[external_id;eq]=site-1001

Ключ уже зайнятий: 409 з id власника

{
  "error": {
    "code": "conflict",
    "message": "external_id уже використано іншим записом",
    "existing_id": 85,
    "deleted": false
  }
}

Схема «створи або онови»

  1. POST з external_id. 201 означає, що запис створено.
  2. 409 conflict означає, що запис уже є. Тоді надішліть PUT /{сутність}/{existing_id} з тими самими даними.
  • ●Порожній рядок зберігається як null, тому записи без ключа не конфліктують між собою.
  • ●Кілька одночасних POST з однаковим ключем: рівно один отримає 201, решта отримають той самий 409 з existing_id.
  • ●Видалений запис тримає свій ключ (у 409 буде "deleted": true), тому повторно цей ключ не використати: створюйте запис з іншим (наприклад, із суфіксом).
  • ●Копіювання запису в інтерфейсі (клон, розділення замовлення) ключ не переносить.
  • ●У товарів external_id теж є (до 100 символів), але не унікальний. Ідентифікуйте товари за sku (артикул унікальний) або перевіряйте наявність фільтром.

Зміни з моменту останньої синхронізації

Кожен запис має updated_at. Забирайте лише змінене, сортуючи за ним:

GET /api/v1/contact
  ?filter[updated_at;gte]=2026-09-30 12:00:00
  &order=updated_at
  &per-page=100
  &page=1
  • ●Запам’ятовуйте найбільший updated_at з отриманих і наступного разу стартуйте з нього (gte, не gt: записи з тією самою секундою не загубляться; повтори відсійте за id).
  • ●Беріть невелике перекриття (1–2 хвилини), щоб не пропустити транзакції, що завершились із запізненням.
  • ●Час у фільтрі задається в часовому поясі кабінету.

Видалені записи

Видалений запис зникає зі списків, і за updated_at його не побачити. Тому є окремий маршрут:

GET/{сутність}/deleted?since=…
id і час видалення записів, видалених з моменту since. Сутності: contact, account, lead, opportunity, task, product, order, invoice.
право: <сутність>.view2 очк.
GET /api/v1/order/deleted?since=2026-09-30T12:00:00+03:00

{
  "items": [ { "id": 77, "deleted_at": "2026-09-30T13:05:11+03:00" } ],
  "total": 1, "page": 1, "per_page": 20
}
ПараметрОпис
sinceОбов’язковий. RFC 3339 (2026-09-30T12:00:00+03:00), 2026-09-30 12:00:00 або 2026-09-30.
page, per-pageЯк у звичайних списках.
Платежі видаляються остаточно й сюди не потрапляють. Для них звіряйте список id із вашим за потрібний період.

Повний цикл

Python: інкрементальна синхронізація контактів

import requests

API = "https://<компанія>.silium.io/api/v1"
H = {"Authorization": f"Bearer {TOKEN}"}

def pages(path, params):
    page = 1
    while True:
        r = requests.get(f"{API}{path}", headers=H, params={**params, "page": page, "per-page": 100})
        r.raise_for_status()
        data = r.json()
        yield from data["items"]
        if page * data["per_page"] >= data["total"]:
            return
        page += 1

since = load_checkpoint()          # напр. "2026-09-30 12:00:00"
for c in pages("/contact", {"filter[updated_at;gte]": since, "order": "updated_at"}):
    upsert_local(c)
for d in pages("/contact/deleted", {"since": since}):
    delete_local(d["id"])
save_checkpoint(now_minus_2_minutes())

Записуйте в Silium через external_id і Idempotency-Key: повтор після обриву зв’язку не створить дубль.