Custom Integration Documentation
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.
product:update (create or update products) and product:delete (remove products). Any other event type returns a 400 Bad Request.
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}
/webhooks/product_update/{webhook_key}
| 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.
product:updateThe 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.
{
"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
}
]
}
}
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. |
| 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. |
| 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. |
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. |
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"]
}
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" }). |
product:deleteThe 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"]
}
}
payloadproduct:update and product:delete are supported)Authorization token (when API-key validation is enabled)
product:delete with the SKU to take it out of the catalog and library.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.
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 -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: