Guides
Products and catalogue import
Add products one at a time or import a CSV or Shopify export. How SKUs, prices and availability work.
Products are the facts the AI quotes: names, prices, stock, sizes. You can add them one at a time with POST /products, or load a whole catalogue from a CSV or Shopify export with POST /products/import. Both paths run the same code, so an imported product is identical to one added by hand.
Every product is also turned into a knowledge document and indexed, so it becomes answerable a few seconds after you save it. You do not need a second call.
Add or update a product
curl -X POST https://api.getengageai.app/products \
-H "Authorization: Bearer $ENGAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sku": "BOOT-TRL-9",
"name": "Trailhead Mid GTX Boot",
"description": "Waterproof mid-cut hiking boot with a Gore-Tex membrane.",
"category": "Footwear",
"brand": "Acme",
"priceAmount": 13500,
"priceCurrency": "GBP",
"availability": "IN_STOCK",
"stockQuantity": 30,
"attributes": { "sizes": "UK 4-13", "weight": "640 g" },
"tags": ["hiking", "waterproof"],
"url": "https://acme.example/products/trailhead-mid"
}'Only name is required. The fields the AI reads most are description and attributes, so put the details customers ask about there.
| Field | Notes |
|---|---|
sku | Your identifier, unique within your organization. Up to 128 characters. |
name | Required. Up to 512 characters. |
description | Free text, up to 20,000 characters. This is what the AI reads and quotes. |
priceAmount, priceCurrency | Minor units and an ISO 4217 code: 13500 + GBP is £135.00. |
availability | IN_STOCK (default), OUT_OF_STOCK, PREORDER or DISCONTINUED. Controls what the AI may say about getting hold of the product. |
stockQuantity | A whole number, 0 or more. |
attributes | Any key-value facts: sizes, materials, dimensions. All of them are shown to the AI. |
tags | Up to 50, each up to 64 characters. |
How a product is matched
POST /products creates or updates. Which one depends on what you send:
skuyou already have → updates that product. Replaying your whole feed every night is safe, and unchanged products are not re-indexed.idfrom an earlier response → updates that product. Use this to change a product's SKU.- Neither, or a new
sku→ creates a product.
No SKU? One is derived from the name, so Enamel Mug, large becomes enamel-mug-large. Sending the same name again updates instead of duplicating. The catch: the name becomes the identity. Two different products with the same name need real SKUs, and renaming a product without a SKU creates a new one.
Read and delete
# A page of products (see cursor pagination)
curl "https://api.getengageai.app/products?limit=50" -H "Authorization: Bearer $ENGAGE_API_KEY"
# One product
curl https://api.getengageai.app/products/$PRODUCT_ID -H "Authorization: Bearer $ENGAGE_API_KEY"
# Delete. The AI stops using it immediately; past conversations stay readable.
curl -X DELETE https://api.getengageai.app/products/$PRODUCT_ID -H "Authorization: Bearer $ENGAGE_API_KEY"Import a CSV file
Send the file as multipart/form-data in a field named file. Always run a dry run first: it validates every row and writes nothing.
curl -X POST "https://api.getengageai.app/products/import?dryRun=true" \
-H "Authorization: Bearer $ENGAGE_API_KEY" \
-F "file=@catalogue.csv"{
"dryRun": true,
"total": 4,
"imported": 3,
"failed": 1,
"failures": [{ "line": 4, "sku": "BAD-01", "message": "name is required" }],
"truncated": false,
"ignoredColumns": ["Colour"]
}If the report looks right, send the same request without dryRun.
lineis the line in the file, counting the header, so line 4 is the third product.failed > 0is a partial success. Rows are independent. Fix the listed rows and upload the whole file again; it updates rather than duplicates.ignoredColumnslists headers that matched nothing. A misspelledPrixecolumn shows up here.failuresis capped at 100 entries, withtruncated: truewhen there were more.failedis always the true count.
An import only adds and updates. It never deletes products missing from the file, and rows already written stay written if a later row fails.
Limits
| Limit | Value |
|---|---|
| File size | 5 MB (413 above it) |
| Rows | 5,000 per request |
| Format | CSV only. Excel and Word files are rejected with a message telling the person to save as CSV. |
| Time | About 3.5 ms per row, so 5,000 rows take around 18 seconds. The request stays open until it finishes, so set your HTTP timeout accordingly. |
Columns
Columns are matched by name, ignoring case, spaces and punctuation, and their order does not matter. Only a name column is required.
| Field | Accepted headers |
|---|---|
| SKU | sku, code, productCode, itemCode, itemNumber, variantSku |
| Name (required) | name, title, productName, productTitle |
| Description | description, details, body, bodyHtml, longDescription |
| Category | category, productType, type, department |
| Brand | brand, vendor, manufacturer, make |
| Price, as written | price, unitPrice, sellingPrice, retailPrice, variantPrice |
| Price, minor units | priceAmount, priceMinor, priceCents, pricePence |
| Currency | currency, priceCurrency, currencyCode |
| Availability | availability, stockStatus, availabilityStatus, inStock |
| Stock | stock, stockQuantity, quantity, qty, inventory, onHand |
| Tags | tags, labels, keywords |
| URL | url, link, productUrl, productLink |
A minimal file:
SKU,Product Name,Description,Price,Currency,Qty,Stock Status,Tags
TENT-RIDGE-2P,Ridgeline 2P Tent,"A two-person, three-season tent. 2.1 kg packed.",135.00,GBP,24,in stock,camping;tent
BOOT-TRAIL-42,Trailhead Mid GTX Boot,"Waterproof mid-height hiking boot. Sizes 38-47.",129.99,GBP,8,in stock,footwear;hikingHow values are read
- Prices are read the way people write them:
13.50,£1,350.00,1,350.00. Symbols and thousands separators are removed and the text is converted without floating point. The currency's own minor unit is used, so1000inJPYstays ¥1000. - A price without a currency column is an error. The import will not guess a currency.
- Availability is matched loosely:
in stock,availableoryes→IN_STOCK;sold out,oosorno→OUT_OF_STOCK;pre-order,backorderorcoming soon→PREORDER;discontinued,retiredorarchived→DISCONTINUED. Anything else fails that row. Blank meansIN_STOCK. - Tags split on
;,|or,. Use;, since a comma also separates columns. - Quoted fields keep their commas, line breaks and doubled quotes. Excel's byte-order mark is removed.
Shopify exports
Upload the file from Shopify's Products → Export → CSV as it is. The format is detected from its headers and the report says "format": "shopify".
curl -X POST "https://api.getengageai.app/products/import?currency=GBP&dryRun=true" \
-H "Authorization: Bearer $ENGAGE_API_KEY" \
-F "file=@products_export.csv"- Pass
currency. A Shopify export has no currency column. Without it, every priced row fails. - One product per
Handle. Variant and image rows are merged, sototalcounts products, not lines. - Stock is summed across variants, and the price is the first variant's.
Body (HTML)becomes plain text, andarchivedproducts becomeDISCONTINUED.- The SKU is the first variant's SKU, or the
Handleif there is none. Re-exporting and re-uploading updates the same products.
Errors
| Status | Example message |
|---|---|
413 | File too large |
422 | No file was uploaded. Send it as multipart/form-data under the field name 'file'. |
422 | This looks like a zipped Office file (.xlsx, .docx, .ods), and only CSV can be read. … |
422 | No product name column found. Expected one of: … Found: <your headers> |
422 | The file has 5001 rows, and 5000 is the most that can be imported in one request. |
These messages are written for the person who uploaded the file, so you can show them as they are.