Skip to content
ShopAssist Docs
APIAPI referenceCatalog Push API

Push Products

Upsert products (mode = replace_all runs tombstone products outside the run after the last batch).

POST/v1/stores/{store_id}/catalog/products:batchScope catalog:write

Upsert products (`mode = replace_all` runs tombstone products outside the run after the last batch).

Parameters

Parameters of Push Products
NameInTypeDescription
store_idrequiredpathstring
Idempotency-KeyrequiredheaderstringReplays return the original

Request body (ProductsBatch)

Request body of Push Products
FieldTypeDescription
batch_indexinteger≥ 0 · ≤ 9999
is_last_batchboolean
mode"upsert" | "replace_all"default "upsert"
productsrequiredCatalogProductInput[]CatalogProductInput items (validated individually; invalid items are reported in rejected[])≥ 1 items · ≤ 500 items
products[].attributesCatalogAttributeInput[]
products[].attributes[].coderequiredstring1–128 characters
products[].attributes[].labelrequiredstring1–255 characters
products[].attributes[].valuesrequiredstring[]≤ 100 items
products[].brandstring | null≤ 255 characters
products[].category_external_idsstring[]
products[].description_htmlstring | nullSanitized server-side
products[].description_textstring | null
products[].external_idrequiredstring1–128 characters
products[].handlestring | null≤ 255 characters
products[].imagesCatalogImageInput[]
products[].images[].altstring≤ 500 characters
products[].images[].urlrequiredstringformat uri · ≤ 2048 characters
products[].images[].variant_external_idsstring[]
products[].is_publishedbooleandefault true
products[].product_typestring | null≤ 255 characters
products[].status"active" | "draft" | "archived"default "active"
products[].tagsstring[]
products[].titlerequiredstring1–255 characters
products[].translationsCatalogTranslationInput[]
products[].translations[].description_textstring | null
products[].translations[].localerequiredstring2–35 characters · pattern `^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$`
products[].translations[].titlerequiredstring1–255 characters
products[].translations[].urlstring | nullformat uri · ≤ 2048 characters
products[].urlrequiredstringhttps on a store origin or extra_link_domains (else url_not_allowed)format uri · ≤ 2048 characters
products[].variantsrequiredCatalogVariantInput[]≥ 1 items
products[].variants[].add_to_cart_urlstring | nullformat uri · ≤ 2048 characters
products[].variants[].available_qtyinteger | null
products[].variants[].compare_at_priceMoney | null
products[].variants[].compare_at_price.amountrequiredstringpattern `^-?\d+(\.\d{1,6})?$`
products[].variants[].compare_at_price.currencyrequiredstringpattern `^[A-Z]{3}$`
products[].variants[].external_idrequiredstring1–128 characters
products[].variants[].gtinstring | null≤ 64 characters
products[].variants[].image_urlstring | nullformat uri · ≤ 2048 characters
products[].variants[].is_compare_at_referenceboolean
products[].variants[].is_purchasableboolean
products[].variants[].options{ [key: string]: string }
products[].variants[].pricerequiredMoneyAn amount with its currency (`03` §2.4 `Money`).
products[].variants[].price.amountrequiredstringpattern `^-?\d+(\.\d{1,6})?$`
products[].variants[].price.currencyrequiredstringpattern `^[A-Z]{3}$`
products[].variants[].price_includes_taxboolean
products[].variants[].pricesCatalogPriceInput[]
products[].variants[].prices[].compare_at_priceMoneyAn amount with its currency (`03` §2.4 `Money`).
products[].variants[].prices[].pricerequiredMoneyAn amount with its currency (`03` §2.4 `Money`).
products[].variants[].prices[].price_listrequiredstringpattern `^(currency:[A-Z]{3}|market:[A-Z]{2})$`
products[].variants[].skustring | null≤ 255 characters
products[].variants[].stock_status"in_stock" | "low_stock" | "out_of_stock" | "backorder" | "unknown"
products[].variants[].titlestring | nullDefault: option values joined " / "≤ 255 characters
run_idstringpattern `^[A-Za-z0-9_-]{1,64}$`

Example request

curl -X POST "https://api.shopassist.coec.dk/v1/stores/sto_01j8000000e008000000000000/catalog/products:batch" \
  -H "Authorization: Bearer $SHOPASSIST_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"batch_index":0,"is_last_batch":true,"mode":"upsert","products":[{"attributes":[{"code":"string","label":"string","values":["string"]}],"brand":"string","category_external_ids":["string"],"description_html":"string","description_text":"string","external_id":"string","handle":"string","images":[{"alt":"string","url":"https://shop.example/products/linen-shirt","variant_external_ids":["string"]}],"is_published":true,"product_type":"string","status":"active","tags":["string"],"title":"string","translations":[{"description_text":"string","locale":"da-DK","title":"string","url":"https://shop.example/products/linen-shirt"}],"url":"https://shop.example/products/linen-shirt","variants":[{"add_to_cart_url":"https://shop.example/products/linen-shirt","available_qty":1,"compare_at_price":{"amount":"499.95","currency":"DKK"},"external_id":"string","gtin":"string","image_url":"https://shop.example/products/linen-shirt","is_compare_at_reference":true,"is_purchasable":true,"options":{},"price":{"amount":"499.95","currency":"DKK"},"price_includes_tax":true,"prices":[{"compare_at_price":null,"price":null,"price_list":null}],"sku":"string","stock_status":"in_stock","title":"string"}]}],"run_id":"string"}'

Response 202 (BatchAccepted)

Response of Push Products
FieldTypeDescription
acceptedrequiredinteger≥ 0
rejectedrequiredItemRejection[]
rejected[].errorrequiredItemError`{ code; message }` of a rejected item.
rejected[].error.coderequired"validation_error" | "currency_mismatch" | "duplicate_external_id" | "too_many_variants" | "url_not_allowed"
rejected[].error.messagerequiredstring
rejected[].indexrequiredinteger≥ 0
sync_run_idrequiredstringpattern `^sync_[0-9a-hjkmnp-tv-z]{26}$`
{
  "accepted": 0,
  "rejected": [
    {
      "error": {
        "code": "validation_error",
        "message": "string"
      },
      "index": 0
    }
  ],
  "sync_run_id": "sync_01j8000000e008000000000000"
}

Errors

Every error uses the error envelope; the code field is stable.

  • 400 Bad Request
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not Found
  • 409 Conflict
  • 413 Content Too Large
  • 422 Unprocessable Content
  • 429 Too Many Requests

Last updated on