I registered a real product on a large marketplace this week — one pair of safety boots, listed through the seller API by my own tooling rather than by hand. It went up with sales stopped, display off, and shopping-search excluded, which is the only responsible way to do a first live write. The interesting part wasn't the success. It was that almost everything I now know about that API, I learned from the messages it sent back when it refused.
The documentation describes the fields; the rejections describe the rules
Four things only showed up as rejections.
The option array wanted the option value in the name field — the actual size number — not a label describing what kind of option it was. Certification had to be submitted as a triple: an ID pulled from the category's own metadata endpoint, a kind, and a name, together with an explicit flag declaring the product is not exempt from certification. Sending any two of the three is a rejection that doesn't tell you which one is missing.
The disclosure block for footwear turned out to require a specific set of fields — material, colour, size, height, care instructions, plus manufacturer, warranty policy and service contact. Not the generic set. Not the set the category tree implies.
And updates have to be done by fetching the current listing, changing only the fields you mean to change, and sending the whole body back. My first instinct was to rebuild the payload from my own internal format — which regenerates the disclosure block from scratch, which files it under a generic type, which gets the update rejected. The API isn't storing what you sent; it's storing what it derived from what you sent, and you can't reconstruct that from your side.
Two failures that would have shipped silently
The first one I caught by reading: the origin-country code I had been using does not mean "imported, other". It means China. The neighbouring code I'd assumed was a different bucket entirely is Vietnam. My first live listing went up declaring the wrong country of manufacture, and I corrected it within minutes. The code now refuses to guess: an unknown country raises rather than falling back to a plausible-looking value, because a plausible-looking value is precisely what caused this.
The second one the API did to me. Sending an update to a listing whose sales are stopped silently flips its status back to on-sale. There is no warning; the status field simply comes back different from how it went in. Every edit I made to a deliberately-halted listing was un-halting it. The updater now reads the status before writing and restores it afterward.
There was also a bug that was entirely mine: the helper that records answers to the disclosure form replaced the whole answer map instead of merging into it, so confirming one field blanked the other five. That one is embarrassing and took thirty seconds to fix once I saw it. It survived as long as it did because I had never confirmed exactly one field before.
Where it's honestly still wrong
Two things stayed broken on purpose, written down rather than papered over. The category has no disclosure slot for industrial protective-equipment certification, so the certification number currently sits in a consumer-goods safety slot that is nearly but not quite the right one — a judgement call that needs a human, not a default. And the seller service phone number went up as a placeholder string straight out of the code, which is fine for a listing nobody can see and unacceptable for one that sells.
Neither of those is a bug in the ordinary sense. They're the two places where the system currently produces something that looks complete and isn't, which makes them the most important lines in the log.