Skip to content
Bloomcount API
Esc
navigateopen⌘Jpreview
On this page

Sync a catalogue

Push suppliers, colours and products from another system, and keep them in step.

A catalogue sync writes in a fixed order, because products reference the other two: suppliers by id, colours by name.

Create the suppliers

A variant’s supplierIds must name suppliers that already exist, so send those first and keep the ids you get back.

curl -X POST "https://app.bloomcount.com/api/v1/suppliers" \
  -H "Authorization: Bearer bloomcount_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Marilliam Flowers", "contactEmail": "orders@marilliam.example" }'

Suppliers are never deleted, because products keep pointing at them. Retire one with POST /api/v1/suppliers/{id}/archive, which leaves history intact and stops it taking new lines, and bring it back with unarchive.

Check the colours

Variants carry colours by name, not by id, so a name that does not exist is simply a tag nothing else shares. Read the palette first and create what is missing:

curl "https://app.bloomcount.com/api/v1/colors" \
  -H "Authorization: Bearer bloomcount_..."
{
  "items": [
    { "colorId": "col_...", "name": "Blush", "hex": "#f4c2c2", "isPreset": true }
  ]
}

Preset colours cannot be edited or deleted; your own can. Categories work the same way and are also referenced by name from a product’s category.

Upsert the products

One call carries up to 500 rows, each a product with one variant. Omitting productId creates; supplying it updates, patching only the fields you send.

curl -X POST "https://app.bloomcount.com/api/v1/products" \
  -H "Authorization: Bearer bloomcount_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: catalogue-2026-09-06-batch-1" \
  -d '{
    "items": [
      {
        "name": "Pink Mondial",
        "category": "Roses",
        "productType": "flower",
        "variant": {
          "name": "50cm",
          "stemLength": 50,
          "unitsPerPack": 10,
          "colors": ["Blush"],
          "supplierIds": ["sup_..."],
          "supplierMinPacks": [{ "supplierId": "sup_...", "minPacks": 5 }]
        }
      }
    ]
  }'

The response reports each row separately:

{
  "results": [
    { "index": 0, "action": "created", "productId": "prod_...", "variantId": "var_..." }
  ],
  "errors": []
}

A row that fails lands in errors with its index and a code, and the rest of the batch still lands. That is the whole point of the bulk shape: one bad supplier reference does not cost you the other 499 rows.

Retire what has gone

Deletes are per resource, not part of the batch:

curl -X DELETE "https://app.bloomcount.com/api/v1/products/prod_..." \
  -H "Authorization: Bearer bloomcount_..."

If the product is on an event, this returns 409 with product_on_event_items:3 rather than quietly removing those lines. Add ?force=true when removing it along with its history is what you mean. Deleting a single variant works the same way, at DELETE /api/v1/products/{id}/variants/{variantId}.

Running it again

Two things make a repeated sync safe.

Send an Idempotency-Key per batch. A replay within 24 hours returns the first response verbatim instead of writing again, so a timeout you retry cannot double-create.

Update by id, not by name. Keep your own map from your system’s identifier to the prod_/var_ ids the first sync returned. Matching on name instead means a rename in either system creates a duplicate.

Was this page helpful?