Guide

Bulk catalogue import from a ZIP archive.

For suppliers of decors, floors and tiles and for furniture retailers: how to prepare the archive, what product.json and catalog.csv are, how the dry run and the import work, what the log lines mean and how to roll an import back. Technical field specification: IMPORT.md.

1. Principle

  • You run the import in the supplier portal (app.furniconf.com/supplier/) in the Bulk import (ZIP) card – it has separate buttons Import decors · Import furniture (3D objects) · Import floors · Import floor tiles · Import wall tiles, each with a description and an archive example. The button determines the item kind, kind in the files is optional (a mismatch fails the item). Floor tiles are offered only on the floor, wall tiles only on walls.
  • The item code (SKU) is the key. The same code in your account = an update of the existing item (price, name, image, model), not a duplicate. An image or model missing from the archive stays as it was.
  • Always start with a Dry run (no writes): you get a line for every item and nothing is saved. Then Import.
  • New decor items go to approval; changing an approved item sends it back to approval. Furniture retailers on a trial invitation are approved automatically.
  • Limits: 5,000 items and 5 GB per archive; image up to 4 MB, thumbnail up to 256 kB, model up to 8 MB, variant image up to 1 MB. The archive is uploaded in 50 MB parts and processed in the background – a big archive takes tens of minutes; keep the page open, progress shows in the log. The temporary ZIP is deleted after the import; only the extracted images and models stay in storage.

2. Archive layout

One folder per item, folder name = code (letters, digits, . _ -, max 40 characters). The archive may have one common root folder (Windows "Send to → Compressed folder" creates one).

catalog.csv                  optional bulk price list (Excel) – overrides product.json
OAK-HALIFAX/                 folder = code
  product.json               item fields (chapter 3)
  image.jpg                  decor: texture; object: preview – png/jpg/webp, max 4 MB
  thumb.jpg                  optional panel thumbnail (≈160 px, max 256 kB)
  model.glb                  3D object only: .glb / .gltf / .kmz / .dae / .obj, max 8 MB
  variants/WHITE.jpg         optional variant images (name = variant code, max 1 MB)
OAK-SB-120/
  …

Flat archive for decors

Decors without models and variants need no folders: catalog.csv + images named by code (OAK-HALIFAX.jpg, OAK-HALIFAX.webp…). The code in the CSV and the file name must match.

SketchUp. A browser cannot display .skp and the import rejects it. Export File → Export → 3D Model → glb (or kmz / dae), or use the plugin furniconf_convert.rb (Window → Extension Manager → Install ExtensionExtensions → Fittle → Convert catalogue): from a folder of CODE/model.skp it creates model.glb, image.jpg, thumb.jpg and the size in product.json. Shrink models over 8 MB (fewer polygons, textures max 1,024 px).

3. product.json

{
  "kind": "model",
  "name": { "en": "Oak sideboard 120", "de": "Kommode Eiche 120", "sk": "Komoda Dub 120" },
  "description": { "en": "Solid oak, 3 drawers, soft close." },
  "category": "Sideboards",
  "size_cm": { "w": 120, "d": 42, "h": 78 },
  "price": 349.00, "currency": "EUR", "vat": 0.23, "price_includes_vat": true, "unit": "ks",
  "url": "https://shop.example/oak-sideboard-120",
  "tags": ["living room", "solid wood"],
  "variants": [
    { "sku": "WHITE", "name": { "en": "white" }, "price": 369.00 },
    { "sku": "BLACK", "name": { "en": "black" }, "price": 369.00, "url": "https://shop.example/oak-sideboard-120-black" }
  ]
}
FieldTypeRequiredNote
kinddecor / floor / tile / modelnowithout kind: a model file → model, otherwise decor
nametext or {lang: text}yes (new item)24 EU languages (en, de, sk, cs, pl, hu…); missing language → en → first available
descriptiontext or {lang: text}nomax 1,000 characters
categorytextnoe.g. "Wood · light", "Sideboards" – categories form the drop-down in the configurator, use the same spelling
finishwood / matt / glossnodecors: surface (default wood)
hex#RRGGBBnoaverage decor colour (fallback until the image loads)
size_cm{w, d, h}yes for modelobject size W × D × H in cm – the model is scaled to it
tile_cm{w, h}yes for tilesize of one tile in cm
usefloor / wall / bothno (tile)floor tile / wall tile / both – the Import floor tiles and Import wall tiles buttons set it automatically
pricenumbernounit price; unit = ks (piece), m2, bm (running metre), bal (pack)
plank_cm{w, h}no (floor)plank size in cm (length × width) – the floor is counted piece by piece following laying rules (below)
pack_m2numberno (floor, tile)m² per pack, e.g. 2.4 – the cart rounds up to whole packs
pack_pcsintegerno (floor, tile)pieces per pack (instead of pack_m2)
currencyEURnodefault EUR
vat0–1noVAT rate, e.g. 0.23
price_includes_vattrue/falsenodefault true (gross price)
urlhttps linknoproduct page in your e-shop ("Order")
tagsarray of textnomax 20
variantsarraynomax 50; each sku (required), name, price, url; image = variants/<sku>.jpg

