One product, four prices. The Allegro listing (Poland's largest marketplace) says 149 zł, Apilo says 139 zł, the supplier's file says 112 zł net, and the shop admin says 145 zł, because somebody last touched it in the spring. The numbers are made up, the situation is not. Every one of those prices was true at some point. The question is which one is true today, and who in the company gets to decide that.
Over the past two weeks we did exactly three things like this in one project: own-brand prices pulled straight from Allegro listings through the API, supplier product prices calculated from their file using the rule “file price minus 2 percent”, and tidying up products imported from Apilo so that the same model in five sizes becomes one product with variants instead of five separate cards. Three tasks, one problem underneath: the same piece of information lived in several places and none of them was marked as binding.
This post is about that marking. Not about a tool, but about a decision you make once and then write into code: where the price comes from, where stock comes from, where the name comes from, and what happens when the sources disagree.
Where the price actually comes from
In a trading company that sells the same product on Allegro and in its own shop, the price usually lives in four places at once:
- Allegro listings. This is where the price is most alive, because it reacts to competitors, commissions and promotions. In many companies it is the only place where somebody really watches the margin.
- Apilo or another OMS. An order management system keeps its own product catalogue, because it has to: it ties sales channels, the warehouse and shipping together. Prices and names drop into it from the marketplaces and stay in whatever shape they arrived in.
- The supplier's file. A CSV or XLSX arrives by e-mail once a week, once a month, or “whenever something changes”. It has purchase prices, sometimes suggested retail prices, sometimes the supplier's own stock. It almost never uses the same item codes as your warehouse.
- The shop admin. Here the price is set by hand, and here it stays wrong the longest, because nobody gets a notification that it has drifted.
There is usually a fifth place: the ERP, most often Subiekt in Polish companies. It knows what the product was bought for and how much of it physically exists, but it knows nothing about the Allegro commission or about the promotion that started on Friday.
Each of those places shows a different number, and each has a good reason for it: in one, prices changed yesterday; the second is three weeks old; in the third, somebody fixed a name by hand and changed the price along the way. The drift does not come from anybody's mistake, it comes from the number of places where the same piece of data lives a life of its own.
Who wins the conflict: a source of truth for price, stock and name separately
The most common mistake at this stage is trying to pick one system for everything. “From today Apilo is the truth” sounds like order and falls apart in the first week, because Apilo knows nothing about your margin, and Allegro knows nothing about a product that sits in the warehouse and is not listed.
A source of truth is chosen separately for each field. Not “for the product”, but for the price, the stock level, the name, the variants and the purchase price, one by one. This is how we usually lay it out:
| Field | Source of truth | Why there | The other systems |
|---|---|---|---|
| Retail price, own products | Allegro listings | That is where the price is watched most closely and changes fastest | Receive it and do not change it |
| Retail price, supplier products | Supplier file plus a rule | It changes with the supplier's price list, not by hand | Calculate from the rule, store no exceptions |
| Purchase price and margin | The ERP (e.g. Subiekt) | That is where the purchase documents are, and margin without them is just a feeling | Show the result, do not set it |
| Stock level | The ERP or the OMS, exactly one of them | Only one place may take goods off the shelf | Receive the level after every change |
| Name, description, photos | The shop admin | This is content for the buyer and for Google, not operational data | Marketplace names never overwrite the shop |
| Variants and sizes | The shop catalogue | One product with variants, even if the source sends a flat list | Map by variant code, not by name |
Scroll the table sideways
With that layout a conflict stops being a conflict. If the price in the shop admin differs from the price on the Allegro listing, it is not a dispute for a human to settle, it is an error to be fixed in one direction. The integration knows which one.
Typical drift: sizes, marketplace names, margin off an old price
Three kinds of drift come back in almost every project where the catalogue has more than one source. All three look like trivia until you have to clean them up across a few thousand items.
A separate product for every size. A jacket in five sizes arrives from the marketplace or the OMS as five independent products, because there every variant is a separate listing. In the shop it should be one product with a list of sizes. The difference is visible to the buyer: five cards instead of one break listings, search and related-product carousels. Merging by name does not work, because the names are inconsistent. Mapping by variant code or by EAN does work, with a rule for what to do with an item that has no code.
Names straight from the marketplace. An Allegro listing title is optimised for Allegro's own search engine: it is full of keywords, parameters and abbreviations. In the shop it is read by a human and by Google. If the name from the operational source overwrites the name in the shop, every sync undoes the work put into the description. The name and the price may flow from different sources, and that is fine.
Margin calculated off an old price. A rule like “the supplier file price minus 2 percent” is simple, as long as everyone knows what those 2 percent are taken from. The price in the new file, or the one currently in the shop? Net or gross? And what about an item that is missing from the new file: does it stay, or does it drop out of the offer? The questions sound trivial, and the answers differ by a few percent of margin across the whole catalogue. That is why the rule is written as code with a test, not as a note in an e-mail.
How often to refresh, and what to do when a source goes quiet
The frequency is chosen per source, not for the whole integration. The supplier's file arrives once a week, so checking it more often adds nothing. Stock moves within hours, so once a day is too rarely. For us it usually looks like this: stock every few minutes, prices every hour, the supplier file as soon as it arrives, the catalogue and descriptions whenever somebody changes them.
The other half of the job is the behaviour when a source does not answer, or answers with something odd. This is the difference between an integration and a script that worked once:
- 01Silence does not mean zero. An empty API response, a zero-byte file, a timeout: that is missing data, not zero stock. An automation that zeroes stock levels in that situation takes the whole shop out of sale within fifteen minutes.
- 02Validation before writing. A price of 0, a price ten times higher than the previous one, 90 percent of the catalogue changed in a single run: these are signals that the source sent garbage or changed its format. Such a run goes to approval, not to production.
- 03Quarantine for single items. One item without a variant code must not stop the import of the rest. It goes onto a list for a manual decision, everything else comes in normally.
- 04Idempotence. The same file loaded twice has to produce the same result, not the same discount twice. With prices calculated from a rule, this is the first thing that hurts when it is missing.
- 05Change history. Who changed the price, when, and on what basis. Without it you cannot reconstruct where a strange number came from, nor show price history for a promotion.
- 06An alert to a human. Not “a line in a log file”, but a message where somebody is actually looking, with specifics: this source, this run, this many items held back.
At the home-appliance wholesaler, where we built an integration hub with Subiekt nexo, this was exactly the part that mattered most: an order resent after a loss of signal is recognised as a duplicate, so only one document ends up in Subiekt. The full write-up is in the B2B wholesaler case study.
The time math: 500 and 5,000 SKUs
Now the numbers. Not from your company, but from a model I built on four assumptions. All of them are yours to swap, and all of them are deliberately cautious:
- 12 percent of the catalogue changes price or stock in one of the sources each month,
- every extra source adds 50 percent more changes to reconcile, because the same item has to be checked in several places,
- 2 minutes to find and fix one item by hand,
- 15 percent of stale items turn into a case to handle (a buyer's question, a cancellation, a correction), at 5 minutes each.
With three sources and two typical manual update rhythms, the table comes out like this:
| Catalogue and rhythm | Items with a stale price | Share of catalogue | Hours a month |
|---|---|---|---|
| 500 SKUs, synced once a week | approx. 14 | 2.8 % | approx. 4 h |
| 500 SKUs, synced once a month | approx. 60 | 12 % | approx. 5 h |
| 5,000 SKUs, synced once a week | approx. 140 | 2.8 % | approx. 42 h |
| 5,000 SKUs, synced once a month | approx. 600 | 12 % | approx. 48 h |
Scroll the table sideways
Two things are worth taking from this. First: at 5,000 SKUs, syncing prices alone is at least a quarter of a full-time job, before handling any of the consequences. Second: syncing less often does not save time, it swaps hours of copying for stale prices in the shop. At 500 SKUs the difference between weekly and monthly is one hour of work, but four times as many wrong prices.
Below is the same model with your numbers. Set the SKU count, tick your sources and your rhythm, and then fill in the source of truth table: that is the most valuable part here.
- Simulator
Price list drift
Enter your SKU count, tick your sources and how often you sync them by hand.
500
Where your prices and stock come from
Tick every place where this data lives.
How often you sync by hand
Estimate under these assumptions
14
items with a stale price or stock level at any given moment
2.8% of the catalogue
4.2 h / mo
hours a month spent on fixes
That is 4 h of copying alone (120 changes a month) and 0.2 h on the consequences: complaints, cancellations, corrections.
3 sources for the same price mean somebody decides every day which one is right. Fill in the table below so that decision is written down once instead of being made again and again.
Your source of truth table
One winning source per field. Everything else is read only.
4 of 4 fields have a source of truth
Assumptions to swap for your own: 12 percent of the catalogue changes price or stock in a month, every extra source adds 50 percent more changes to reconcile, 2 minutes to fix one item, 15 percent of stale items turn into a case that takes 5 minutes to handle.
The simulator does not know your company and does not pretend to. It shows how the drift behaves when three things change: the size of the catalogue, the number of sources and the update rhythm. If you want a similar calculation for manually re-typing orders, we have one in a separate post on the cost of handling Allegro by hand.
- sources for the same price in a typical shop
- 3
- a month at 5,000 SKUs (assumptions)
- approx. 42 h
- fields that need a source of truth
- 6
What we build for our clients
The scope of an implementation like this is fairly repeatable, whether the source is Allegro, Apilo, a supplier file, or all three at once:
- 01An inventory of sources: what lives where, who changes it and how often. At this stage there is usually one source nobody remembered.
- 02A source of truth table per field, signed off by the person responsible for pricing. That is a business decision, not a technical one.
- 03Product mapping: EAN, manufacturer code, variant code, and for items with none of those, an explicit rule and a list for manual decisions.
- 04Pricing rules in code, with tests: markups, rounding, net and gross prices, exceptions for specific product groups.
- 05Variant merging: one product with sizes in the shop, even if the source sends a flat list of listings.
- 06Validation, quarantine, change history and alerts, that is everything described above in the section on silent sources.
- 07A preview for a human: what this run is about to change, before the change reaches the shop.
A typical implementation is 2-3 weeks from kick-off to production, and a larger project is split into stages of 2-3 weeks, each with a working piece at the end. That is how we did it at the home-appliance wholesaler with four price lists and 1,293 products, where a tablet app, a B2B portal and Subiekt nexo now work on the same data. At the workwear store the application publishes listings directly through the Allegro REST API and calculates margin after commission and shipping before publication; the road to production took 3 weeks.
What we do not promise. An automation does not replace a pricing decision: it executes a rule somebody in the company agreed on, and it is only as good as that rule. We do not promise order in the catalogue either, if the same product has three different item codes in three systems and nothing connects them; then the first stage is mapping, and that is work somebody on your side has to take part in. And we do not pretend a custom integration always beats an off-the-shelf tool: with one account, one price list and standard rules, a subscription integrator will do, and we will say so plainly. More about how we approach implementations like this is on our process automation page.
If it is worth doing, the next step is an audit for PLN 699 net: a few days of our work and an implementation document with the source of truth table, the mapping, the scope, the risks, a fixed price and a deadline. The full amount is deducted from the implementation price.




