ÚvodPlatformaCeníkOtázkyNápovědaKontakt Kivea FlexiKivea PohodaKivea účetnictvíKivea fakturace Vyzkoušet zdarma

Co je to?

Poznámka pro administrátory: Toto je systém, který informuje vaše ostatní aplikace o každé změně ve vašem e-shopu. Je to jako „notifikační služba“, která udržuje váš sklad, účetnictví a marketingové nástroje dokonale synchronizované s vašimi nejnovějšími daty.

Pro koho je to určeno? Administrátoři by si měli přečíst tento článek, aby pochopili různé způsoby, jakými mohou jejich systémy zůstat aktualizované (např. aktualizace v reálném čase vs. pravidelné aktualizace). Budete se muset se svým vývojářem rozhodnout, která metoda nejlépe vyhovuje vašim obchodním potřebám – například, potřebuje váš sklad vědět o prodeji okamžitě, nebo stačí jednou za hodinu?

Klíčové výhody pro e-shop:

  • Přesnost v reálném čase: Použijte „Webhooks“ k aktualizaci vašich ostatních systémů během několika sekund po změně, čímž zajistíte, že vaše skladové zásoby budou vždy správné.
  • Nikdy nezmeškáte aktualizaci: „Changes API“ funguje jako digitální záznam, který zajišťuje, že i když váš jiný systém přejde do režimu offline, může „dohnat“ každou jednotlivou změnu, kterou zmeškal.
  • Automatická synchronizace smazání: Zajistěte, aby při smazání produktu nebo kategorie na jednom místě došlo k automatickému odstranění všude jinde, čímž se zabrání „zastaralým“ produktům na vašem webu.
  • Přizpůsobená oznámení: Nastavte chytrá pravidla, abyste byli upozorněni pouze na změny, které jsou důležité (např. „informujte mou marketingovou aplikaci pouze tehdy, když cena produktu klesne“).

Přehled

{productName} nabízí tři metody pro detekci a sledování změn ve vašich datech. Každá metoda má jiné možnosti a je vhodná pro konkrétní případy použití.

Výběr správné metody

  • updatedAt — Jednoduché pravidelné synchronizace bez sledování smazání
  • Changes API — Kompletní historie změn s dotazováním
  • Webhooks — Oznámení v reálném čase s automatickým doručením

Porovnání metod

Porovnejte tři metody detekce změn a vyberte tu nejvhodnější pro váš případ použití

card: updatedAt
**Výhody**
- Jednoduchá implementace
- Nízká režie – používá standardní filtry dotazů
- Vhodné pro pravidelné synchronizace (hodinové, denní)

**Omezení**
- Nedetekuje smazání
- Vyžaduje dotazování
- Může zmeškat rychlé změny, pokud je interval dotazování příliš dlouhý

**Nejlepší pro:** Jednoduché integrace, kde jsou smazání vzácná nebo nekritická
card: Changes API
**Výhody**
- Zaznamenává všechny operace (vytvoření, aktualizace, smazání)
- Sledování verzí se sekvenčními ID
- Spolehlivé – nezmešká žádné změny
- Může sledovat více entit

**Omezení**
- Vyžaduje dotazování
- Je třeba udržovat ID poslední verze
- Zpoždění na základě intervalu dotazování

**Nejlepší pro:** Robustní integrace vyžadující kompletní historii změn a sledování smazání
card: Webhooks
**Výhody**
- Oznámení v reálném čase (do 5 sekund)
- Není vyžadováno dotazování
- Dávkové doručení (až 100 změn)
- Vestavěný mechanismus opakování
- Podporuje filtrování

**Omezení**
- Vyžaduje veřejně přístupný koncový bod
- Musí zvládat spolehlivost webhooků
- Složitější nastavení

**Nejlepší pro:** Integrace v reálném čase vyžadující okamžitou akci na změny dat

Metoda 1: Použití updatedAt [badge:Simple|info]

Sledování změn pomocí pole časového razítka updatedAt dostupného u všech entit

**Důležité omezení:**
Metoda `updatedAt` nedetekuje smazání. Pokud potřebujete sledovat smazané záznamy, použijte místo toho Changes API nebo Webhooks.

Dotazování produktů aktualizovaných od poslední synchronizace

Načíst všechny produkty, které byly upraveny po určitém časovém razítku

GET /c/{companyId}/products?filter=updatedAt > '2025-11-14T10:00:00Z'&limit=100

// Response
{
    "data": [
        {
            "id": "prod-123",
            "name": "Updated Product",
            "price": 99.99,
            "updatedAt": "2025-11-14T10:15:30Z"
        }
        // ... more products
    ]
}

Sledování času poslední synchronizace (správná metoda)

Uložte časové razítko z posledního načteného záznamu, abyste nezmeškali změny

// Initialize with a timestamp from your last sync
// For first sync, use a timestamp in the past or null
let lastSyncTime = '2025-01-01T00:00:00Z';

// On each sync
const url = `/c/{companyId}/products?filter=${encodeURIComponent(
    `updatedAt > '${lastSyncTime}'`
)}&limit=100&sort=updatedAt`;