Prices are shown only in configurators of retailers with the price mode enabled; carpenters never see prices.

Floors, tiles and wall tiles – area, packs and price

The customer enters the room size, picks a floor, floor tiles or wall tiles and sees the required area, the number of packs and the price in the cart:

  1. Floor and wall tiles. The planner lays tiles piece by piece (pattern, grout, windows and doors; an offcut is reused where it fits) → pieces and m² of tiles.
  2. Plank floors (plank_cm). Real laying is simulated: planks run towards the window (without a window along the longer side), 10 mm expansion gap at the walls, end piece of a row at least 20 cm, joints of neighbouring rows offset by at least 40 cm, last row ripped lengthwise (strips are waste). A plank clicks in from one side only, so an offcut from the end of a row cannot be used anywhere – only as the start of a later row, cut end to the wall. Waste comes from these rules, no percentage reserve is added. Floor without plank_cm: room area.
  3. Packs. pack_m2: packs = area ÷ m² per pack, rounded up; pack_pcs: pieces ÷ pieces per pack. Without pack data the exact area or pieces are charged.
  4. Price by unit. m2: paid m² of whole packs × price; bal: packs × pack price; ks: pieces × price.
Example. Room 4 × 3 m, laminate 120 × 20 cm, 2.4 m² per pack, €19.90/m² → 15 rows of 3.98 m → 57 planks = 13.68 m² (area 12.0 m², waste ≈ 12 %) → 6 packs (14.4 m²) → €286.56. Tiles 60 × 60 cm, 3 mm grout, 4 per pack, €28/pack → 35 tiles → 9 packs → €252. The request shows packs, m² and price per line.

4. catalog.csv

Header in the first row, delimiter , or ;, UTF-8 encoding (in Excel "CSV UTF-8"). All columns are optional except sku:

sku;kind;name_en;name_de;name_sk;desc_en;category;finish;hex;price;currency;vat;unit;url;w;d;h;tile_w;tile_h;tags
OAK-SB-120;model;Oak sideboard 120;Kommode Eiche 120;Komoda Dub 120;Solid oak;Sideboards;;;349;EUR;0.23;ks;https://shop.example/sb120;120;42;78;;;living room|solid wood
OAK-HALIFAX;decor;Halifax oak;;Dub Halifax;;Light wood;wood;#C9A87C;;;;;;;;;;;
  • A CSV value overrides product.json – the CSV suits monthly price updates from your system without re-sending models.
  • A row without a folder and files updates an existing item (e.g. price only); a new item also needs an image.
  • Names per language: columns name_xx; separate tags with a vertical bar |.

5. How the import runs

  1. Pick the archive and click Dry run (no writes). The archive is uploaded and checked; the result is a table: will be created / will be updated / skipped / error + reason. Nothing is written.
  2. Fix the errors (chapter 6) and click Import. Upload and processing run in the background; a log line is added for every product. The log can be downloaded.
  3. After the import: new decors wait for approval (the portal shows them as pending), as do updated items whose name/image changed; retailers on a trial see the items in their shop within minutes.
  4. The import history under the form shows every run (dry and real) with a summary and the log.

6. What is checked (reasons in the log)

  • missing name / image / model / size depending on the item kind,
  • image over 4 MB, thumbnail over 256 kB, model over 8 MB, .skp instead of an export,
  • invalid JSON, unknown kind, finish outside wood/matt/gloss, hex not #RRGGBB,
  • price not a number, currency not a 3-letter code, VAT outside 0–1, unit outside ks/m2/bm/bal, bal without pack_m2/pack_pcs,
  • variant without sku, variant image without a matching variant in the JSON,
  • files outside the layout are ignored (listed as "skipped").
Typical mistakes. The code in the CSV does not match the folder/image name (upper/lower case, a space); Excel saved the CSV in another encoding (broken accents – save as "CSV UTF-8"); JSON with a trailing comma or typographic quotes “” instead of ""; a model saved as .skp; textures in a side folder next to .obj (use glb).

7. Rolling an import back

Made a mistake (wrong price list, wrong models)? In the import history the latest real import has a Roll back button: items the import created are deleted with their files; items it changed get their previous data, images and models back (files are versioned, older versions are kept for 30 days). Only the latest real import can be rolled back – if you imported again since, roll back the newer one first. Dry runs need no rollback.