Skip to content
FloeeAPI

API reference · Catalogue

Create or update products

POST/api/v1/catalogue/productsScope catalogue:sync

Batch upsert from your store, keyed on your own product id. At most 200 products per request, 100 variants per product.

Request

curlshell
curl -X POST "https://icebot.icebergaisolutions.com/api/v1/catalogue/products" \
  -H "Authorization: Bearer $ICEBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"source":"woocommerce","products":[{"external_id":"101","name":"Nasi lemak ayam goreng","price":12.9,"sku":"NL-AYAM","stock":40,"category":"Mains"},{"external_id":"102","name":"Teh tarik","price":3.5,"variants":[{"external_id":"102-R","name":"Regular","price":3.5,"stock":null},{"external_id":"102-L","name":"Large","price":4.5,"stock":null}]}]}'

Body

FieldTypeDescription
sourceapi | woocommerce | shopifyWhere the data came from. Default api.
products[].external_id (required)string | numberYour store's product id. Unique per request.
products[].name (required)stringUp to 300 characters.
products[].pricenumberRinggit, non-negative. Only MYR is supported.
products[].stockinteger | null12 = twelve in stock, 0 = sold out, null = not tracked (sell without limit), absent = leave unchanged.
products[].description, category, sku, image_url, is_activevariousOptional. is_active defaults to true.
products[].variants[]arrayEach { external_id, name, sku?, price?, is_active?, stock? }. Absent = variants untouched; [] = the product has none now.
Example bodyjson
{
  "source": "woocommerce",
  "products": [
    {
      "external_id": "101",
      "name": "Nasi lemak ayam goreng",
      "price": 12.9,
      "sku": "NL-AYAM",
      "stock": 40,
      "category": "Mains"
    },
    {
      "external_id": "102",
      "name": "Teh tarik",
      "price": 3.5,
      "variants": [
        {
          "external_id": "102-R",
          "name": "Regular",
          "price": 3.5,
          "stock": null
        },
        {
          "external_id": "102-L",
          "name": "Large",
          "price": 4.5,
          "stock": null
        }
      ]
    }
  ]
}

Responses

200

Per-item results, even when some failed, so you can retry exactly those.

200 responsejson
{
  "data": [
    {
      "external_id": "101",
      "status": "created",
      "id": "0a7d3e21-5c44-4b8e-9f10-6e2d8c9b1a37"
    },
    {
      "external_id": "102",
      "status": "updated",
      "id": "1b8e4f32-6d55-4c9f-8a21-7f3e9d0c2b48"
    }
  ],
  "created": 1,
  "updated": 1,
  "failed": 0
}

Errors

Every endpoint can also return 401 (missing, unknown or revoked key), 403 (origin not allowed, or the key lacks catalogue:sync) and 429 (rate limited). See Errors.

StatuserrorWhen
400invalid bodyThe batch is malformed; nothing was written. details lists every problem with its index.

Source of truth: /api/v1/catalogue/products in apps/dashboard/app/api/v1/catalogue/products/route.ts.