const response = await fetch(url);
const { data } = await response.json();

if (data.length > 0) {
    // Process the changed products
    data.forEach(product => {
        console.log('Updated:', product.id, product.updatedAt);
    });
    
    // ✅ CORRECT: Use updatedAt from the last record
    lastSyncTime = data[data.length - 1].updatedAt;
    
    // ❌ WRONG: Never use new Date().toISOString()
    // This can miss changes due to:
    // - Time between query and new Date() call
    // - Clock skew between client and server
}
⚠️ Kritické: Synchronizace času

**Nikdy nepoužívejte `new Date().toISOString()` pro lastSyncTime!**

Tento přístup má dva kritické problémy:

1. **Závodní podmínka:** Změny mohou nastat mezi načítáním dat a voláním `new Date()`, což způsobí, že tyto změny zmeškáte při další synchronizaci.
2. **Rozdíl v čase:** Hodiny klienta a serveru nemusí být synchronizovány. Pokud jsou hodiny klienta napřed, zmeškáte změny. Pokud jsou pozadu, získáte duplicitní data.

✅ Vždy používejte hodnotu `updatedAt` z posledního záznamu vráceného serverem.

Metoda 2: Použití Changes API [badge:Complete|success]

Sledování všech změn včetně smazání pomocí protokolu změn se sledováním verzí

Klíčové výhody
- Zaznamenává operace vytvoření, aktualizace a smazání
- Sekvenční ID verzí pro spolehlivé sledování
- Dotazování více entit v jednom požadavku
- Žádná ztráta dat ani při dlouhých intervalech dotazování

Získat nedávné změny pro produkty

Načíst všechny změny (včetně smazání) pro produkty se sledováním verzí

GET /c/{companyId}/changes?filter=entity = 'products' and id > 100&limit=100

// Response
{
    "data": [
        {
            "id": 101,  // version number
            "entity": "products",
            "rowId": "prod-123",
            "operation": "update",
            "changeSetId": null,
            "createdAt": "2025-11-14T10:15:30Z"
        },
        {
            "id": 102,
            "entity": "products",
            "rowId": "prod-456",
            "operation": "delete",
            "changeSetId": null,
            "createdAt": "2025-11-14T10:16:45Z"
        }
    ]
}

Dotazovat se na změny se sledováním verzí

Průběžně dotazovat na nové změny pomocí poslední známé ID verze

// Store the last processed version
let lastVersionId = 0;

async function pollForChanges() {
    const filter = encodeURIComponent(
        `entity = 'products' and id > ${lastVersionId}`
    );
    
    const response = await fetch(
        `/c/{companyId}/changes?filter=${filter}&limit=100&sort=id`
    );
    const { data } = await response.json();
    
    if (data.length > 0) {
        // Process changes
        for (const change of data) {
            console.log(
                `Change #${change.id}: ${change.operation} on ${change.rowId}`
            );
            
            if (change.operation === 'delete') {
                // Handle deletion
                console.log('Product deleted:', change.rowId);
            } else {
                // Fetch the updated product
                const product = await fetch(
                    `/c/{companyId}/products/${change.rowId}`
                ).then(r => r.json());
                console.log('Product updated:', product);
            }
        }
        
        // Update last version ID
        lastVersionId = data[data.length - 1].id;
    }
}

// Poll every 30 seconds
setInterval(pollForChanges, 30000);

Získat změny pro více entit

Monitorovat změny napříč různými typy entit

const filter = encodeURIComponent(
    `(entity = 'products' OR entity = 'categories') and id > ${lastVersionId}`
);

const response = await fetch(
    `/c/{companyId}/changes?filter=${filter}&limit=100&sort=id`
);
const { data } = await response.json();

// Group changes by entity
const changesByEntity = data.reduce((acc, change) => {
    if (!acc[change.entity]) acc[change.entity] = [];
    acc[change.entity].push(change);
    return acc;
}, {});

console.log('Products changed:', changesByEntity.products?.length || 0);
console.log('Categories changed:', changesByEntity.categories?.length || 0);

Metoda 3: Použití Webhooks [badge:Real-time|warning]

Přijímat automatická oznámení do 5 sekund od jakékoli změny dat

**Funkce v reálném čase**
- Oznámení doručena do 5 sekund od změn
- Dávkové doručení (až 100 změn na jeden webhook)
- Filtrovat podle typu entity (konkrétní entita nebo všechny entity)
- Filtrovat podle podmínek řádků (např. "price > 100")
- Filtrovat podle změněných sloupců (např. ["price", "status"])
- Automatické opakování s exponenciálním zpožděním

Registrace webhooku pro produkty

Dostávejte automatická oznámení při změně produktů

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": "products",
    "url": "https://your-api.com/webhooks/products",
    "action": "webhook"
}

// Your webhook endpoint will receive:
{
    "hookId": "hook-123",
    "tenantId": "tenant-789",
    "organisationId": "{companyId}",
    "changeSetId": null,
    "changes": [
        {
            "id": "change-001",
            "entity": "products",
            "operation": "update",
            "rowId": "prod-123",
            "changeSetId": null
        }
    ],
    "timestamp": "2025-11-14T10:30:00.000Z"
}

