📦 Product Data Webhook API

Custom Integration Documentation

📋 Overview

This API lets 3rd party systems push product catalog data into our system. When products are created, updated, or removed in your shop, send them to our webhook endpoint and we build the chatbot's product catalog and knowledge library from them — the same way our native Shoptet / Shopify integrations do.

⚠️ Important: This endpoint supports two event types: product:update (create or update products) and product:delete (remove products). Any other event type returns a 400 Bad Request.

🚀 Getting Started

1. Get Your Webhook URL

Contact your system administrator to obtain your unique webhook URL. It shares the same webhook-key as your order-data channel. It looks like:

https://admin.jarabot.com/webhooks/product_update/{your-webhook-key}

2. Webhook Endpoint

POST /webhooks/product_update/{webhook_key}

📝 Request Format

Headers

Header Value Required
Content-Type application/json Yes
Authorization Token {your-api-key} If enabled

The Authorization header is required only when API-key validation is enabled for your connection. We strongly recommend enabling it for product push.

🟢 Event: product:update

The payload is an array of product objects. Each object is the full current state of one product, keyed by its sku — we replace any previously stored data for that SKU (no field-level merge). The example below mixes one fully-described product and one minimal (required-fields-only) product.

Request Body

{
  "webhook": {
    "event": "product:update",
    "payload": [
      {
        "sku": "NIKE-PEGASUS-40",
        "external_id": "12345",
        "title": "Nike Air Zoom Pegasus 40",
        "url": "https://shop.example.cz/nike-pegasus-40",
        "price": 3499.00,
        "currency": "CZK",
        "margin": 800.00,
        "availability": 0,
        "availability_description": "In stock",
        "visible": true,
        "short_description": "Versatile running shoe for daily training.",
        "description": "<p>The Pegasus 40 brings snappier response and a lighter upper.</p>",
        "image_url": "https://shop.example.cz/img/pegasus40.jpg",
        "thumbnail_url": "https://shop.example.cz/img/pegasus40-thumb.jpg",
        "brand": "Nike",
        "categories": [
          { "title": "Shoes",         "url": "https://shop.example.cz/shoes" },
          { "title": "Sports shoes",   "url": "https://shop.example.cz/sports-shoes" },
          { "title": "Running shoes",  "url": "https://shop.example.cz/running-shoes" }
        ],
        "traits": {
          "color":   ["black"],
          "surface": ["road"]
        },
        "variants": [
          { "sku": "NIKE-PEGASUS-40-42", "availability": 0, "params": { "size": "42" } },
          { "sku": "NIKE-PEGASUS-40-43", "availability": 5, "params": { "size": "43" } }
        ],
        "gifts": ["Free sports socks"],
        "ean": "0195869884532",
        "last_modified": "2026-06-30T10:00:00Z"
      },
      {
        "sku": "GEL-NIMBUS-26",
        "title": "Asics Gel-Nimbus 26",
        "url": "https://shop.example.cz/gel-nimbus-26",
        "price": 4290,
        "currency": "CZK",
        "availability": 0
      }
    ]
  }
}

📊 Product Object Structure

Required fields

The minimum viable product is these six fields. It will index and be findable, but answers are thin without a description, image, and traits — send the recommended fields too.

Field Type Required Description
sku String Yes Stable unique product identifier. Used as the upsert/dedup key.
title String Yes Product name.
url String Yes Product page URL (http/https).
price Number Yes Final customer price including VAT, in currency. No conversion is applied.
currency String Yes ISO-4217 3-letter code (e.g. "CZK", "EUR").
availability Integer Yes Days until available: 0 = in stock now, -1 = unavailable / out of stock, N = available in N days. Out-of-stock products are excluded from the catalog.

Recommended fields

