I was at payever for two months. February and March 2020, which you may recognize as the two months directly before the pandemic locked everything down and everyone’s plans changed. Short tour, specific work. This is that work.

payever builds e-commerce infrastructure — a platform that lets merchants manage their sales across multiple channels from a single product. The specific problem I was handed: backend microservices for integrating with Mobile.de, Amazon.de, and eBay. Three marketplaces. Three wildly different data models. One unified domain representation that the platform could work with consistently.

How many engineers have you talked to who can describe Mobile.de’s vehicle listing API from firsthand experience? Right.

Three marketplaces, three different worldviews

The most important thing to understand about marketplace integration is that each marketplace is not just a different API. It is a different conceptual model of what commerce means.

Amazon thinks in terms of catalog and inventory separately. A product has an ASIN, which is Amazon’s canonical identifier for a thing that exists in the world. Your listing is not the product — it is your offer to sell a product that Amazon already knows about. This distinction has deep implications for how you model updates: when you change a price, you are updating your offer. When you change the product description, you may be trying to update Amazon’s canonical record of what the product is, which Amazon has strong opinions about. The feed-based update flow (MWS at the time, now SP-API) is asynchronous and acknowledgment-based. You submit a feed, you get a submission ID, you poll for results. Error handling is not a simple HTTP status code; it is a structured feed result document that you have to parse.

eBay is more like a direct auction/listing model. You own your listing entirely — there is no catalog disambiguation layer. This sounds simpler and it is, in some ways; the tradeoff is that your listing is an island and you’re responsible for its complete data. The integration complexity shifts to the order flow: eBay’s order model has its own concept of buyer messages, feedback, dispute resolution, and return initiation that has to be mapped onto whatever the platform’s internal order model looks like.

Mobile.de is the interesting one to describe at a dinner party, because almost nobody outside Germany knows it, and almost nobody in software has worked with it directly. It is Germany’s dominant used-car marketplace. The inventory model is highly vertical — a vehicle listing has make, model, year, trim, mileage, VIN, a specific classification taxonomy for condition, and a set of searchable attributes (fuel type, transmission, emissions class) that matter in the German market in ways that a generic e-commerce platform does not natively understand. The API is well-documented but the conceptual model is alien to anyone who has only worked with horizontal retail integrations.

The unified domain model problem

The platform’s job is to give a merchant a single interface to manage all of this. Which means the backend’s job is to have a single internal domain model that can faithfully represent a listing on all three platforms and round-trip updates between them.

This is where it gets genuinely hard. A “product” in your internal model has to carry enough information to:

  • Be submitted to Amazon as a feed entry against a known ASIN, or trigger a new product creation request if no ASIN exists
  • Be listed on eBay with full ownership of the listing data, including category, item specifics, and shipping policy
  • Be listed on Mobile.de with the correct vehicle taxonomy fields that neither Amazon nor eBay need at all

The naive approach is a giant product schema with every field from every marketplace. This is wrong. The fields are not just different — they are semantically different. “Condition” on eBay (New, Used, For parts or not working, etc.) is not the same concept as vehicle condition on Mobile.de, which has its own grading vocabulary. A unified model that tries to flatten these differences produces a schema that lies.

The correct approach is a core domain model that carries the fields that are genuinely universal (title, price, inventory count, media), with marketplace-specific extensions that are typed separately and stored alongside the core record. When you publish to a marketplace, you compose the core record with the appropriate extension. When you receive an update from a marketplace, you decompose it back. MongoDB’s document model is well-suited for this because the extension fields vary by marketplace and do not have a fixed schema that would work well in a relational table.

NestJS as the seam

The service layer was NestJS, which is TypeScript on Node.js with Angular- inspired module organization. For integration work like this, the module boundaries are genuinely useful: the Amazon module owns the Amazon wire format, the eBay module owns the eBay wire format, and the core product module owns the domain model. The dependency direction is clear. Nothing in the Amazon module depends on how eBay represents a listing.

RabbitMQ handled the async work: marketplace feeds that take time to process, order notifications inbound from each marketplace, inventory updates that need to fan out to all active channels when a merchant changes a price. The exchange routing here was straightforward — one exchange per marketplace for inbound events, one exchange for internal product updates that fans out to all enabled channel publishers. The publishers are the modules that know how to translate the internal update into the marketplace-specific wire format.

Eight weeks and what they’re worth

Two months is not a lot of time, and I’m not going to pretend the integration was complete. What we shipped in that window was the core product push path and the inbound order sync for all three marketplaces. The returns flow, the messaging integration, the full error reconciliation loop — that was roadmap.

What two months is enough time for is learning the domain deeply enough to have useful opinions about it. I know what Mobile.de’s vehicle taxonomy looks like from the inside. I know what Amazon’s asynchronous feed acknowledgment flow looks like when a feed fails validation. I know how eBay’s category-specific item specifics requirements can make or break whether a listing goes live. These are not abstract architectural concepts — they are the specific failure modes that were happening in the logs when I was reading them.

This is the kind of integration archaeology that takes most engineers longer than two months to develop opinions about, because most engineers never work with all three of these systems at the same time. The compressed timeline forced clarity about what mattered and what was incidental complexity.

I’ve been putting integration discipline into Fulcrum: the same thinking about typed contracts between domains, stable event schemas, and composable adapters for external systems applies directly to agent orchestration. The problems rhyme even if the domain is different. And unlike the payever engagement, the timeline on Fulcrum is not two months.