Příklad obslužné rutiny webhooku

Zpracování příchozích oznámení webhooku

// Express.js webhook handler
app.post('/webhooks/products', async (req, res) => {
    const { changes } = req.body;
    
    for (const change of changes) {
        console.log(
            `Webhook: ${change.operation} on ${change.rowId}`
        );
        
        if (change.operation === 'delete') {
            // Handle product deletion
            await deleteProductInMySystem(change.rowId);
        } else {
            // Fetch and process the updated product
            const product = await fetch(
                `https://api.productsync.com/c/{companyId}/products/${change.rowId}`,
                {
                    headers: {
                        'Authorization': 'Bearer YOUR_API_KEY'
                    }
                }
            ).then(r => r.json());
            
            await updateProductInMySystem(product);
        }
    }
    
    // Always respond with 200 to acknowledge receipt
    res.status(200).json({ received: true });
});

Webhook pro konkrétní entitu

Omezte oznámení na jeden typ entity

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": "products",
    "url": "https://your-api.com/webhooks/products",
    "action": "webhook"
}

// Only products changes will trigger this webhook
// Changes to categories, units, etc. will be ignored

Webhook pro všechny entity

Sledujte všechny změny entit v jednom webhooku

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": null,
    "url": "https://your-api.com/webhooks/all-changes",
    "action": "webhook"
}

// This webhook will receive notifications for ALL entity types
// Products, categories, units, customers, orders, etc.

Webhook s filtrem podmínek řádků

Dostávejte oznámení pouze tehdy, když řádky odpovídají konkrétním podmínkám

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": "products",
    "url": "https://your-api.com/webhooks/expensive-products",
    "action": "webhook",
    "filter": "price > 100 AND status = 'active'"
}

// You will only receive webhooks when:
// - The entity is 'products'
// - AND the product price is greater than 100
// - AND the product status is 'active'

Webhook s filtrem sloupců

Spustí se pouze při změně konkrétních sloupců

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": "products",
    "url": "https://your-api.com/webhooks/product-pricing",
    "action": "webhook",
    "columns": ["price", "discount", "tax"]
}

// Webhook only triggers when price, discount, or tax changes
// Changes to name, description, etc. will be ignored

Webhook s kombinovanými filtry

Kombinujte entitu, podmínky řádků a filtry sloupců

POST /c/{companyId}/hooks
Content-Type: application/json

{
    "entity": "products",
    "url": "https://your-api.com/webhooks/premium-product-pricing",
    "action": "webhook",
    "filter": "price > 100",
    "columns": ["price", "status"]
}

// Triple filtering:
// 1. Only 'products' entity
// 2. Only when price > 100
// 3. Only when price or status columns change
** Možnosti filtrování webhooku**

**1. Filtrování entit**

Nastavte `entity` pro omezení oznámení na konkrétní typ entity (např. „produkty“, „kategorie“). Použijte `null` pro příjem oznámení pro všechny entity.

**2. Filtrování podle podmínek řádků**

Použijte `filter` s klauzulemi `WHERE` podobnými SQL pro spuštění webhooků pouze tehdy, když řádky odpovídají konkrétním podmínkám (např. „price > 100 AND status = 'active'“).

**3. Filtrování změn sloupců**

Zadejte pole `columns` pro spuštění pouze tehdy, když se změnily konkrétní sloupce. Ideální pro sledování aktualizací cen, změn stavu atd.

**4. Kombinované filtrování**

Kombinujte všechny tři filtry pro přesnou kontrolu: typ entity + podmínky řádků + změny sloupců. Tím se minimalizují zbytečné volání webhooků a zpracování.

Poznámka: Kompletní dokumentaci k webhookům, včetně logiky opakování, možností filtrování a příkladů datové části, naleznete v [navigate:webhooks.md|Dokumentaci k webhookům].


Doporučené postupy

Kdy použít updatedAt

  • Jednoduché integrace s pravidelnými synchronizacemi (hodinové, denní)
  • Když jsou odstranění zpracovávána samostatně nebo nejsou potřeba
  • Nízkofrekvenční aktualizace dat
  • Rychlé prototypy a MVP

Kdy použít Changes API

  • Potřeba sledovat všechny operace včetně odstranění
  • Vytváření kompletního systému synchronizace dat
  • Udržování záznamu o změnách (audit trail)
  • Když není k dispozici infrastruktura webhooků
  • Dávkové zpracování změn

Kdy použít webhooks

  • Potřeba aktualizací dat v reálném čase nebo téměř v reálném čase
  • Spouštění okamžitých akcí při změnách dat
  • Automatické udržování externích systémů v synchronizaci
  • Když můžete udržovat veřejně přístupný koncový bod
  • Vysokofrekvenční změny dat vyžadující rychlou odezvu
**Hybridní přístup:**
Zvažte použití webhooků pro aktualizace v reálném čase a Changes API jako záložní řešení pro zachycení všech zmeškaných změn během výpadků nebo selhání webhooků. To poskytuje to nejlepší z obou světů: aktualizace v reálném čase se zaručenou úplností.