Skip to content
SyncMyShop

Systems

Salsify integration with your online store: product content from Salsify, kept current

Salsify allows 10,000 API requests an hour per organization, shared by every integration on it, so a full catalog goes through an export run and changes come in through webhooks. We build the integration on your properties and lists, then host and run it.

What Salsify is and who runs it

Salsify is a cloud platform for product information and digital assets, which it calls product experience management. Brands, distributors and retailers use it to keep product content in one place and send it to retailers, marketplaces and their own store. Each customer has its own organization, identified by an org_id that appears in the app URL after /orgs/.

The model has three parts: products, digital assets (images, videos, documents) and properties. A property is an attribute with a data type, such as text, a number or an enumerated value. The organization defines its own properties, and their names are case sensitive: Product Name and product name are two properties. Every product also carries system metadata with the prefix salsify:.

Field What it is What the store integration uses it for
salsify:id value of the property with the product ID role match key, usually the SKU
salsify:system_id permanent internal ID, never changes key that survives a SKU change
salsify:parent_id ID of the parent product variant under a product
salsify:updated_at last update, in UTC reconciliation pass
salsify:version counter, +1 on every saved update compare with the previous run

A product ID cannot start with =, _ or salsify, so an ERP item number that does gets a prefix rule before it goes in.

What connects to Salsify

Salsify owns what a product is: name, descriptions, attributes, translations and images. The ERP owns the item number, price and stock.

Flow Direction Mechanism in Salsify
Full catalog Salsify to store export run, as JSON, JSONL, CSV or XLSX
Changes per product Salsify to store product change webhook
One product on demand Salsify to integration GET /api/v1/orgs/{org_id}/products/{id}
Images and documents Salsify to store digital assets with a URL
Item numbers and base data ERP to Salsify JSON or JSONL import, from FTP or upload

An export run takes a configuration: entity_type (product, digital_asset, attribute, attribute_value or all), a format, a filter such as =list:default, and the properties to include. Watch product_type: the default is leaves, only the products on the lowest level of the hierarchy. An integration that needs parent products to group variants asks for all. How product data moves between systems in general is on the product data page.

How Salsify exposes data

REST API with a token

The API takes and returns JSON. Authentication is an API key, sent as Authorization: Bearer or as the access_token query parameter, or OAuth 2.0. We send the key only in the header, because a URL with a token in it ends up in logs. Every user has an API key with that user's permissions, and the key works until it is regenerated or the user is disabled. The integration runs as its own user, with read access to products, properties and exports and nothing else.

10,000 requests an hour, per organization

Salsify allows each organization 10,000 API requests an hour, whichever user makes them. Requests from the app's own sessions are not counted. Every response carries three headers:

HTTP/1.1 200 OK
x-ratelimit-limit: 10000
x-ratelimit-remaining: 212
x-ratelimit-reset: 1380

x-ratelimit-reset is the number of seconds to the top of the hour, when the counter resets. Over the limit the answer is 429 Too Many Requests until then. Salsify's rate limiting documentation has the full rules.

The arithmetic for a first load of 25,000 products read one by one at 5 requests a second: 10,000 requests take 2,000 seconds, which is 33 minutes 20 seconds. The budget is then gone until the top of the hour, for this integration and for every other one on the organization.

25,000 single-product reads against Salsify's hourly limit of 10,000 requests per organization An integration that reads 25,000 products one by one at 5 requests a second uses the organization's 10,000 requests in 33 minutes and 20 seconds. Every integration on the organization then gets 429 until the top of the hour. The load ends at 11:16:40 after two blocked periods of 26 minutes and 40 seconds. An export run does the same load in a few requests. Single-product GETs at 5 per second 10,000 requests 10,000 requests 5,000 Every integration on the organization 429 until 10:00 429 until 11:00 Export run instead start, status, download: 3+ calls 09:00 10:00 11:00 11:30
The hourly limit is per organization: single-product reads for a full catalog lock out every other integration twice.

The load ends at 11:16:40 after two blocked periods of 26 minutes 40 seconds each. An export run does the same work in a start call, a few status calls and one download. We use exports for every bulk read and keep the hourly budget for webhooks, single reads and retries, as described in API throttling and backoff.

Export runs

POST /api/orgs/{org_id}/export_runs with the configuration returns an export ID and the status running. The integration polls GET .../export_runs/{id} until the status is completed, then downloads the file from the url in that response. The user needs Exports read and manage, Products read, Profile read and manage, and Properties read.