Field Type Required Description
external_id String No Your stable product id if different from sku. Defaults to sku.
description String No Long description. HTML allowed (stripped for catalog, kept for the knowledge library). Primary content for AI answers.
short_description String No Teaser / summary.
image_url String No Main product image URL. Used in product cards.
thumbnail_url String No Thumbnail image URL. Defaults to image_url.
brand String No Manufacturer / brand name. Searchable and facetable.
categories Array<Object> No Category breadcrumb, broad → specific. See Categories below.
availability_description String No Human-readable stock text shown to the customer (e.g. "In stock", "Ships in 3 days").
traits Object No Structured filterable attributes. See Traits below.
variants Array<Object> No Per-variant rows (size/color combos). See Variants below.

Optional fields

Field Type Required Description
visible Boolean No Default true. false stores the product but excludes it from the catalog and library.
last_modified String No When the product last changed on your side (ISO-8601). Defaults to the push time.
margin Number No Price minus purchase price, in currency. Internal only, never shown to customers. Defaults to 0.
purchase_price Number No Alternative to margin: we compute margin = price − purchase_price.
ean / gtin String No Barcode. Stored for future matching; not indexed yet.
gifts Array<String> No Free items bundled with the purchase. Shown as a "Free gifts" block.

Categories (breadcrumb)

An ordered array, broadest first and the most specific (leaf) last. The leaf is treated as the product's primary category.

"categories": [
  { "title": "Shoes",        "url": "https://shop.example.cz/shoes" },
  { "title": "Sports shoes", "url": "https://shop.example.cz/sports-shoes" },
  { "title": "Running shoes","url": "https://shop.example.cz/running-shoes" }
]
Field Type Required Description
categories[].title String Yes Category name for this breadcrumb level.
categories[].url String No Link to this category's page.

Traits (filterable attributes)

An object mapping attribute name to an array of string values — always an array, even for a single value. Used for faceted filtering ("red shoes size 42"). Only send values that are actually buyable.

"traits": {
  "color": ["red"],
  "size":  ["42", "43", "44"],
  "material": ["leather"]
}

Variants

Optional per-variant rows. A buyable variant's params are folded into the product's filterable traits, so a variant-only attribute (e.g. shoe size) becomes searchable even when it isn't a top-level trait.

"variants": [
  { "sku": "SHOE-42", "availability": 0, "params": { "size": "42" } },
  { "sku": "SHOE-43", "availability": 5, "params": { "size": "43" } }
]
Field Type Required Description
variants[].sku String Yes Variant SKU (distinct from the parent product sku).
variants[].availability Integer No Same convention as product availability. Decides whether the variant is buyable. Defaults to the product's availability.
variants[].params Object No Attribute name → single value for this variant (e.g. { "size": "42" }).

🔴 Event: product:delete

The payload is an array of SKUs to remove. Deleted products disappear from the catalog and knowledge library.

{
  "webhook": {
    "event": "product:delete",
    "payload": ["GEL-NIMBUS-26", "NIKE-PEGASUS-40"]
  }
}

📤 Response Codes

200 OK: The batch was accepted and queued for processing. Per-product validation happens asynchronously; invalid products are skipped and logged while valid ones in the same batch still persist.
400 Bad Request:
401 Unauthorized: Missing or invalid Authorization token (when API-key validation is enabled)
404 Not Found: Invalid webhook key

🔄 Update, Create & Delete Behavior

Note: sku is the unique identifier. Keep it consistent across all webhook calls for the same product. Products are language-agnostic — one pushed product feeds every language the bot is configured for.

💡 Example Implementations

cURL — update products

curl -X POST https://admin.jarabot.com/webhooks/product_update/your-webhook-key \
  -H "Content-Type: application/json" \
  -H "Authorization: Token your-api-key" \
  -d '{
    "webhook": {
      "event": "product:update",
      "payload": [
        {
          "sku": "PROD-001",
          "title": "Example Product",
          "url": "https://shop.example.com/prod-001",
          "price": 599.00,
          "currency": "CZK",
          "availability": 0
        }
      ]
    }
  }'

cURL — delete products

curl -X POST https://admin.jarabot.com/webhooks/product_update/your-webhook-key \
  -H "Content-Type: application/json" \
  -H "Authorization: Token your-api-key" \
  -d '{
    "webhook": {
      "event": "product:delete",
      "payload": ["PROD-001", "PROD-002"]
    }
  }'

Last updated: