Guide chapters
Integrating seller shops
The problem#
A seller who already sells somewhere will not type the catalogue in a second time. From their side it is one click. From the platform side it is the moment the same product starts existing in two systems, each with its own price, stock level and edit history.
The whole difficulty of integration comes down to one question, asked separately for every field: which system is right when the two disagree.
The maturity ladder#
You do not start with synchronisation. Each rung is cheap and solves a real problem before the next one appears.
| Stage | When it is enough | What it adds |
|---|---|---|
| Manual entry | a dozen sellers, a small catalogue | nothing, and that is the point |
| File import | a seller with hundreds of products | column mapping, validation, an error report |
| One-off API import | a seller has a shop and will not export | authentication, identifier mapping |
| Stock synchronisation | the same goods sell in two places | change listening, a queue, error handling |
| Continuous synchronisation | the catalogue lives on the seller side | conflict detection, source-of-truth rules |
Minimum version#
A first integration needs four things, and none of them is synchronisation.
- A connection: the record that this seller attached this shop, with credentials kept apart from the rest of the data.
- Identifier mapping: a table tying your record to the source record, at variant level rather than product level.
- An import job with a visible state: how many items, how many passed, how many failed and why.
- A disconnect that does not delete imported products, only breaks the link.
What not to build yet#
- A bespoke connector written from scratch for each provider. The second provider should land in the same layer as the first.
- Two-way synchronisation. Start with one direction and one kind of data.
- A conflict resolution screen, before you have seen which conflicts actually occur.
- Syncing descriptions and images. That is usually data you want to keep on the platform side.
Plan ahead#
Source of truth per field, not per integration#
There is no single answer to who wins. A typical split: stock on the seller shop side, price and description on the platform side, because the platform owns presentation and promotions. What matters is that the split is a recorded rule rather than a consequence of which write arrived last.
Idempotency from the first version#
Every synchronisation operation needs a key that lets you recognise it has already happened. External systems send notifications several times, out of order and sometimes an hour late. Without a key, the first repeated notification duplicates a product or rolls back a stock level.
A queue rather than inline calls#
Import and synchronisation should go through a queue with retries rather than happening inside an HTTP request. This is not a performance optimisation; it is the condition for a provider outage not ending in lost data.
Three queue behaviours are easy to skip at the start and expensive to add later: growing gaps between retries, switching a provider off after a run of failures instead of hammering it in a loop, and somewhere for the things that could not be processed to land.
Triggers#
- a second seller asks for the same kind of shop as the first;
- a seller attaches a second shop to the same account;
- the first sale of goods that were already out of stock in the source shop;
- an import takes long enough for somebody to ask whether it has hung;
- the first conflict where your price and the seller price differ during a promotion.
Next stage#
After the second trigger: separating the connection from the seller, because one seller may have several. After the third: stock synchronisation, still one-way. After the fifth: explicit conflict detection with an operator decision, before you build automatic resolution.
Common mistakes#
| Assumption | Why it costs |
|---|---|
| "One seller means one connection." | A second shop from the same seller forces a model rebuild. |
| "A notification arrives once." | Repeats duplicate products or roll back stock levels. |
| "Sync everything, we already have access." | Descriptions and images come back as overwrites of platform-authored content. |
| "Disconnecting deletes the products." | A seller loses their catalogue when switching shops, and orders lose context. |
| "We will retry immediately." | A provider having an outage gets a flood of requests and blocks the account. |
What works in practice#
On integrations, what mattered most was putting every provider behind one execution layer instead of writing a separate integration each time. Platforms differ in how they authenticate and in the shape of their data, but the queue, the retries, the idempotency and the handling of repeated notifications are shared. Work on a new provider then comes down to what actually makes it different, rather than rebuilding the whole mechanism again.
The second thing: a disconnect that breaks the link rather than deleting data. A seller may switch shops, lose access or want to reconnect later, and a catalogue wiped on disconnect cannot be recovered.
Checklist#
- A connection is its own entity, and a seller can have more than one.
- Identifier mapping exists at variant level.
- For every synchronised field, the source of truth is settled.
- Every operation has an idempotency key, and received notifications have a ledger.
- Synchronisation runs through a queue with growing retry gaps.
- Disconnecting breaks the link rather than deleting products.
I design multi-vendor platforms with onboarding, payments, moderation, and operational workflows.
Explore marketplace development