Product change webhooks

A webhook is set up in the app on a list of products: when a product is added, when any property changes, when selected properties change, or when a product is removed. The message holds the products in the export format, their parents in parent_products, and a trigger_type of add, change or remove. A deleted product carries salsify:destroyed_at. Messages are signed with an X.509 certificate and SHA-256, and the integration drops any message whose signature does not verify.

Delivery has three properties that shape the design:

  • A failed delivery is retried 15 times over 48 hours with an exponential backoff.
  • Updates to one product in a short period can be combined into one message, and a change that is quickly reversed may send nothing.
  • Changing the filter of a smart list adds or removes products without any webhook.

Updates to the same product arrive in order; across products there is no order. More on why a webhook is a signal and not a record is in webhooks are not a guarantee.

Where a Salsify integration gets stuck

What goes wrong Cause in Salsify What the integration does
Variant not updated in the store salsify:version of a variant does not change when an inherited value on the parent changes rereads all variants when a parent changes
Old value stays in the store an emptied property is left out of the product treats a missing expected property as empty
Store assortment behind the list smart list filter edited, no webhook reconciliation pass on list membership
Parent products missing product_type defaults to leaves all in the export configuration
Other integrations get 429 the hourly budget is per organization bulk reads through exports, budget tracked per response

Variants and inheritance

A variant has a salsify:parent_id and by default inherits the parent's values. Salsify does not raise the variant's salsify:version when an inherited value changes on the parent. An integration that compares variants on version or date misses a new description or material. We keep a map of parent to variants and reread them when the parent changes. How the store side holds variants is on the variants page.

Empty properties and locales

Salsify stores only properties that have a value. When a property is emptied, its key is missing from the next response, and an integration that updates only the fields it receives leaves the old value in the store. The integration compares against the list of properties it expects and clears a missing one. A localized property holds a value per locale, such as en-US and fr-CA, and the store often uses other codes. The integration records per store which locale feeds which language and what happens when a translation is missing; the field mapping note covers this class of mismatch.

Platforms we integrate with Salsify

The integration is built on your properties, lists and store. What the receiving side needs is on each platform page: Shopify, BigCommerce, Magento, WooCommerce and Shopware. A different PIM is covered on the Akeneo page.

We build the integration for a fixed price, then host, run and monitor it for a monthly fee. Before go-live it runs as a dry run: you see per product which fields and images would land in the store, and nothing changes. Tell us which properties and which store you have, and you hear which exports and webhooks the integration uses and what it takes from your hourly budget.

Frequently asked questions

Is API access included in every Salsify subscription?

No. Salsify's developer documentation says API access is not included in all organizations and depends on the license type. Check it with your Salsify account manager before the build starts. Without API access an integration can work from scheduled channel or export files, without webhooks and with the delay of the schedule.

Do we share the API limit with other integrations?

Yes. The 10,000 requests an hour apply per organization, whichever user or token makes them. A retailer feed or a marketplace integration on the same organization draws from the same budget. Requests from people working in the Salsify app do not count. The integration reads x-ratelimit-remaining on every response and moves bulk work to an export when the budget runs low.

Should the integration use an API key or OAuth 2.0?

For an integration that runs for one organization, an API key on a dedicated integration user. The key does not expire until someone regenerates it, and it has the permissions of that user, so the user gets only what the flows need. The key stops working when the user is disabled, which is why it should not belong to an employee.

How fast does a change in Salsify reach the store?

With a product change webhook, as soon as Salsify sends it. The message holds the product itself, so no extra read is needed. Two quick changes can arrive as one message with the last value, and a change that is reverted quickly may send nothing, so a reconciliation pass on salsify:updated_at runs next to the webhooks.

Can Salsify be the source for price and stock?

A property can hold any value, including a price or a stock count. In most setups the ERP owns price and stock and sends them to the store directly, and Salsify owns the product content. One owner per field keeps two systems from overwriting each other.

Tell us what you need

Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.

  • You know the price and the timeline before you commit to anything
  • We work out the connection that takes the work off your hands
  • We handle the build, hosting, monitoring and maintenance
  • Your team has less information to retype and fewer discrepancies to chase

Suppliers, products, orders per day, a rough estimate is fine.

Or email directly: carsten@syncmyshop.com